[DEV] add a system for stadard user global config saving

This commit is contained in:
Edouard DUPIN 2013-05-28 21:18:45 +02:00
parent 3f74842f8e
commit c2b7cedb8c
13 changed files with 351 additions and 29 deletions

206
sources/ewol/UserConfig.cpp Normal file
View File

@ -0,0 +1,206 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license BSD v3 (see license file)
*/
#include <ewol/UserConfig.h>
#include <ewol/eObject/EObjectManager.h>
#include <etk/os/FSNode.h>
#include <ewol/debug.h>
class UserConfig : public ewol::EObject
{
private:
etk::Vector<ewol::EObject*> m_list;
etk::UString m_fileName;
public:
UserConfig(void) : m_fileName("USERDATA:generalConfig.xml")
{
m_static = true; // Note : Set the object static notification( Must be set or assert at the end of process)
};
~UserConfig(void) { m_list.Clear(); };
etk::Vector<ewol::EObject*>& List(void) { return m_list; };
etk::UString& FileName(void) { return m_fileName; };
void OnObjectRemove(ewol::EObject * _removeObject)
{
for( int32_t iii=m_list.Size()-1 ; iii>=0 ; iii--) {
if (m_list[iii] == _removeObject) {
m_list.Erase(iii);
}
}
};
};
static UserConfig& l_obj(void)
{
static UserConfig s_obj;
return s_obj;
}
void ewol::userConfig::Init(void)
{
}
void ewol::userConfig::UnInit(void)
{
}
const ewol::EObject* ewol::userConfig::GetUserConfig(const etk::UString& _name)
{
if (_name == "") {
return NULL;
}
for (int32_t iii=0; iii<l_obj().List().Size() ; iii++) {
if (l_obj().List()[iii] != NULL) {
if (l_obj().List()[iii]->GetName() == _name) {
return l_obj().List()[iii];
}
}
}
return NULL;
}
void ewol::userConfig::AddUserConfig(ewol::EObject* _newConfig)
{
if (_newConfig == NULL) {
return;
}
for (int32_t iii=0; iii<l_obj().List().Size() ; iii++) {
if (l_obj().List()[iii] != NULL) {
if (l_obj().List()[iii] == _newConfig) {
return ;
}
}
}
l_obj().List().PushBack(_newConfig);
}
void ewol::userConfig::SetConfigName(const etk::UString& _fileName)
{
l_obj().FileName() = _fileName;
}
bool ewol::userConfig::Load(void)
{
etk::FSNode file(l_obj().FileName());
if (file.Exist()==false) {
EWOL_ERROR("Can not load the file : " << l_obj().FileName());
return false;
}
// allocate the document in the stack
TiXmlDocument XmlDocument;
int32_t fileSize = file.FileSize();
if (0==fileSize) {
EWOL_ERROR("This file is empty : " << file);
return false;
}
if (false == file.FileOpenRead()) {
EWOL_ERROR("Can not open the file : " << file);
return false;
}
// allocate data
char * fileBuffer = new char[fileSize+5];
if (NULL == fileBuffer) {
EWOL_ERROR("Error Memory allocation size=" << fileSize);
return false;
}
memset(fileBuffer, 0, (fileSize+5)*sizeof(char));
// load data from the file :
file.FileRead(fileBuffer, 1, fileSize);
// close the file:
file.FileClose();
// load the XML from the memory
XmlDocument.Parse((const char*)fileBuffer, 0, TIXML_ENCODING_UTF8);
TiXmlElement* root = XmlDocument.FirstChildElement("config");
if (NULL == root ) {
EWOL_ERROR("(l ?) main node not find: \"config\" in \"" << file << "\"");
if (NULL != fileBuffer) {
delete[] fileBuffer;
}
return false;
}
for(TiXmlNode * pNode = root->FirstChild();
NULL != pNode;
pNode = pNode->NextSibling() ) {
if (pNode->Type()==TiXmlNode::TINYXML_COMMENT) {
// nothing to do, just proceed to next step
} else {
bool elementFound = false;
for (int32_t iii=0; iii<l_obj().List().Size() ; iii++) {
if (l_obj().List()[iii] != NULL) {
if (l_obj().List()[iii]->GetName() == pNode->Value()) {
l_obj().List()[iii]->LoadXML(pNode);
elementFound = true;
break;
}
}
}
if (elementFound==false) {
EWOL_ERROR("(l "<<pNode->Row()<<") node not suported : \""<<pNode->Value());
}
}
}
if (NULL != fileBuffer) {
delete[] fileBuffer;
}
return true;
}
#define MAX_SAVING_FILE_HISTORY (9)
bool ewol::userConfig::Save(void)
{
// step 1 : Move the file to prevent writing error
//Get the first oldest save :
for (int32_t iii=MAX_SAVING_FILE_HISTORY-1; iii>0 ; iii--) {
if (true==etk::FSNodeExist(l_obj().FileName()+"-"+iii) ) {
etk::FSNodeMove(l_obj().FileName()+"-"+iii,l_obj().FileName()+"-"+(iii+1));
}
}
if (true==etk::FSNodeExist(l_obj().FileName()) ) {
etk::FSNodeMove(l_obj().FileName(),l_obj().FileName()+"-1");
}
// basic create file:
etk::FSNode myNode(l_obj().FileName());
// create basic folders ...
myNode.Touch();
etk::UString tmpCompleateName = myNode.GetFileSystemName();
// step 2 : save the file
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "UTF-8", "");
doc.LinkEndChild(decl);
TiXmlElement * ElementBase = new TiXmlElement("config");
doc.LinkEndChild(ElementBase);
for (int32_t iii=0; iii<l_obj().List().Size() ; iii++) {
if (l_obj().List()[iii] != NULL) {
if (l_obj().List()[iii]->GetName().Size() != 0) {
TiXmlElement * element = new TiXmlElement(l_obj().List()[iii]->GetName().c_str());
if (NULL != element) {
l_obj().List()[iii]->StoreXML(element);
ElementBase->LinkEndChild(element);
}
}
}
}
//Save Document
doc.SaveFile( tmpCompleateName.c_str() );
EWOL_DEBUG("Save in file : " << tmpCompleateName);
// step 3 : Remove oldest save
return true;
}

