Appendix D. GConf Examples

Table of Contents

Example 1
Example 2

Example 1

A simple example that shows a single GConf option for monitoring and setting Metacity's reduced resources mode is shown below.

The XML file generated by glade that contains this layout is below. The code turn this graphical layout into a functioning program is shown below the .glade file.

<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">

<glade-interface>
<requires lib="gnome"/>

<widget class="GtkDialog" id="MainWindow">
  <property name="visible">True</property>
  <property name="title" translatable="yes">Window Manager Settings</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_NONE</property>
  <property name="modal">False</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="has_separator">True</property>

  <child internal-child="vbox">
    <widget class="GtkVBox" id="dialog-vbox1">
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">0</property>

      <child internal-child="action_area">
	<widget class="GtkHButtonBox" id="dialog-action_area1">
	  <property name="visible">True</property>
	  <property name="layout_style">GTK_BUTTONBOX_END</property>

	  <child>
	    <widget class="GtkButton" id="CloseButton">
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-close</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="response_id">-7</property>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	  <property name="pack_type">GTK_PACK_END</property>
	</packing>
      </child>

      <child>
	<widget class="GtkCheckButton" id="Reduced Resources">
	  <property name="border_width">6</property>
	  <property name="visible">True</property>
	  <property name="can_focus">True</property>
	  <property name="label" translatable="yes">Use Reduced Resources Setting</property>
	  <property name="use_underline">True</property>
	  <property name="relief">GTK_RELIEF_NORMAL</property>
	  <property name="active">False</property>
	  <property name="inconsistent">False</property>
	  <property name="draw_indicator">True</property>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">False</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

</glade-interface>

GTK

The file using the C language bindings to GTK to make this interface layout into a functioning program is below.

/* This program monitors the /apps/metacity/general/reduced_resources
 * gconf key, and allows the user to change it as well.
 */

#include <gtk/gtk.h>
#include <glade/glade.h>
#include <gconf/gconf-client.h>

static gboolean old_setting;

void
gconf_key_changed_callback (GConfClient* client,
                            guint cnxn_id,
                            GConfEntry* entry,
                            gpointer user_data)
{
  GtkWidget* button;
  button = GTK_WIDGET (user_data);

  /* Make sure the preference has a valid value */
  if (gconf_entry_get_value (entry) != NULL && 
      gconf_entry_get_value (entry)->type == GCONF_VALUE_BOOL)
    {
      /* Get the new value */
      gboolean new_setting =
        gconf_value_get_bool (gconf_entry_get_value (entry));

      /* Try to handle asynchronous-ness of GConf and prevent calling
       * checkbutton_toggled_callback again if this function was
       * called as a result of the gconf_client_set_bool function call.
       */
      if (new_setting != old_setting)
        {
          old_setting = new_setting;
          gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), new_setting);
        }
    }
}

void
checkbutton_toggled_callback (GtkWidget* check_button, gpointer user_data)
{
  GConfClient* client = GCONF_CLIENT (user_data);

  /* Determine whether the checkbutton is already set or not */
  gboolean is_set = 
    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button));
 
  /* Try to handle asynchronous-ness of GConf and prevent calling
   * gconf_key_changed_callback again if this function was called as a
   * result of the gtk_toggle_button_set_active function call.
   */
  if (is_set != old_setting)
    {
      old_setting = is_set;
      gconf_client_set_bool (client,
                             "/apps/metacity/general/reduced_resources",
                             is_set,
                             NULL);
    }
}

void
hook_up_callbacks_and_set_defaults (GladeXML * the_widgets)
{
  GtkWidget *widget;

  /* Get the GconfClient, tell it we want to monitor /apps/metacity/general */
  GConfClient* client = gconf_client_get_default();
  gconf_client_add_dir(client,
                       "/apps/metacity/general",
                       GCONF_CLIENT_PRELOAD_NONE,
                       NULL);

  /* Get the check_button */
  widget = glade_xml_get_widget (the_widgets, "Reduced Resources");

  /* Connect the check_button to a callback that can toggle it when the option
   * is changed by some outside program.
   */
  gconf_client_notify_add(client,
                          "/apps/metacity/general/reduced_resources",
                          gconf_key_changed_callback,
                          widget,
                          NULL,
                          NULL);

  /* Connect the check_button's clicked callback up so that it can change the
   * gconf setting.
   */
  g_signal_connect(G_OBJECT (widget), "clicked",
                   G_CALLBACK (checkbutton_toggled_callback), client);

  /* Determine whether button should start activated or not */
  old_setting =
    gconf_client_get_bool (client,
                           "/apps/metacity/general/reduced_resources",
                           NULL);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), old_setting);


  /* Get the main_window and connect the close button to gtk_main_quit */
  widget = glade_xml_get_widget (the_widgets, "MainWindow");
  g_signal_connect (G_OBJECT (widget), "delete_event",
                    G_CALLBACK (gtk_main_quit), NULL);

  /* Get the quit button and it to gtk_main_quit */
  widget = glade_xml_get_widget (the_widgets, "CloseButton");
  g_signal_connect (G_OBJECT (widget), "clicked",
                    G_CALLBACK (gtk_main_quit), NULL);
}

int
main (int argc, char **argv)
{
  GladeXML *all_da_widgets;

  gtk_init (&argc, &argv);
  gconf_init(argc, argv, NULL);

  /* load the interface */
  all_da_widgets = glade_xml_new ("example-1.glade", NULL, NULL);

  /* Connect all the signals to the appropriate callbacks */
  hook_up_callbacks_and_set_defaults (all_da_widgets);

  /* start the event loop */
  gtk_main ();

  return 0;
}

GTKMM

The files using the C++ language bindings to GTK to make this interface layout into a functioning program are below. First, the ExampleWindow.h header file:

#ifndef EXAMPLE_WINDOW_H
#define EXAMPLE_WINDOW_H

#include <libglademm.h>
#include <gtkmm.h>
#include <gconfmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow(BaseObjectType* cobject,
                const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml);
  virtual ~ExampleWindow();

protected:
  void key_changed(guint connection_id, Gnome::Conf::Entry entry);
  void checkbutton_toggled();

  Glib::RefPtr<Gnome::Conf::Client> d_conf_client;
  Gtk::CheckButton*                 d_checkbutton;
  bool                              d_old_setting;
};

#endif // EXAMPLE_WINDOW_H

Next is the ExampleWindow.cc file:

#include "ExampleWindow.h"

ExampleWindow::ExampleWindow(
  BaseObjectType* base_object,
  const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml)
  : Gtk::Window(base_object)
{
  // Get the GConf::Client, tell it we want to monitor /apps/metacity/general
  d_conf_client = Gnome::Conf::Client::get_default_client();
  d_conf_client->add_dir("/apps/metacity/general");

  // Get the check_button
  glade_xml->get_widget("Reduced Resources", d_checkbutton);

  // Connect the check_button to a callback that can toggle it when the option
  // is changed by some outside program.
  d_conf_client->notify_add("/apps/metacity/general/reduced_resources",
                            sigc::mem_fun(*this, &ExampleWindow::key_changed));

  // Connect the check_button's clicked callback up so that it can change the
  // gconf setting.
  d_checkbutton->signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::checkbutton_toggled) );

  // Determine whether button should start activated or not
  d_old_setting = 
    d_conf_client->get_bool("/apps/metacity/general/reduced_resources");
  d_checkbutton->set_active(d_old_setting);

  // Get the close button and connect it to hide
  Gtk::Button* close_button;
  glade_xml->get_widget("CloseButton", close_button);
  close_button->signal_clicked().connect(
    sigc::mem_fun(*this, &Gtk::Widget::hide));
}

ExampleWindow::~ExampleWindow()
{
}

