toffeehoops
toffeehoops

Reputation: 51

Qt - multiple copies of the same app open & settings synchronisation

I have a pretty standard Qt GUI application. It uses Qt's QSettings to store a number of settings, and it all works fine.

However, when multiple copies of the application are launched, and settings are changed in one or the other, the different copies can appear inconsistent (as one has the "old" copy of the data).

What are the preferred solutions to this problem? I guess this problem occurs, even outside of the Qt arena.

Upvotes: 4

Views: 1410

Answers (2)

I am facing the same problem. There is QSettings::sync() function but it seems to take of the integrity of the settings file (INI, registry etc.) than to make the settings consistent with the state of the application. By this 'consistency' I mean for example that when as a user I change the font size value in the settings dialog, I expect the whole application to be re-layouted and repainted. This is easy to achieve within one instance of application (using signals-slots, events etc.). But when I have two or more applications running, the other instances get no information that the font size settings was changed, they are not re-layouted nor repainted and later when any widget gets drawn using the new font size initialized from the QSettings, it becomes inconsistent with the rest of the application and the layout get potentially broken.

There is however a solution to this. It requires adding another 'caching' level for all settings, above QSettings. All the settings will be loaded to some settings data class using QSettings::value(...) only at the application start, and during the run of the application the application will not directly read from QSettings::value() but only from the cache. This way you will have fully consistent behavior. When the user changes some setting in settings dialog, each item will be compared to the cached value (i.e. check whether the user changed it) and if it is not equal, it gets written to settings using QSettings::setValue().

// To be created at application startup, just after
// QApplication::setApplication(), setOrganizationName() etc. is called.
// When the application is running, you only obtain cached values
// from the instance of Settings instead of querying QSettings.
class Settings
{
    Settings() { 
        m_x = QSettings().value("x", 0).toInt(); 
    }

    int x() const {
        return m_x;
    }

    void setX(int x) {
        if (x == m_x)
            return;
        m_x = x;
        QSettings().setValue("x", x);
    }

private:
    int m_x;
}

Upvotes: 0

Mihai Limbășan
Mihai Limbășan

Reputation: 67836

The QSettings docs mention this in the Accessing Settings from Multiple Threads or Processes Simultaneously section:

  • QSettings can safely be used from different processes (which can be different instances of your application running at the same time or different applications altogether) to read and write to the same system locations. It uses advisory file locking and a smart merging algorithm to ensure data integrity. Changes performed by another process aren't visible in the current process until sync() is called.

Have you tried to call yoursettings.sync() from the writer app after writing values and from the reader app before reading them? If so, and if your logic is correct, this sounds like a Qt bug.

Upvotes: 2

Related Questions