Raphael
Raphael

Reputation: 8192

Qt - How to save a configuration file on multiple platforms

I'm writing a Qt application that needs to save some settings to the user's configuration directory.

I've come up with the following code to get this folder:

#ifdef Q_WS_WIN
    path = QDir::homePath() + "/Application Data/Timely";
#else
    path = QDir::homePath() + "/.config/Timely";
#endif

This fails on Windows 7 cause Windows 7 uses App Data/Roaming/[YourApp]. How can I get the user's configuration folder in a cross-platform way? I'm I missing something obvious? (this is supposed to be an easy task)

Upvotes: 4

Views: 7410

Answers (4)

Neurotransmitter
Neurotransmitter

Reputation: 6817

In addition to provided answers suggesting to use QSettings, I will shamelessly copy here Qt's own example from documentation (I slightly edited it, though).

Here are the functions to read and write settings from the file/registry/whatever:

void MainWindow::readSettings()
{
    QSettings settings("Moose Soft", "Clipper");

    settings.beginGroup("MainWindow");
    resize(settings.value("size", QSize(400, 400)).toSize()); // note the 400x400 defaults if there is no saved settings yet
    move(settings.value("pos", QPoint(200, 200)).toPoint()); // here default pos is at 200,200
    settings.endGroup();
}

void MainWindow::writeSettings()
{
    QSettings settings("Moose Soft", "Clipper");

    settings.beginGroup("MainWindow");
    settings.setValue("size", size());
    settings.setValue("pos", pos());
    settings.endGroup();
}

The readSettings() function may be called from the MainWindow constructor:

MainWindow::MainWindow()
{
    ...
    readSettings();
}

while writeSettings() from the close event handler:

void MainWindow::closeEvent(QCloseEvent *event)
{
        writeSettings();
        event->accept();
}

Last but not least, take a note, that settings format may be different. For example, if you want settings to be saved in the registry in Windows, you should pass QSettings::NativeFormat to the constructor, but if you'd like text config in the %appdata%, pass QSettings::IniFormat instead. In the example above format isn't passed, so it's native by default.

My personal preference to set IniFormat for Windows (because registry data isn't easily transferable) and NativeFormat for Linux and macOS, like this:

QSettings *settings;

if ( (os == "Linux") | (os == "macOS") ) {
    settings = new QSettings(QSettings::NativeFormat, QSettings::UserScope, "Moose Soft", "Clipper");
} else {
    settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "Moose Soft", "Clipper");
};

Upvotes: 0

tibur
tibur

Reputation: 11636

Depends on the settings you want to record, but I would suggest to use QSettings.

Upvotes: 11

gnud
gnud

Reputation: 78568

Yes, this is supposed to be an easy task - but you're not supposed to hard-code paths. You should use the native APIs on win/mac, and an enviroment variable on most newer unix-like. Of course, Qt helps you do this cross-platform.

Follow Tibur's suggestion and use QSettings if it's configuration data for your Qt app. You can also get the config directory by using the appropriate QT api.

QT4: QDesktopServices::storageLocation(QDesktopServices::DataLocation)
QT5: QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)

Upvotes: 6

dmiller309
dmiller309

Reputation: 385

I use QSettings for simple values that make sense to put in the Windows registry or an INI file, and SQLite for more complicated setups. In Qt5, put the SQLite database in QStandardPaths::writableLocation(QStandardPaths::ConfigLocation). In Qt4, put the SQLite database in QDesktopServices as gnud suggested (deprecated in Qt5).

Upvotes: 1

Related Questions