How to make UI from definition of Ini setting in Qt
Download QsettingUI2.zip - 14.69 KB
Introduction
This is my second article on Qt. I recommand to everyone who is interest by C++ to have a look to this great framework.
Something when I code, I'm thinking ,"hum , this hard value coded should be in a preference file", but if I do with , I have to make a gui interface to change this preference by user. And sometime I don't have enought time.But the projet continue and at one moment I have to do this.I have worked in a compagny for softwares with something around 1000 preferences entry. So we make a system to have a gui to change theses preferences settings.It's a softicated one with xml file describe the ini file. Here I want to show you how I make a simple one.
I want a system where the type of the setting entry is in the name of the Key of Ini file.
I have to make a gui to watch and set the setting of an application.
Qt have an objet to make that, it's really good one: QSettings.
So I have an idea, and I want to share with you it.
The setting are saving in the commun INI format ( key = value )
I want to generated dynamicly my ui from the definition of the key's name
So to do this, I have to type my key value. I do this by the prefix of the name the key in ini file.- str_ : string
- int_ : integer
- bool_ : boolean
- path_ : path filename
- list_ : path filename
- combo_ : an index in a list
- font_ : a font
- color_ : a color
My ini file should be like that:
[FirstSection]
str_Name=titi
int_CacheMegaByte=0
path_FilePath=titi
[SecondSection]
combo_ChooseInCombo=0
ChooseInCombo.value=tutu:toto:titi
path_OtherPath=C:/Qt/2010.05/QsettingUI-build-desktop/Makefile.Release
And I got finaly this:
But I want also to have some parameter for some preference , like when it's a path on filesystem, I want to be sure it exists, or for a integer preference , I want to set the minimum and maximun value. So my solution is to eliminate the type of the key and add like a member of class like this:
int_CacheMegaByte=0 CacheMegaByte.min=0 CacheMegaByte.max=10min and max describe the minimun and the maximun of the preference CacheMegaByte and the type of this preference is int. If there's an error, then there's a messageBox when user wants to save.
Using the code
So in the MainWindow there's a method call :
void MainWindow::buildUIFromQSetting(QSettings *settings)
I use a QToolBlox to add section of INI , and in the widget added I add gui preference ini widgets .In the example up there 're to section ( FirstSetion, and SecondSetion ).
andf I store the widget in a FormLayout, to have a coherent layout between entry.
This parse the INI file and create widget in function of it:
void MainWindow::buildUIFromQSetting(QSettings *settings) { QWidget *wid = new QWidget(ui->toolBox); QFormLayout *layout = new QFormLayout(); wid->setLayout(layout); ui->toolBox->addItem(wid,s); settings->beginGroup(s); QStringList lstKeys = settings->childKeys(); foreach(QString k,lstKeys) { IprefWidget *prefW=NULL; QStringList split = k.split("_"); if (split.length()>1) { if (split[0]=="str") { prefW = new strPrefWidget(settings,s,k,layout); } if (split[0]=="int") { prefW = new intPrefWidget(settings,s,k,layout); } if (split[0]=="path") { prefW = new pathPrefWidget(settings,s,k,layout); } if (split[0] == "combo") { prefW = new comboPrefWidget(settings,s,k,layout); } if (split[0] == "font") { prefW = new fontPrefWidget(settings,s,k,layout); } if (split[0] == "color") { prefW = new colorPrefWidget(settings,s,k,layout); } if (split[0] == "bool") { prefW = new boolPrefWidget(settings,s,k,layout); } if (split[0] == "file") { prefW = new filePrefWidget(settings,s,k,layout); } } if (prefW != NULL) { prefWidgetsList.append(prefW); //layout->addWidget(prefW); } } settings->endGroup(); } }All widget for the gui preference setting herited of IprefWidget and have to implement :
virtual QVariant getValue() =0;
For example : the gui for a simple string implementation is :
#include <QLineEdit> #include "prefWidget/iprefwidget.h" class strPrefWidget : public IprefWidget { public: strPrefWidget(QSettings *settings,const QString &group, const QString &nameKey,QWidget *parent = 0); virtual QVariant getValue(); protected: QLineEdit *edit; };
strPrefWidget::strPrefWidget(QSettings *setting,const QString &group, const QString &nameKey,QWidget *parent) : IprefWidget(setting,group,nameKey,parent) { edit = new QLineEdit(this); edit->setText(setting->value(nameKey).toString()); _layout->addWidget(edit); } QVariant strPrefWidget::getValue() { QVariant result; // If regexp is set then test if (_regexp.isEmpty() == false) { if (_regexp.exactMatch(edit->text()) == false) { return result; } } QVariant result; result.setValue(edit->text()); return result; }
The different option of type INI with possible restriction.
path | .pathMustExist verify if path exists |
file | .pathMustExist verify if file exists |
int | .min .max test id the value enter is superior of min or inferior of max |
str | .regexp verifit if entry is exact match with regexp |
bool | |
font | |
color | |
combo | .value give value of list in combo. |
The objet architeture is
After when you want to save the objet you have to do:
void MainWindow::saveSettings() { QSettings settings("settings.ini", QSettings::IniFormat ); for (int n=0;n<prefwidgetslist.length();n++) { settings.setValue( prefWidgetsList[n]->groupKey(), prefWidgetsList[n]->getValue()); } }And that do the job. your setting are saving according to the gui.
Points of Interest
It's interesting to have a gui automaticly generated , but it's limited ... I know that. But this method is more a tip , to make fast a gui. I hope you find it usefull may be.
History
I made modification from message of codeproject community , I hope my article is better now, not perfect of course but better.