This page is likely outdated (last edited on 19 Oct 2005). Visit the new documentation for updated content.

GConfTutorial

Table of contents

What is GConf?

GConf is the system for storing application preferences in Gnome. It is intended for user preferences.

What makes GConf different than other configuration databases is that GConf is “live” and will notify interested parties of changes in the configuration values. This allows developers to build more modern applications: changes can always be applied immediately and the user will get a chance of preview the visual effects immediately.

What is it not?

GConf is not a place to store configuration of something like Apache, or arbitrary data storage.

Some Theory

Theory

The root motivation for GConf is to make application preferences more manageable for system administrators.

Another important motivation for GConf is that it’s “process transparent.” This means that if I change a setting from one application, it instantly updates in all other applications that are interested in that setting. This technology is vital for the snazzy “instant apply” UI of GNOME 2, and vital for writing applications made up of multiple out-of-process components.

GConfattempts to leapfrog the registry concept. It’s a library which provides a simple configuration data storage interface to applications, and also an architecture that tries to make things easy for system administrators.

Here are some of the features of GConf:

  • Replaceable backend architecture. GConf currently has a single backend that stores configuration data in XML-format text files; however, the architecture allows a Registry-like binary database backend, an LDAP backend, or even a full-blown SQL database backend. The backend used is configurable by the system administrator. This is a valuable feature for IS deparatments managing large numbers of computers.
  • Configuration key documentation. Applications can install documentation along with their configuration data, explaining the possible settings and the effect of each configuration key. A regedit-style tool can display this documentation, making it much easier to customize applications without breaking them. The GConf database also stores useful meta-information such as the application that owns a key, when the key was last changed, etc.
  • Data change notification service. If configuration data is changed, all interested applications are notified. The notification service works across the network, affecting all login sessions for a single user.

This means that programs built from components (where each component may be in a separate process) are much easier to write, because if one component changes a setting the others can discover the change and update themselves. For example, GNOME’s Nautilus file manager is actually a collection of applications, including an embedded web browser, and various navigation components. The components communicate via CORBA. However, you want a single preferences dialog located in the top-level “shell” component. Without GConf, a custom protocol would have to be invented for each preferences setting, to notify embedded components of changes to user preferences.

Notification is also useful if multiple application instances are running. GNOME uses this feature to let user interface configuration take effect on-the-fly without restarting any applications; if you turn off toolbar icons, for example, toolbar icons will immediately disappear in all running apps.

  • The client API is very abstract, which allows us to change its implementation at a later time without a big headache. Because a good implementation is a complex problem, this is important. I also like to think the API is simple to use.
  • GConf does proper locking so that the configuration data doesn’t get corrupted when multiple applications try to use it.

Most nontrivial applications will need to store user preferences. Traditionally, on most Unix-like systems user prefs have been stored in so called “dot files” which don’t provide a flexible and convenient way of dealing with settings. GConf tries to clear up the mess of “dot files”. It provides a tree-structured repository of keys and corresponding values. Data types supported include integers, floats, strings, boolean values and lists composed of the previous ones. Applications can set and get values and also listen for changes. If some values change, your application will be notified accordingly.

What are we going to do in this tutorial?:

Screenshots

Our Application

Gconftutorial-app.png

GConf-Editor

Gconftutorial-gconf-editor.png

Sample Code

// GConf.cs
// GConf Tutorial
// mcs GConf.cs -out:GConf.exe -pkg:gtk-sharp -pkg:gconf-sharp
using System;
using Gtk;
using GConf;
 
class GConfTutorial {
    // defining global constants for later use in the program
    GConf.Client client; // gconf client
    // these strings represent our gconf paths
    static string GCONF_APP_PATH = "/apps/gconf-tutorial";
    static string NAME_KEY = GCONF_APP_PATH + "/name";
    static string EMAIL_KEY = GCONF_APP_PATH + "/email";
    static string SN_KEY = GCONF_APP_PATH + "/serialno";
    static string MARRIED_KEY = GCONF_APP_PATH + "/married";
 
    // defines our edit boxes and our checkbox
    Entry name;
    Entry email;
    Entry sn;
    CheckButton married;
 
    public static void Main(string[] args)
    {
        new GConfTutorial ();
    }
 