32
sources/ewol/UserConfig.h Normal file
View File

@ -0,0 +1,32 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license BSD v3 (see license file)
*/
#ifndef __EWOL_USER_CONFIG_H__
#define __EWOL_USER_CONFIG_H__
#include <etk/types.h>
#include <etk/Stream.h>
#include <ewol/eObject/EObject.h>
namespace ewol
{
namespace userConfig
{
void Init(void);
void UnInit(void);
const ewol::EObject* GetUserConfig(const etk::UString& _name);
void AddUserConfig(ewol::EObject* _newConfig);
//void RmUserConfig(ewol::EObject* _newConfig); // note : To remove user config ==> just destroy it ==> simple ..
void SetConfigName(const etk::UString& _fileName="USERDATA:generalConfig.xml");
bool Load(void);
bool Save(void);
};
};
#endif

View File

@ -104,7 +104,8 @@ void ewol::EObjectMessageMultiCast::AnonymousSend(const char* const _messageId,
const char* const ewol::EObject::configName = "name";
ewol::EObject::EObject(void)
ewol::EObject::EObject(void) :
m_static(false)
{
static int32_t ss_globalUniqueId = 0;
// note this is nearly atomic ... (but it is enough)

View File

@ -48,6 +48,8 @@ namespace ewol {
public:
// Config list of properties
static const char* const configName;
protected:
bool m_static; //!< set this variable at true if this element must not be auto destroy (exemple : use static object)
private:
int32_t m_uniqueId; //!< Object UniqueID ==> TODO : Check if it use is needed
etk::Vector<EventExtGen*> m_externEvent; //!< Generic list of event generation for output link
@ -63,6 +65,12 @@ namespace ewol {
*/
virtual ~EObject(void);
/**
* @brief Get the static status of the EObject ==> mark at true if the user set the object mark as static allocated element ==> not auto remove element
* @return true if it might not be removed ==> usefull for conficuration class
*/
bool GetStatic(void){ return m_static; };
/**
* @brief Get the UniqueId of the EObject
* @return the requested ID

View File

@ -35,13 +35,18 @@ void ewol::EObjectManager::UnInit(void)
EWOL_DEBUG("==> Un-Init EObject-Manager");
RemoveAllAutoRemove();
EWOL_INFO(" Remove missing user widget");
while(0<m_eObjectList.Size()) {
if (m_eObjectList[0]!=NULL) {
EWOL_WARNING("Un-INIT : Remove EObject type=\"" << m_eObjectList[0]->GetObjectType() << "\"");
delete(m_eObjectList[0]);
m_eObjectList[0] = NULL;
int32_t iii=0;
while(iii<m_eObjectList.Size()) {
if (m_eObjectList[iii]!=NULL) {
if (m_eObjectList[iii]->GetStatic() == true) {
iii++;
} else {
EWOL_WARNING("Un-INIT : Remove EObject type=\"" << m_eObjectList[iii]->GetObjectType() << "\"");
delete(m_eObjectList[iii]);
m_eObjectList[iii] = NULL;
}
} else {
m_eObjectList.Erase(0);
m_eObjectList.Erase(iii);
}
}

View File

@ -16,6 +16,7 @@
#include <etk/os/FSNode.h>
#include <ewol/Dimension.h>
#include <date/date.h>
#include <ewol/UserConfig.h>
#undef __class__
#define __class__ "ewol"
@ -31,6 +32,7 @@ int32_t ewol::Run(int32_t argc, const char* argv[])
}
// init display convertions:
ewol::dimension::Init();
ewol::userConfig::Init();
EWOL_DEBUG("Store commangLine in the specific system");
ewol::commandLine::Clean();

View File

@ -145,5 +145,6 @@ bool widget::Label::LoadXML(TiXmlNode* _node)
// TODO : Unparse data type XML ...
EWOL_DEBUG("Load label:" << _node->ToElement()->GetText());
SetLabel(_node->ToElement()->GetText());
EWOL_ERROR(" parse text : \"" << m_label << "\"");
return true;
}

View File

@ -181,6 +181,17 @@ void widget::Menu::OnReceiveMessage(const ewol::EMessage& _msg)
// set it in the pop-up-system :
m_widgetContextMenu->SetSubWidget(mySizer);
bool menuHaveImage = false;
for(int32_t jjj=m_listElement.Size()-1; jjj>=0; jjj--) {
if (m_listElement[iii]!=NULL) {
if (m_listElement[iii]->m_localId == m_listElement[jjj]->m_parentId) {
if (m_listElement[jjj]->m_image.Size()!=0) {
menuHaveImage = true;
break;
}
}
}
}
for(int32_t jjj=m_listElement.Size()-1; jjj>=0; jjj--) {
if (m_listElement[iii]!=NULL) {
if (m_listElement[iii]->m_localId == m_listElement[jjj]->m_parentId) {
@ -188,17 +199,33 @@ void widget::Menu::OnReceiveMessage(const ewol::EMessage& _msg)
if (NULL == myButton) {
EWOL_ERROR("Allocation Error");
} else {
/*if (m_listElement[jjj]->m_image.Size()!=0) {
if (m_listElement[jjj]->m_image.Size()!=0) {
myButton->SetSubWidget(
new widget::Composer(widget::Composer::String,
etk::UString("<composer>\n") +
" <sizer mode=\"hori\">\n"
etk::UString("<composer expand=\"true,false\" fill=\"true,true\">\n") +
" <sizer mode=\"hori\" expand=\"true,false\" fill=\"true,true\" lock=\"true\">\n"
" <image src=\"" + m_listElement[jjj]->m_image + "\" size=\"8,8mm\"/>\n"
" <label exand=\"true,false\">" + m_listElement[jjj]->m_label + "</label>\n"
" <label exand=\"true,true\" fill=\"true,true\"><![CDATA[" + m_listElement[jjj]->m_label + "]]></label>\n"
" </sizer>\n"
"</composer\n"));
} else */ {
myButton->SetSubWidget( new widget::Label(etk::UString("<left>") + m_listElement[jjj]->m_label + "</left>") );
"</composer>\n"));
} else {
if (true == menuHaveImage) {
myButton->SetSubWidget(
new widget::Composer(widget::Composer::String,
etk::UString("<composer expand=\"true,false\" fill=\"true,true\">\n") +
" <sizer mode=\"hori\" expand=\"true,false\" fill=\"true,true\" lock=\"true\">\n"
" <spacer min-size=\"8,0mm\"/>\n"
" <label exand=\"true,true\" fill=\"true,true\"><![CDATA[" + m_listElement[jjj]->m_label + "]]></label>\n"
" </sizer>\n"
"</composer>\n"));
} else {
widget::Label* tmpLabel = new widget::Label(etk::UString("<left>") + m_listElement[jjj]->m_label + "</left>");
if (NULL != tmpLabel) {
tmpLabel->SetExpand(bvec2(true,false));
tmpLabel->SetFill(bvec2(true,true));
myButton->SetSubWidget(tmpLabel);
}
}
}
// set the image if one is present ...
myButton->RegisterOnEvent(this, widget::Button::eventPressed, widget::Button::eventPressed);

View File

@ -189,7 +189,7 @@ void widget::WSlider::PeriodicCall(int64_t _localTime)
} else {
if (m_lastPeriodicCall != -1) {
float delta = (double)(_localTime - m_lastPeriodicCall)/1000000.0;
m_slidingProgress += m_transitionSpeed*delta;
m_slidingProgress += delta/m_transitionSpeed;
m_slidingProgress = etk_avg(0.0f, m_slidingProgress, 1.0f);
}
m_lastPeriodicCall = _localTime;

View File

@ -38,8 +38,6 @@ namespace widget {
int32_t m_windowsDestination; //!< widget destinated viewed
float m_slidingProgress; //!< ratio progression of a sliding
int64_t m_lastPeriodicCall;
float m_transitionSpeed; //!< speed of the transition (default 1 ==> 1s)
sladingMode_te m_transitionSlide; //!< mode to slide the widgets
public:
/**
* @brief Select a new subwidget to display
@ -56,6 +54,22 @@ namespace widget {
* @param[in] _widgetName Name of the subwidget name
*/
void SubWidgetSelectSet(const etk::UString& _widgetName);
private:
float m_transitionSpeed; //!< speed of the transition (default 1 ==> 1s)
public:
/**
* @brief Set transition speed element.
* @param[in] _timeSecond number of second needed to do the transition.
*/
void SetTransitionSpeed(float _timeSecond) { m_transitionSpeed = _timeSecond; };
/**
* @brief Get transition speed element.
* @return number of second needed to do the transition.
*/
float GetTransitionSpeed(void) { return m_transitionSpeed; };
private:
sladingMode_te m_transitionSlide; //!< mode to slide the widgets
public:
/**
* @brief Set a new mode of sliding element
* @param[in] _mode new display mode
@ -66,7 +80,6 @@ namespace widget {
* @return The current sliding mode
*/
sladingMode_te GetTransitionMode(void) { return m_transitionSlide; };
public: // Derived function
virtual const char * const GetObjectType(void) { return "Ewol::WSlider"; };
virtual void CalculateSize(const vec2& _availlable);

View File

@ -13,6 +13,7 @@
#include <ewol/widget/Image.h>
#include <ewol/widget/WidgetManager.h>
#include <ewol/widget/Composer.h>
#include <ewol/UserConfig.h>
#include <etk/Vector.h>
@ -24,13 +25,13 @@
extern const char * const ewolEventParameterValidate = "ewol-event-parameter-validate";
extern const char * const ewolEventParameterClose = "ewol-event-parameter-close";
extern const char * const ewolEventParameterSave = "ewol-event-parameter-save";
static const char * const l_eventMenuSelected = "local-event-menu-selected";
widget::Parameter::Parameter(void) :
m_currentIdList(0),
m_widgetTitle(NULL),
m_widgetCancel(NULL),
m_paramList(NULL)
{
AddEventId(ewolEventParameterClose);
@ -68,11 +69,36 @@ widget::Parameter::Parameter(void) :
mySizerHori->SubWidgetAdd(mySpacer);
}
m_widgetCancel = new widget::Button();
if (NULL == m_widgetCancel) {
widget::Button* tmpButton = new widget::Button();
if (NULL == tmpButton) {
EWOL_ERROR("Can not allocate widget ==> display might be in error");
} else {
m_widgetCancel->SetSubWidget(
tmpButton->SetSubWidget(
new widget::Composer(widget::Composer::String,
"<composer>\n"
" <sizer mode=\"hori\">\n"
" <image src=\"THEME:GUI:Save.svg\" expand=\"true\" size=\"8,8mm\"/>\n"
" <label>Save</label>\n"
" </sizer>\n"
"</composer\n"));
tmpButton->RegisterOnEvent(this, widget::Button::eventPressed, ewolEventParameterSave);
mySizerHori->SubWidgetAdd(tmpButton);
}
mySpacer = new widget::Spacer();
if (NULL == mySpacer) {
EWOL_ERROR("Can not allocate widget ==> display might be in error");
} else {
mySpacer->SetExpand(bvec2(false,false));
mySpacer->SetMinSize(ewol::Dimension(vec2(10,0)));
mySizerHori->SubWidgetAdd(mySpacer);
}
tmpButton = new widget::Button();
if (NULL == tmpButton) {
EWOL_ERROR("Can not allocate widget ==> display might be in error");
} else {
tmpButton->SetSubWidget(
new widget::Composer(widget::Composer::String,
"<composer>\n"
" <sizer mode=\"hori\">\n"
@ -80,8 +106,8 @@ widget::Parameter::Parameter(void) :
" <label>Close</label>\n"
" </sizer>\n"
"</composer\n"));
m_widgetCancel->RegisterOnEvent(this, widget::Button::eventPressed, ewolEventParameterClose);
mySizerHori->SubWidgetAdd(m_widgetCancel);
tmpButton->RegisterOnEvent(this, widget::Button::eventPressed, ewolEventParameterClose);
mySizerHori->SubWidgetAdd(tmpButton);
}
}
@ -131,6 +157,8 @@ widget::Parameter::Parameter(void) :
if (NULL == m_wSlider) {
EWOL_ERROR("Can not allocate widget ==> display might be in error");
} else {
m_wSlider->SetTransitionSpeed(0.5);
m_wSlider->SetTransitionMode(widget::WSlider::sladingTransitionVert);
m_wSlider->SetExpand(bvec2(true,true));
mySizerVert2->SubWidgetAdd(m_wSlider);
}
@ -184,6 +212,8 @@ void widget::Parameter::OnReceiveMessage(const ewol::EMessage& _msg)
GenerateEventId(ewolEventParameterClose);
// Close this widget ...
AutoDestroy();
} else if (_msg.GetMessage() == ewolEventParameterSave) {
ewol::userConfig::Save();
} else if (_msg.GetMessage() == l_eventMenuSelected) {
if (NULL != m_wSlider) {
int32_t value = 0;
@ -208,9 +238,6 @@ void widget::Parameter::OnObjectRemove(ewol::EObject * removeObject)
if(removeObject == m_paramList) {
m_paramList = NULL;
}
if(removeObject == m_widgetCancel) {
m_widgetCancel = NULL;
}
if(removeObject == m_wSlider) {
m_wSlider = NULL;
}

View File

@ -43,7 +43,6 @@ namespace widget {
private:
int32_t m_currentIdList;
widget::Label* m_widgetTitle;
widget::Button* m_widgetCancel;
widget::ParameterList* m_paramList;
widget::WSlider* m_wSlider;
};

View File

@ -18,7 +18,8 @@ def Create(target):
'ewol/commandLine.cpp',
'ewol/key.cpp',
'ewol/cursor.cpp',
'ewol/Dimension.cpp'])
'ewol/Dimension.cpp',
'ewol/UserConfig.cpp'])
# Basic Eobject of EWOL
myModule.AddSrcFile([