images images images

The weather applet and clock/calendar applet for the Avant Window Navigator both use GConf to store their configuration settings. GConf is part of the GNOME environment on Linux. It maintains a hierarchical set of configuration data in (key,value) pairs, much like the registry on Windows or the “plist files” on OSX. One of the nice things about GConf is that you can register your application to receive notifications in a callback function whenever any interesting configuration values change.

I noticed that there weren’t a lot of tutorials out there on the topic of mixing Python with GConf, so I decided to write one.

First, you’ll need to import the Python bindings for GConf:

1
import gconf

Next, you want to create a GConf “client” in your Python app. You’ll probably want to do this in an __init__() function somewhere. You’ll also want to register your application to receive notifications when ever your configuration values change. The hierarchy of configuration values in GConf follows the familiar slash-separated path notation. For example, the configuration values for my AWN weather applet are stored in /apps/avant-window-navigator/applets/weather. So, if I want to register a callback named config_event to be called whenever configuration values on that path are modified, I’d do the following:

1
2
self.gconf_client = gconf.client_get_default()
self.gconf_client.notify_add("/apps/avant-window-navigator/applets/weather", self.config_event)

I usually write a generic “get_config” function, and have the callback call get_config. That way, I can use the same configuration code when I initialize. The config callback then looks simple… something like this:

1
2
def config_event(self, gconf_client, *args, **kwargs):
  self.get_config()

The kwargs parameter gives you a list of parameters that changed. You can fine-tune your configuration code based on this, but I usually just ignore it and re-read everything because I don’t usually have very many parameters.

GConf provides functions for reading your parameters. They look like this:

1
2
3
foo = self.gconf_client.get_string("/path/to/my/config/data/foo")
bar = self.gconf_client.get_int("/path/to/my/config/data/bar")
baz = self.gconf_client.get_bool("/path/to/my/config/data/baz")

All of the functions except get_boolreturn None if the key isn’t found. Oddly, get_bool seems to return False if the key isn’t found. In my configuration code, I like to initialize my GConf values when the key isn’t found. So when if my code were to read the “foo” parameter like the above example, it’d actually be coded something like this:

1
2
3
4
foo = self.gconf_client.get_string("/path/to/my/config/foo")
if foo == None:
  self.gconf_client.set_string("/path/to/my/config/foo", "Default Value")
  foo = "Default Value"

And I usually wrap the above idiom in its own function that accepts a key name and a default value.


Note that you can edit and interact with your GConf settings in realtime using the GNOME configuration tool. If you use Ubuntu, then this utility may be found under the “System Tools” menu. Editing configuration values in the configuration tool will result in your callback being executed as you might expect.

This also makes creating a configuration dialog easy. The configuration dialog just needs to write its updated values to gconf when the user clicks Apply or OK. If you’ve created a callback and generic configuration function, then the application will automatically reconfigure itself after the user applies their modifications!