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:    

firstTab_2.png

secondTab_1.png

 

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=10
min 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.

errorPref.png 

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


 class_ipref_widget2.png


  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.

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"