qtuser-interfaceqsettingsqjson

Save UI settings with QSettings or QJson?


Saving UI settings with QSettings is cumbersome and buggy, because each time you must use setValue() and value() functions and also define groups, application name and organization which can be buggy in large applications:

QSettings settings(qApp->applicationDirPath() + "/" + qApp->applicationName() + ".ini" , QSettings::IniFormat) ...

settings.beginGroup("someGroup");
settings.setValue("someKey", "blah blah");
QString str = settings.value("someKey");
settings.endGroup();

However with JSON it can be simpler:

QJsonObject obj;
obj["someKey"] = "blah blah"
...

What is the best practice for saving and restoring ui settings?

Any other idea?


Solution

  • The QSettings code won't be more cumbersome than your QJsonObject example if you use all benefits of the first one.

    Default QSettings constructor:

    You can set the application and organization names just once:

    QApplication::setApplicationName("My Application");
    QApplication::setOrganizationName("My Organization");
    QSettings::setDefaultFormat(QSettings::IniFormat);
    

    Then simply use the default QSettings constructor anywhere in your code:

    QSettings settings;
    settings.setValue("Key", "Value");
    

    Group as an argument:

    The settings group for your keys can be set without using the beginGroup() / endGroup() methods. Simply pass the slash-delimited argument to thevalue() / setValue() methods:

    settings.setValue("Group/Key", "Value");
    

    Storing the UI settings:

    It's not clear from your question what exact UI settings you want to save, however there are two handy methods – QWidget::saveGeometry() and QMainWindow::saveState(). You can use it to store your windows geometry and state respectively:

    QSettings settings;
    settings.setValue("ui/geometry", saveGeometry());
    settings.setValue("ui/state", saveState());
    

    JSON:

    In case if you still want some deep nesting and hierarchy for your settings file, you're right, you will have to use JSON. The most convenient way is to register the custom read/write functions using the QSettings::registerFormat. Why still QSettings? This class is designed considering the cross-platform code, no need to reinvent the wheel.

    Of course, you can also write your own JSON settings class from scratch. But if there is no need in multilevel settings hierarchy – is it worth it?

    In terms of application design you can wrap QSettings in an additional class. In this case you can easily experiment and switch to your own JSON read/write implementations without touching the main code.

    Standard system paths:

    In your example you are using the applicationDirPath() to store the settings data. That's an improper place to keep your settings for the most applications (e.g. you will likely face the Windows UAC issues in this case; Unix systems also have the separate directory for such files). Use the paths intended by the operating system for storing application data.

    For example, on Windows QSettings::setDefaultFormat(QSettings::IniFormat) coupled with the default scope (UserScope) will store the settings in the %APPDATA% path. This also improves the cross-platform portability of your code.