Qt Settings

It is a common request for an application to need a way of keep persistent a bunch of configuration values between to different executions.

For instance, we could want to store the application's main window position and size, so that we could reopen that window keeping the same aspect.

Qt offers a class for this task: QSetting.

Its behaviour depends on the operating system on which the application runs, for the Windows systems the values are stored in the registry.

For instance this function writes the position and the size of the current widget (in our case the main window) in the registry under the key "Computer\HKEY_CURRENT_USER\Software\Trolltech\Hello Qt":

void WinMain::writeSettings()
{
QSettings settings("Trolltech", "Hello Qt");
settings.setValue("pos", pos());
settings.setValue("size", size());
}

The QSettings setValue() method accepts in input a QString, the key where to store the value, and a QVariant, the value we want actually store.

QVariant is a sort of union type that allow us to manage unrelated types without using void pointer. So we can use setValue() for both the position (a QPoint object) and the size (a QSize instance) still having a good level of type safety.

We should call writeSettings when we are closing the main window, typically in the closeEvent() function, doing something like this:

void WinMain::closeEvent(QCloseEvent* event)
{
if(confirmed())
{
writeSettings();
event->accept();
}
else
event->ignore();
}

Simmetrically, we usually call in the main window constructor a function that would read and use the previously stored values, if any:

WinMain::WinMain(QWidget *parent) : QMainWindow(parent)
{
// ...
readSettings();
// ...
}

That function should be something like this:

void WinMain::readSettings()
{
QSettings settings("Trolltech", "Hello Qt");

QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
resize(size);

QSize size = settings.value("size", QSize(200, 200)).toSize();
move(pos);
}

The value() method gets the value specified by the first parameter. If such key is not available the second parameter is returned, in this way we can define a default value.

Instead of using the toPoint(), toSize(), and all the other similar functions to extract the actual object from the variant, it is possible to use a template version of the value function, in this way:

QPoint pos = settings.value("pos", QPoint(200, 200)).value<QPoint>();

No comments:

Post a Comment