    public GConfTutorial()
    {
        Application.Init ();
 
        // creates new window with the given title
        Window w = new Window("GConf Tutorial");
        // creates all edit boxes
        name = new Entry();
        email = new Entry();
        sn = new Entry();
        // creates our checkbox
        married = new CheckButton("Married");
        // we create a big vertical box where we will place other widgets
        VBox globvbox = new VBox();
 
        // setting up the box so we look more HIGish
        globvbox.BorderWidth = 12;
        globvbox.Spacing = 6;
 
        // adding the vbox to our window
        w.Add(globvbox);
 
        // we set up our label
        Label info = new Label("<span weight=\"bold\" size=\"large\"> Your Information</span>");
        info.UseMarkup = true;
        // and add it to the vertical box
        globvbox.PackStart(info, false, false, 0);
 
        // creates a new horizontal box
        HBox horz = new HBox();
        horz.Spacing = 6;
 
        // adds the horizontal box the the global vertical
        globvbox.Add(horz);
 
        // creating another vbox which will hold our labels
        VBox lblcnt = new VBox();
        lblcnt.Spacing = 6;
        // adds the vbox to the horizontal one
        horz.PackStart(lblcnt, false, false, 0);
 
        // creates label
        Label lbl = new Label("Name:");
        lbl.Xalign = 0; // aligns it to the left
        lblcnt.PackStart(lbl, true, false, 0);
 
        // creates label
        lbl = new Label("Email:");
        lbl.Xalign = 0; // aligns it to the left
        lblcnt.PackStart(lbl, true, false, 0);
 
        // creates label
        lbl = new Label("Serial Number:");
        lbl.Xalign = 0; // aligns it to the left
        lblcnt.PackStart(lbl, true, false, 0);
 
        // another vbox to hold the edit boxes
        VBox ntrycnt = new VBox();
        ntrycnt.Spacing = 6; // HIGying
        // adds the vbox containing the edit boxes to the horizontal one
        horz.PackStart(ntrycnt, true, true, 0);
 
        // adding all the edit boxes
        ntrycnt.PackStart(name, true, true, 0);
        ntrycnt.PackStart(email, true, true, 0);
        ntrycnt.PackStart(sn, true, true, 0);
        // last, but not least - the check box
        globvbox.PackStart(married, false, false, 0);
 
        // creates our link to gconf
        client = new GConf.Client();
        // tries to grab values from gconf and update the GUI
        UpdateFromGConf();
        // sets the function to be called if some key changes
        client.AddNotify (GCONF_APP_PATH, new NotifyEventHandler (GConf_Changed));
 
        // hooks events
        w.DeleteEvent += on_close_app;
        married.Toggled += on_married_toggled;
        name.Changed += on_name_activate;
        email.Changed += on_email_activate;
        sn.Changed += on_sn_activate;
 
        // shows the window
        w.ShowAll();
 
        // runs the application
        Application.Run ();
    }
 
    // function to grab values from gconf and update the GUI
    void UpdateFromGConf ()
    {
        try {
            name.Text = (string) client.Get (NAME_KEY);
            email.Text = (string) client.Get (EMAIL_KEY);
            sn.Text = (string) client.Get (SN_KEY);
            married.Active = (bool) client.Get (MARRIED_KEY);
        } catch (GConf.NoSuchKeyException e) {
            Console.WriteLine("Error: A key with that name doesn't exist.");
            // add your exception handling here
        } catch (System.InvalidCastException e) {
            Console.WriteLine("Error: Cannot typecast.");
            // add your exception handling here
        }
    }
 
    public void on_married_toggled (object o, EventArgs args)
    {
        // sets the corresponding value in gconf
        client.Set (MARRIED_KEY, married.Active);
    }
 
    public void on_name_activate (object o, EventArgs args)
    {
        // sets the corresponding value in gconf
        client.Set (NAME_KEY, name.Text);
    }
 
    public void on_email_activate (object o, EventArgs args)
    {
        // sets the corresponding value in gconf
        client.Set (EMAIL_KEY, email.Text);
    }
 
    public void on_sn_activate (object o, EventArgs args)
    {
        // sets the corresponding value in gconf
        client.Set (SN_KEY, sn.Text);
    }
 
    public void GConf_Changed (object sender, NotifyEventArgs args)
    {
        // sets the corresponding value in gconf
        UpdateFromGConf();
    }
 
    public void on_close_app(object o, DeleteEventArgs args)
    {
        // quits the application
        Application.Quit();
    }
}
  • All the settings are set/retrieved in real-time so any change would affect your application immediatelly
  • Try running the application and GConf-Editor in parallel. Place them so they don’t overlap and start typing your name or editing some other checkbox - you’ll see that the values in GConf change immediatelly. Now try it the other way around - it will immediatelly change your values in your application.

References