QSettings setDefaultFormat(QSettings::IniFormat) does not work on the first created object



  • Hi All,
    I am making a program on windows, that uses QSettings objects to read and write settings.
    In main, I write the following:

        QCoreApplication::setOrganizationName("me");
        QCoreApplication::setOrganizationDomain("me.nl");
        QCoreApplication::setApplicationName("myProgram");
    

    in other files I have the following:

    QSettings * settings = new QSettings;
    settings->setValue("Start",((QDateTimeEdit*)(myTableWidget->cellWidget(i,IDXSTART)))->dateTime());
    

    This works fine, but I would like to use .ini files. Therefore I do the following:

    QSettings * settings = new QSettings;
    settings->setDefaultFormat(QSettings::IniFormat);
    qDebug()<<"Reading settings from:"<< settings->fileName();
    

    The first created QSettings object, reads from the registry, all the QSettings objects that are created after it, correctly read and write from the .ini file.

    I can solve this by using the following constructor, but then I also need to specify the filename: I would not like to do this, as I then have to feed the same filename throughout my entire program, and I don't like the idea of using hardcoded paths

    QSettings(const QString &fileName, Format format, QObject *parent = Q_NULLPTR)
    

    I can also use this constructor, but then I have to specify my organisation, and application name in multiple places in my program.

    QSettings(Scope scope, const QString &organization, const QString &application = QString(), QObject *parent = Q_NULLPTR)
    

    After a search in this forum, I found somebody who has created a global QSettings object:
    https://forum.qt.io/post/328451

    // in .h-File
    class MainWindow : public QMainWidnow
    {
         Q_OBJECT
    
    public:
         static QSettings Settings;
    };
    
    // beginning of .cpp-File
    QSettings MainWindow::Settings = QSettings("My Company Inc.", "My Application");
    
    Then use
    
    MainWindow::Settings.setValue( ... );
    MainWindow::Settings.value( ... );
    

    This looks good, as I then enter the information in exactly one place in the application, but somebody else then made an argument against a global QSettings object:
    https://forum.qt.io/post/306740

    You are using QSettings in a global variable. Move the initialisation inside the main().
    
    Looks like you are using a statically linked Qt, right ? Your QSettings is a global variable, QSettings implementation itself rely on other global variables. The order of initialisation of global variables is undefined.
    What could work, from worst to best:
    
        shuffle the link order around to get QSettings globals initialised first (that would be a very fragile fix)
        link Qt as a shared library, shared lib would be loaded and initialised before your code.
        Don't build a QSettings as a global, replace it with a QSettings * and build it in main().
    

    What is the correct way to use .ini files on Windows without having to enter the same information in multiple places in the application?
    Is the global object method above correct, or fragile?

    Cheers,
    Cedric



  • Hi, I've also faced the same conundrum as you, and knowing from previous bad experiences that global Qt objects is something to avoid, I wrote a simple utility class to encapsulate a QSettings instance.
    To avoid repeating the file information, I used one nifty C++ trick: delegating constructor, like this:

    class AppSettings
    {
         QSettings* pSettings;
    public:
        AppSettings() : AppSettings(qApp->applicationName() + ".ini") {}   // use appname.ini as filename
        AppSettings(QString sIniFileName);                                 // use the specified filename
        ~AppSettings();
    
        bool    readBool              (QString sKeyName);
        bool    readBoolWithFallback  (QString sKeyName,bool    bFallbackValue);
        int     readInt               (QString sKeyName);
        int     readIntWithFallback   (QString sKeyName,int     nFallbackValue);
        QString readString            (QString sKeyName);
        QString readStringWithFallback(QString sKeyName,QString sFallbackValue);
    
        void    writeBool             (QString sKeyName,bool    bValue);
        void    writeInt              (QString sKeyName,int     nValue);
        void    writeString           (QString sKeyName,QString sValue)
    };
    

    Then i my app, I just declare an AppSettings settings; and voila I can read/write from an .ini file, e.g. settings.readString("SavedNumber");. If you want to see the code in all its glory, its here


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.