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?:
- Create a checkbox and an editbox
- Link them with GConf
- Test live notification with GConf-Editor
Screenshots
Our Application
GConf-Editor
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.