void
ExampleWindow::key_changed(guint connection_id, Gnome::Conf::Entry entry)
{
  // Make sure the preference has a valid value
  if (entry.get_value().get_type() == Gnome::Conf::VALUE_BOOL) {
    // Get the new value
    bool new_setting = entry.get_value().get_bool();

    // Try to handle asynchronous-ness of GConf and prevent calling
    // checkbutton_toggled again if this function was called as a
    // result of the d_conf_client->set() function call.
    if (new_setting != d_old_setting) {
      d_old_setting = new_setting;
      d_checkbutton->set_active(new_setting);
    }
  }
}

void
ExampleWindow::checkbutton_toggled()
{
  // Determine whether the checkbutton is already set or not
  bool is_set = d_checkbutton->get_active();
 
  // Try to handle asynchronous-ness of GConf and prevent calling
  // key_changed again if this function was called as a result of the
  // d_checkbutton->set_active() function call.
  if (is_set != d_old_setting) {
    d_old_setting = is_set;
    d_conf_client->set("/apps/metacity/general/reduced_resources", is_set);
  }
}

And finally, here is the example-1.cc file which glues everything together:

// This program monitors the /apps/metacity/general/reduced_resources
// gconf key, and allows the user to change it as well.

#include "ExampleWindow.h"

using namespace std;

int
main (int argc, char *argv[])
{
  Gnome::Conf::init();
  Gtk::Main kit(argc, argv);

  Glib::RefPtr<Gnome::Glade::Xml> all_da_widgets;

  // load the interface
  all_da_widgets = Gnome::Glade::Xml::create("example-1.glade");

  // Get the main window
  ExampleWindow* window;
  all_da_widgets->get_widget_derived("MainWindow", window);

  // start the event loop
  Gtk::Main::run( *window );

  return 0;
}

GTK2-PERL

The file using the perl language bindings to GTK to make this interface layout into a functioning program is below.

#!/usr/bin/perl -w

# This program monitors the /apps/metacity/general/reduced_resources
# gconf key, and allows the user to change it as well.

use Glib qw(TRUE FALSE);
use Gtk2 '-init';
use Gtk2::GladeXML;
use Gnome2::GConf;

# Just to be pedantic...
use strict;
use vars qw($all_da_widgets);

sub gconf_key_changed_callback
{
  my ($check_button, $new_setting, $old_setting) = @_;

  # Try to handle asynchronous-ness of GConf and prevent calling
  # checkbutton_toggled_callback again if this function was * called
  # as a result of the $client->set_bool function call.
  if ($new_setting != $$old_setting) {
    $$old_setting = $new_setting;
    $check_button->set_active($new_setting);
  }
}

sub checkbutton_toggled_callback
{
  my ($check_button, $client, $old_setting) = @_;

  # Determine whether the checkbutton is already set or not
  my $is_set = $check_button->get_active;
 
  # Try to handle asynchronous-ness of GConf and prevent calling
  # gconf_key_changed_callback again if this function was called as a
  # result of the $check_button->set_active function call.
  if ($is_set != $$old_setting) {
    $$old_setting = $is_set;
    $client->set("/apps/metacity/general/reduced_resources",
                 { type => 'bool', value => $is_set }
                );
  }
}

sub hook_up_callbacks_and_set_defaults
{
  my ($the_widgets) = @_;

  my $old_setting;

  # Get the GconfClient, tell it we want to monitor /apps/metacity/general
  my $client = Gnome2::GConf::Client->get_default;
  $client->add_dir("/apps/metacity/general", 'preload-none');

  # Get the check_button
  my $check_button = $the_widgets->get_widget('Reduced Resources');

  # Determine whether button should start activated or not
  $old_setting = $client->get_bool("/apps/metacity/general/reduced_resources");
  $check_button->set_active($old_setting);

  # Connect the check_button to a callback that can toggle it when the option
  # is changed by some outside program.
  $client->notify_add("/apps/metacity/general/reduced_resources",
                      sub {
                        my ($client, $cnxn_id, $entry) = @_;

                        # Make sure the preference has a valid value
                        return unless $entry->{value} &&
                                      $entry->{value}->{type} eq 'bool';

                        &gconf_key_changed_callback($check_button, 
                                                    $entry->{value}->{value},
                                                    \$old_setting);
                      }
                     );

  # Connect the check_button's clicked callback up so that it can
  # change the gconf setting.
  $check_button->signal_connect( clicked => 
                                 sub { 
                                   &checkbutton_toggled_callback($check_button,
                                                                 $client,
                                                                 \$old_setting);
                                 }
                               );

  # Get the main_window and make the close button quit
  my $main_window = $the_widgets->get_widget('MainWindow');
  $main_window->signal_connect( delete_event => 
                                sub { Gtk2->main_quit; return TRUE; } 
                              );

  # Get the quit button and it to gtk_main_quit
  my $close_button = $the_widgets->get_widget('CloseButton');
  $close_button->signal_connect( clicked => sub { Gtk2->main_quit; } );
}

  # load the interface
  $all_da_widgets = Gtk2::GladeXML->new('example-1.glade');

  # Connect all the signals to the appropriate callbacks
  &hook_up_callbacks_and_set_defaults($all_da_widgets);

  # start the event loop
  Gtk2->main;

  # Return 0, meaning no errors
  0;

PYGTK

The file using the python language bindings to GTK to make this interface layout into a functioning program is below.

#!/usr/bin/env python

# This program monitors the /apps/metacity/general/reduced_resources
# gconf key, and allows the user to change it as well.

import gtk
import gtk.glade
import gconf

class ExampleWindow:
  def __init__(self, glade_file):
    # Parse the glade file
    self.all_da_widgets = gtk.glade.XML(glade_file)

    # Get the GConf::Client, tell it we want to monitor /apps/metacity/general
    self.conf_client = gconf.client_get_default()
    self.conf_client.add_dir("/apps/metacity/general", gconf.CLIENT_PRELOAD_NONE)

    # Get the check_button
    self.checkbutton = self.all_da_widgets.get_widget("Reduced Resources")

    # Connect the check_button to a callback that can toggle it when the option
    # is changed by some outside program.
    self.conf_client.notify_add("/apps/metacity/general/reduced_resources", \
                                self.key_changed);

    # Connect the check_button's clicked callback up so that it can change the
    # gconf setting.
    self.checkbutton.connect("clicked", self.checkbutton_toggled)

    # Determine whether button should start activated or not
    self.old_setting = \
      self.conf_client.get_bool("/apps/metacity/general/reduced_resources")
    self.checkbutton.set_active(self.old_setting)

    # Get the close button and connect it to hide
    close_button = self.all_da_widgets.get_widget("CloseButton")
    close_button.connect("clicked", gtk.mainquit)

    # Get the close button and connect it to hide
    main_window = self.all_da_widgets.get_widget("MainWindow")
    main_window.connect("delete_event", gtk.mainquit)

  def key_changed(self, client, connection_id, entry, args):
    # Make sure the preference has a valid value
    if (entry.get_value().type == gconf.VALUE_BOOL):
      # Get the new value
      new_setting = entry.get_value().get_bool()

      # Try to handle asynchronous-ness of GConf and prevent calling
      # checkbutton_toggled again if this function was called as a
      # result of the self.conf_client.set() function call.
      if (new_setting != self.old_setting):
        self.old_setting = new_setting;
        self.checkbutton.set_active(new_setting);

  def checkbutton_toggled(self, checkbutton_widget):
    # Determine whether the checkbutton is already set or not
    is_set = self.checkbutton.get_active()
 
    # Try to handle asynchronous-ness of GConf and prevent calling
    # key_changed again if this function was called as a result of the
    # self.checkbutton.set_active() function call.
    if (is_set != self.old_setting):
      self.old_setting = is_set
      self.conf_client.set_bool("/apps/metacity/general/reduced_resources", \
                                is_set)

# Create the ExampleWindow
window = ExampleWindow("example-1.glade")

# start the event loop
gtk.main()