Application Programming

GConf makes it as simple as possible for application programmers to store and retrieve their configuration data. However, the general structure of configuration data storage and retrieval is somewhat different from the one you might use with configuration files.

Model-View-Controller Architecture

Applications using GConf effectively should structure their preferences and configuration code according to the famous Model-View-Controller (MVC) design pattern. In this pattern, your application contains three separate objects:

  1. The model traditionally models a real-world object; but more generally, it is the data you are planning to present to the user and allow the user to edit. In the GConf case, the model is the configuration database (in the big picture) and a particular configuration key (from a smaller-scale point of view). For example, the configuration key /desktop/gnome/menus/show-icons can be thought of as a model; it stores a boolean value indicating whether to show icons next to menu items in GNOME menus.

  2. The view somehow displays or represents your model. It receives some sort of notification when the model changes, and updates itself accordingly. For example, the GNOME menu item widgets listen for changes to the /desktop/gnome/menus/show-icons configuration key, and show or hide icons accordingly. An important point about views is that there can be more than one of them; you can have many menu items, without changing the model.

  3. The controller modifies the model. In the menu icons example, a GNOME control panel might be the controller; users use it to set the /desktop/gnome/menus/show-icons key to true or false.



An MVC architecture has a number of advantages. Most notably, it encourages code reuse and modularity; you can have any number of views, and different types of views, without changing the model or the controller; you can have any number of controllers, and different types of controller, without changing the model or the view. The main controller may be the GNOME control panel, but if the key is changed by some other application, that will also work properly. The primary view may be the GNOME menu item code, but if some different menu item code wanted to monitor and honor this setting, it could certainly do so.

GConf implements an exciting enhancement to the basic MVC pattern: the model is process-transparent. That is, the view and controller have no knowledge of which process contains the model; if you set a configuration key, then all views in all interested processes will be notified of the change. In a world of component technology, this is extremely useful.

All buzz-acronyms aside, all MVC means for you as an application programmer is that every section of code only has to be concerned with directly related configuration issues. For example, the menu item code only monitors the keys that affect how menu items are displayed. It is not concerned with any other keys, or with setting or saving that setting.

In contrast, with a simple configuration file, typically you have a global data structure which stores all your preferences, and you load and save it as a single unit. To add a setting, you have to modify the global structure. Whenever you load settings, you have to add code to the global preferences code that knows about all the interested parts of the program and notifies them (via some ad-hoc mechanism). It's kind of unpleasant and leads to poor modularity in a single process; but once multiple processes are involved, coming up with a suitable ad-hoc mechanism for change notification becomes a really significant problem.

Major Data Types

GConfEngine

A GConfEngine represents a configuration database (normally a connection to gconfd). You can store values in a GConfEngine, and retrieve values from one. You can also ask a GConfEngine to monitor a key or directory for changes, and invoke an application-supplied callback if changes occur. Each time you ask a GConfEngine to notify you of changes, it registers a request for notification with gconfd. Thus, notification requests are relatively expensive. With GConfClient, they are relatively cheap.

GConfClient

GConfClient is located in a separate library from GConf itself, because to use it you must link with GTK+. GConfClient derives from GtkObject and is a wrapper for the GConfEngine type. It adds a few nice features:

  • It can keep a client-side cache of values. Sometimes this is just memory overhead, so you'll want to turn it off. However, if you access the same keys frequently it can be a performance win.

  • It can do client-side notification request dispatching. This means that if you want to monitor the keys /foo/bar and /foo/baz, GConfClient registers a single notification request with gconfd; when the notification comes from gconfd, GConfClient decides which key has changed and dispatches to the proper application callback. With GConfEngine, each callback involves registering a request with gconfd.

  • It uses the GTK signal system. Instead of using GConf's custom callback API for notification, you can simply connect to a "value_changed" signal.

  • Finally, GConfClient provides default error handlers. This allows you to ignore errors, and let GConfClient present them to the user via an error dialog.



GConfValue

When GConf needs to pass around a dynamically-typed value retrieved from or to be stored in the database, it uses a type-tagged union called GConfValue. For example, the gconf_get() function takes a GConfEngine and a key name as arguments and returns a GConfValue. There are also convenience wrappers such as gconf_get_string() and gconf_get_int() that allow you to avoid the pesky GConfValue union.

GConfChangeSet

Modifications to the GConf database can be grouped into change sets, or collections of changes. A change is a new value for a key, or a directive to unset a key's current value. For now, the GConfChangeSet is primarily a convenience mechanism for managing the set of changes a user has made via a preferences dialog. However, in the future committing a change set may be an atomic operation (that is, GConf could be extended to support transactions).

GConfError

If you explicitly handle errors, rather than allowing the GConfClient default error handler to report them to the user, you receive information about an error in an object called GConfError. This contains a verbose error description, and an error code number.

GNOME Integration

Version 2.0 of GNOME automatically integrates with GConf, making it simpler to use the library. It does the following: