Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / C++

How to Make UI from Definition of INI Setting in Qt

Rate me:
Please Sign up or sign in to vote.
4.44/5 (9 votes)
18 Mar 2011CPOL3 min read 41.7K   532   18   10
How to generate a complete UI by typing key of value of key in INI setting in QT

Introduction

This is my second article on Qt. I recommend to everyone who is interested in C++ to have a look at this great framework.

Sometimes when I code, I think, "hmm, 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 sometimes, I don't have enough time. But the project continues and at one moment, I have to do this. I have worked in a company for software with something around 1000 preferences entry. So we make a system to have a GUI to change these preferences settings. It's a sophisticated one with XML file described in 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 has an object to make that, it's a really good one: QSettings. So I have an idea, and I want to share with you it. The settings are saved in the common INI format (key = value). I want to generate my UI dynamically from the definition of the key's name. To do this, I have to type my key value. I do this by the prefix of the name of 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:

C++
[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 finally get this:

SettingUI/firstTab_2.png

SettingUI/secondTab_1.png

But I also want to have some parameters for some preference, like when it's a path on filesystem, I want to be sure it exists, or for an integer preference, I want to set the minimum and maximum value. So my solution is to eliminate the type of the key and add like a member of class like this:

C++
int_CacheMegaByte=0
CacheMegaByte.min=0
CacheMegaByte.max=10

min and max describe the minimum and the maximum 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.

SettingUI/errorPref.png

Using the Code

So in the MainWindow, there's a method call:

C++
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 above example, there are two sections (FirstSection and SecondSection) and I store the widget in a FormLayout, to have a coherent layout between entries.

This parses the INI file and creates a widget in its function:

C++
 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 widgets for the GUI preference setting are inherited from IprefWidget and have to implement:

C++
virtual QVariant getValue() =0;

For example: the GUI for a simple string implementation is:

C++
#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 options of type INI with possible restrictions are:

path .pathMustExist verifies if path exists
file .pathMustExist verifies if file exists
int.min .max test id the value enter is superior of min or inferior of max
str.regexp verifies if entry is exact match with regexp
bool
font
color
combo.value gives value of list in combo

The object architecture is:

SettingUI/class_ipref_widget2.png

Later when you want to save the object, you have to do:

C++
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 does the job. Your settings are saved according to the GUI.

Points of Interest

It's interesting to have a GUI automatically generated, but it's limited ... I know that. But this method is more a tip to make a GUI fast. I hope you will find it useful.

History

I made modifications from message of The Code Project community. I hope my article is better now, not perfect of course, but better.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) http://www.cmb-soft.com/
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey26-Feb-12 21:13
professionalManoj Kumar Choubey26-Feb-12 21:13 
GeneralMy vote of 4 Pin
ray pixar13-Feb-11 1:28
ray pixar13-Feb-11 1:28 
GeneralRe: My vote of 4 Pin
zebulon7501818-Mar-11 15:54
zebulon7501818-Mar-11 15:54 
GeneralArticle needs improvements but idea is interesting Pin
PedroMC8-Feb-11 1:01
PedroMC8-Feb-11 1:01 
GeneralMy vote of 3 Pin
Konstantin Mamutov7-Feb-11 6:07
professionalKonstantin Mamutov7-Feb-11 6:07 
Not clearly for what it is necessary
QuestionFor what? Pin
Konstantin Mamutov7-Feb-11 6:06
professionalKonstantin Mamutov7-Feb-11 6:06 
AnswerRe: For what? Pin
zebulon750187-Feb-11 12:13
zebulon750187-Feb-11 12:13 
GeneralNot bad but not great either Pin
xComaWhitex6-Feb-11 20:31
xComaWhitex6-Feb-11 20:31 
GeneralRe: Not bad but not great either Pin
zebulon750187-Feb-11 12:10
zebulon750187-Feb-11 12:10 
GeneralRe: Not bad but not great either Pin
zebulon7501818-Mar-11 15:53
zebulon7501818-Mar-11 15:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.