Thursday, September 22, 2016

GSettings vs QSettings

A few weeks ago after discussing with Luke Yelavich about what to work on in speech-dispatcher next I decided to take a stab at making it use GSettings for its settings. (You can see the work in progress here if you like.) I've used GSettings before for work projects so thought it would be a good/easy thing to take on.

There are many advantages of using GSettings over plain ini-style files.
  • Type checking (You can't enter a string for a numeric setting for example).
  • Notification of setting changes.
  • Command-line changing of settings.
  • Default values for settings defined in the schema(s).

On that wip branch speech-dispatcher itself has been changed to use GSettings and also reacts to many setting changes dynamically. It doesn't react to changing the port type or port number or unix socket path dynamically, since we have no mechanism to tell client applications that it is changing. There are also GSettings schemas for the output modules, just need to make them read their settings from GSettings instead of the old ini-style .conf files. spd-conf also has been modified to write to GSettings rather than .conf files. That change alone reduced the spd-conf python script by quite a few lines of code and made it a lot easier to read.

As I was doing this work I got thinking about the differences between GSettings and QSettings. Besides one being glib/c based and the other being Qt/C++ they are really pretty similar. There are a few differences though:
  • QSettings doesn't emit signals when a setting changes. (I found a few forum posts asking why this is with possible workarounds. Nothing built into QSettings though).
  • QSettings doesn't have a schema for the settings themselves. There's no way to introspect a setting file to see what settings are possible. It just depends what keys the application reads.
  • QSettings doesn't have a command-line tool to set the settings. Since QSettings is cross platform it uses the Registry by default on Windows, PList files by default on macOS, and ini-style files on linux
  • QSettings does have type checking, but no range checking or anything like that.

I was a bit disappointed that QSettings that I've used for many many years is lacking these seemingly obvious and probably useful features. I wonder if we as a community implemented these features in QSettings if the Qt company would accept them.

13 comments:

scummos said...

Well, there's KConfig XT: https://techbase.kde.org/Development/Tutorials/Using_KConfig_XT

Jeremy Whiting said...

Yeah, KConfig is closer to what GSettings provides in that you can list what settings you want your application to support and can set ranges on numeric settings and such. It doesn't however send any signals when a setting changes that I could see in the KConfig API. Maybe I'm missing something though?

Dave said...

Your avatar on PlanetKDE and the one in the comments are of two clearly different people.

Jeremy Whiting said...

Heh, I noticed the one there on planetkde is quite old indeed. I need to update it... I'll do that now.

Unknown said...

KConfig(/XT) doesn't have such signal because it's not supported. It would need to track changes locally and reparse if a different process modifies the configuration. And resolve the conflicts if there's any.

In some places we have some dbus api to report such changes.

Die Brücke vom Kwai said...

Maybe some one could write a GSettings backend for QSettings?

Die Brücke vom Kwai said...

Maybe some one could write a GSettings backend for QSettings?

scummos said...

What is the use case for having multiple applications change the same config simulatneously and sending notify signals to each other? I currently cannot imagine ...

If you need that, it should be very simple to create your own dbus interface, right?

Jeremy Whiting said...

The use case I've used as a developer when using GSettings is having an application that runs in one screen and either an ssh connection or some other terminal connection on another device that I can change settings by running gsettings set org.foo.schemaname settingname newsetting and have the application react to that change dynamically. I think that alone is pretty convenient, though you're right exposing a dbus interface in the application itself accomplish the same thing (except then you have to set your dbus environment to the same as the running UI application when ssh-ing in...)

Tomaz said...

Jeremy,

I'm currently working in a replacement for KConfigXT / KConfig / QSettings that already does most of the things you said here you wanted to use. Currently is in pre-pre-alpha, but already works for the bare minimum.

Martin Sandsmark said...

The keyword for KConfigXT makes it emit a signal when the setting changes, but only in the same application instance I guess.

The biggest reason for having cross-application notification of configuration changes would be that application wouldn't inadvertently overwrite eachothers changed configuration, IMHO, like often seems to happen with applications using KSharedConfig.

Jeremy Whiting said...

Die Brücke vom Kwai,

A GSettings backend for QSettings would a) add the missing functionality, but also b) limit QSettings cross-platformness (I think). Plus it would make QSettings have a different set of features based on what backend you are using.

Tomaz,

Why reinvent it all, can't we add this functionality to existing QSettings instead?

Martin,

I wasn't aware of that signal. Having it only work within the same instance seems to be a big limitation though.

I suggest we use GSettings as inspiration for how to do the same thing in QSettings. Though I admit I haven't read that part of the GSettings code yet to see how it all works.

Tomaz said...

I didn't reinvent the wheel, but created a layer on top of qsettings - it does its job well (saves / restore prefs), on top of that I added a few nice things. I just send you an email explaining it more.