Click here to Skip to main content
Click here to Skip to main content

Tagged as

How to Make UI from Definition of INI Setting in Qt

, 18 Mar 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

[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:

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:

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:

 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:

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 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:

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)

Share

About the Author

zebulon75018
Software Developer (Senior) http://www.cmb-soft.com/
France France
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermanoj kumar choubey26-Feb-12 22:13 
GeneralMy vote of 4 PinmemberBehrouz Mohamadi13-Feb-11 2:28 
GeneralRe: My vote of 4 Pinmemberzebulon7501818-Mar-11 16:54 
GeneralArticle needs improvements but idea is interesting PinmemberPedroMC8-Feb-11 2:01 
GeneralMy vote of 3 Pinmemberkmamutov7-Feb-11 7:07 
QuestionFor what? Pinmemberkmamutov7-Feb-11 7:06 
AnswerRe: For what? Pinmemberzebulon750187-Feb-11 13:13 
GeneralNot bad but not great either PinmemberxComaWhitex6-Feb-11 21:31 
GeneralRe: Not bad but not great either Pinmemberzebulon750187-Feb-11 13:10 
GeneralRe: Not bad but not great either Pinmemberzebulon7501818-Mar-11 16:53 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150327.1 | Last Updated 18 Mar 2011
Article Copyright 2011 by zebulon75018
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid