Example 4

An example that has a preferences window with three tabs and an alternate window that can come up when the user exits is shown below.

GTK

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

/* This program shows a preferences window, which contains
 * RadioButtons, a color selection widget, and a font selection
 * widget.  It does manual signal connection the gtk way (as opposed
 * to either the automatic libglade way or the manual libglade way,
 * the latter of which is sort of ugly IMO), pops up a (modal) window
 * to confirm whether the user really wants to exit, demonstrates how
 * to use pango markup, and shows how to manually free the memory
 * used by widgets when they're not wanted any more.
 */

#include <gtk/gtk.h>
#include <glade/glade.h>
#include <stdio.h>

/* A bunch of data to be set and used in the callbacks */
typedef struct _QuitData QuitData;
struct _QuitData
{
  GtkFontSelection* font_selection;
  GtkDialog       * annoying_confirmation_window;
  GtkLabel        * warning_label;
  GdkColor          color;
  gchar             location[10];
};

void
new_location_selected (GtkWidget *widget, gpointer data)
{
  QuitData * quit_choices = (QuitData*) data;

  /* Copy the widget name to quit_choices->location */
  snprintf(quit_choices->location, 10, gtk_widget_get_name (widget));
}

void
new_color_selected (GtkWidget *widget, gpointer data)
{
  QuitData * quit_choices = (QuitData*) data;
  gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (widget),
                                         &quit_choices->color);
}

/* This simple helper function which converts an RGB triplet (which is
 * part of a GdkColor) into a "#RRGGBB" string.
 */
void
convert_color_to_string (GdkColor * color, gchar * color_string)
{
  color_string[0] = '#';

  /* GdkColor stores its red, green, and blue as 0..65536 instead of 0..256 */
  sprintf(&color_string[1], "%.2X", color->red  /256);
  sprintf(&color_string[3], "%.2X", color->green/256);
  sprintf(&color_string[5], "%.2X", color->blue /256);
}

/* This makes the confirmation window pop up to ask the user if they really
 * want to quit.  The message to the user changes slightly depending on the
 * preferences they had set.
 */
void
time_to_quit (GtkWidget *widget, gpointer data)
{
  QuitData * quit_choices = (QuitData*) data;

  /* Create a color string of the form #RRGGBB, where R, G, & B are hex digits */
  gchar color_string[8];
  convert_color_to_string(&quit_choices->color, color_string);

  /* Get the warning message, and find where we want to modify it */
  const gchar * message = gtk_label_get_label (quit_choices->warning_label);
  gchar * end_span = g_strrstr (message, "span");
  gchar * beg_span = g_strrstr_len (message, end_span-message, "span");

  /* Now, modify the string--namely the second span markup stuff */
  GString * new_message = g_string_new(NULL);
  g_string_append_len(new_message, message, beg_span-message-1);
  g_string_append_printf(new_message,
                         "<span font_desc=\"%s\" foreground=\"%s\">%s</span>",
                         gtk_font_selection_get_font_name (quit_choices->
                                                           font_selection),
                         color_string,
                         quit_choices->location);
  g_string_append_printf(new_message, "%s", end_span+5);

  /* Update the label and free our temporary string */
  gtk_label_set_label (quit_choices->warning_label, new_message->str);
  g_string_free (new_message, TRUE);

  /* Make sure the confirmation window is shown */
  gtk_widget_show (GTK_WIDGET (quit_choices->annoying_confirmation_window));
}

/* This exists simply because delete_event and clicked signals require different
 * numbers of arguments and return types.  This just calls time_to_quit.
 */
gboolean
time_to_quit_dumb_events (GtkWidget *widget, GdkEvent *event, gpointer data)
{
  time_to_quit (widget, data);
  return TRUE;
}

/* clean_up merely frees the data being passed around to all the callbacks */
void
clean_up (GtkWidget *widget, gpointer data)
{
  QuitData * quit_choices = (QuitData*) data;
  g_free(quit_choices);
}

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

  /* Get the preferences and confirmation windows */
  GtkWidget *preferences  = glade_xml_get_widget (the_widgets, "MainWindow");
  GtkWidget *are_you_sure = glade_xml_get_widget (the_widgets, "ConfirmClose");
  GtkWidget *font_sel     = glade_xml_get_widget (the_widgets, "FontSelection");

  /* FIRST, allocate some data needed by callbacks and initialize some of it. */

  QuitData * the_data = (QuitData*)malloc (sizeof (QuitData));
  the_data->font_selection = GTK_FONT_SELECTION (font_sel);
  the_data->annoying_confirmation_window = GTK_DIALOG (are_you_sure);
  sprintf(the_data->location, "undefined");

  /* SECOND, we handle setting up defaults and connect callbacks for
   * the confirmation window.
   */

  /* Have the delete event (window close) do nothing */
  g_signal_connect (G_OBJECT (are_you_sure), "delete_event",
                    G_CALLBACK (gtk_true), NULL);

  /* Have the cancel button hide the confirmation window */
  widget = glade_xml_get_widget (the_widgets, "CancelButton");
  g_signal_connect_swapped (G_OBJECT (widget), "clicked",
                            G_CALLBACK (gtk_widget_hide),
                            G_OBJECT (are_you_sure));

  /* Have the "Exit anyway" button close everything */
  widget = glade_xml_get_widget (the_widgets, "ExitButton");
  g_signal_connect (G_OBJECT (widget), "clicked",
                    G_CALLBACK (gtk_main_quit), NULL);

  /* Get the warning label so we can modify it later. */
  GtkWidget *info_label = glade_xml_get_widget (the_widgets, "InfoLabel");
  the_data->warning_label = GTK_LABEL (info_label);

  /* Make the window start hidden */
  gtk_widget_hide (are_you_sure);

  /* THIRD, we handle setting up defaults and connect callbacks for
   * the preferences window.
   */

  /* Keep track of when the location changes */
  widget = glade_xml_get_widget (the_widgets, "Here");
  g_signal_connect (G_OBJECT (widget), "toggled",
                    G_CALLBACK (new_location_selected),
                    (gpointer)the_data);
  widget = glade_xml_get_widget (the_widgets, "There");
  g_signal_connect (G_OBJECT (widget), "toggled",
                    G_CALLBACK (new_location_selected),
                    (gpointer)the_data);
  /* Make 'There' be the default; note this also emits the toggled signal */
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);

  /* Keep track of when the color changes */
  widget = glade_xml_get_widget (the_widgets, "ColorSelection");
  g_signal_connect (G_OBJECT (widget), "color_changed",
                    G_CALLBACK (new_color_selected),
                    (gpointer)the_data);
  /* Set the default to whatever the ColorSelection widget defaults to */
  gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (widget),
                                         &the_data->color);
  /* Turn off the opacity slider */
  gtk_color_selection_set_has_opacity_control (GTK_COLOR_SELECTION (widget),
                                               FALSE);

  /* Have the quit button show the confirmation window */
  widget = glade_xml_get_widget (the_widgets, "QuitButton");
  g_signal_connect (G_OBJECT (widget), "clicked",
                    G_CALLBACK (time_to_quit),
                    (gpointer)the_data);

  /* Have the delete event (window close) also show the confirmation window */
  g_signal_connect (G_OBJECT (preferences), "delete_event",
                    G_CALLBACK (time_to_quit_dumb_events),
                    (gpointer)the_data);

  /* Have the destroy signal call the cleanup callback, to free the_data */
  g_signal_connect (G_OBJECT (preferences), "destroy",
                    G_CALLBACK (clean_up),
                    (gpointer)the_data);
}

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

  gtk_init (&argc, &argv);

  /* load the interface */
  all_da_widgets = glade_xml_new ("example-4.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 ();

  /* Free the memory used by the widgets we're no longer using */
  gtk_widget_destroy( glade_xml_get_widget (all_da_widgets, "MainWindow"));
  gtk_widget_destroy( glade_xml_get_widget (all_da_widgets, "ConfirmClose"));

  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 PreferencesWindow.h header file:

#ifndef PREFERENCES_WINDOW_H
#define PREFERENCES_WINDOW_H

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

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

protected:
  virtual bool on_delete_event(GdkEventAny* event);
  void         cancel_button_pressed();
  void         new_location_selected(Glib::ustring location);
  void         new_color_selected();
  void         time_to_quit();

  Glib::ustring        d_location;
  Gtk::ColorSelection* d_color_sel;
  Gtk::FontSelection*  d_font_sel;
  Gdk::Color           d_color;
  Gtk::Dialog*         d_confirm_close;
  Gtk::Label*          d_warning_label;
};

#endif // PREFERENCES_WINDOW_H

Next is the PreferencesWindow.cc file:

#include "PreferencesWindow.h"
#include <iostream>

using namespace std;

static bool
do_nothing(GdkEventAny* event)
{
  // Return true to signify that this event has been fully handled
  return true;
}

PreferencesWindow::PreferencesWindow(
  BaseObjectType* base_object,
  const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml)
  : Gtk::Window(base_object)
{
  //
  // FIRST, get the widgets I want to track
  //

  // Get the widgets I'm interested in
  glade_xml->get_widget("ColorSelection", d_color_sel);
  glade_xml->get_widget("FontSelection",  d_font_sel);
  glade_xml->get_widget("ConfirmClose",   d_confirm_close);
  glade_xml->get_widget("InfoLabel",      d_warning_label);
  // Initialize the color and location to "not-yet-known" values
  d_location = "undefined";
  d_color.set_rgb(0,0,0);


  //
  // SECOND, we handle setting up defaults and connect callbacks for
  // the confirmation window.
  //

  // Have the confirm-closing window's delete event (window close) do nothing
  d_confirm_close->signal_delete_event().connect(sigc::ptr_fun(&do_nothing));

  // Have the cancel button hide the confirmation window
  Gtk::Button* cancel_button;
  glade_xml->get_widget("CancelButton", cancel_button);
  cancel_button->signal_clicked().connect(
    sigc::mem_fun(*this, &PreferencesWindow::cancel_button_pressed) );

  // Have the "Exit anyway" button hide the Preferences window (which has the
  // result of closing everything
  Gtk::Button* exit_button;
  glade_xml->get_widget("ExitButton", exit_button);
  exit_button->signal_clicked().connect(
    sigc::mem_fun(*this, &Gtk::Widget::hide));

  // Make the confirm-closing window start hidden
  d_confirm_close->hide();


  //
  // THIRD, we handle setting up defaults and connect callbacks for
  // the preferences window.
  //

  // Keep track of when the location changes
  Gtk::CheckButton* here = 
    dynamic_cast<Gtk::CheckButton*>(glade_xml->get_widget("Here"));
  here->signal_toggled().connect(
    sigc::bind<Glib::ustring>(
      sigc::mem_fun(*this, &PreferencesWindow::new_location_selected),
      "Here")
    );
  Gtk::CheckButton* there = 
    dynamic_cast<Gtk::CheckButton*>(glade_xml->get_widget("There"));
  there->signal_toggled().connect(
    sigc::bind<Glib::ustring>(
      sigc::mem_fun(*this, &PreferencesWindow::new_location_selected),
      "There")
    );

  // Make 'There' be the default; note this also emits the toggled signal
  there->set_active();

  // Keep track of when the color changes
  d_color_sel->signal_color_changed().connect(
    sigc::mem_fun(*this, &PreferencesWindow::new_color_selected));
  // Set the default to whatever the ColorSelection widget defaults to
  d_color = d_color_sel->get_current_color();  
  // Turn off the opacity slider
  d_color_sel->set_has_opacity_control(false);

  // Have the quit button show the confirmation window
  Gtk::Button* quit_button =
    dynamic_cast<Gtk::Button*>(glade_xml->get_widget("QuitButton"));
  quit_button->signal_clicked().connect(
    sigc::mem_fun(*this, &PreferencesWindow::time_to_quit));

  // Delete event taken care of by overriding the on_delete_event function...  
  // Destroy even taken care of by destructor...
}

PreferencesWindow::~PreferencesWindow()
{
}

void
PreferencesWindow::cancel_button_pressed()
{
  d_confirm_close->hide();
}

void
PreferencesWindow::new_location_selected(Glib::ustring location)
{
  d_location = location;
}

void
PreferencesWindow::new_color_selected()
{
  d_color = d_color_sel->get_current_color();  
}

// This simple helper function which converts an RGB triplet (which is
// part of a GdkColor) into a "#RRGGBB" string.
static Glib::ustring
convert_color_to_string (Gdk::Color & color)
{
  char color_string[8];

  color_string[0] = '#';

  // Gdk::Color stores its red, green, and blue as 0..65536 instead of 0..256
  sprintf(&color_string[1], "%.2X", color.get_red()  /256);
  sprintf(&color_string[3], "%.2X", color.get_green()/256);
  sprintf(&color_string[5], "%.2X", color.get_blue() /256);

  return color_string;
}

void
PreferencesWindow::time_to_quit()
{
  // Create a color string of the form #RRGGBB, where R, G, & B are hex digits
  Glib::ustring color = convert_color_to_string(d_color);

  // Get the warning message, and find where we want to modify it
  Glib::ustring message = d_warning_label->get_label();
  Glib::ustring::size_type end_span = message.rfind("span");
  Glib::ustring::size_type beg_span = message.rfind("span", end_span-1);

  // Set up the replacement text.  Note that we basically found the two
  // places where the letter 's' in span was in a string of the form 
  //   <span bla bla bla...>yadda yadda yadda...</span>
  // Now, we are just replacing all the stuff between those two s's.
  // (And yeah, I should really check out the String Composition)
  // (Library at  http://www.cs.auc.dk/~olau/compose/   but I'm )
  // (lazy and will use sprintf for now.                        )
  char replacement_text[500];
  sprintf(replacement_text, "span font_desc=\"%s\" foreground=\"%s\">%s</",
          d_font_sel->get_font_name().c_str(),
          color.c_str(),
          d_location.c_str());

  // Make the new message and update the label
  message.replace(beg_span, end_span-beg_span, replacement_text);
  d_warning_label->set_label(message);

  // Make sure the confirmation window is shown
  d_confirm_close->show();
}

bool
PreferencesWindow::on_delete_event(GdkEventAny* event)
{
  time_to_quit();

  // No other handlers need be called...
  return true;
}

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

/* This program shows a preferences window, which contains
 * RadioButtons, a color selection widget, and a font selection
 * widget.  It pops up a (modal) window to confirm whether the user
 * really wants to exit, demonstrates how to use pango markup, and
 * shows how to manually free the memory used by widgets when they're
 * not wanted any more.
 */

#include <gtkmm.h>
#include <libglademm/xml.h>
#include "PreferencesWindow.h"

using namespace std;

int
main (int argc, char *argv[])
{
  Glib::RefPtr<Gnome::Glade::Xml> all_da_widgets;
  Gtk::Main kit(argc, argv);

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

  // Get the main window
  PreferencesWindow* 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 shows a preferences window, which contains
# RadioButtons, a color selection widget, and a font selection widget.
# It demonstrates the use of anonymous perl subroutines to serve as
# callbacks including using them as a method of passing extra or
# different parameters to the real callback, pops up a (modal) window
# to confirm whether the user really wants to exit, and demonstrates
# how to use pango markup.

use Glib qw(TRUE FALSE);
use Gtk2 '-init';
use Gtk2::GladeXML;
use POSIX qw(floor);

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

sub convert_color_to_string
{
  my ($color) = @_;
  my ($color_string);

  $color_string = "#"
                  . sprintf("%.2X", floor($color->red  /256))
                  . sprintf("%.2X", floor($color->green/256))
                  . sprintf("%.2X", floor($color->blue /256));

  return $color_string;
}

sub time_to_quit
{
  my ($font_selection, $confirm_close, $warning_label, $color, $location) = @_;

  my ($color_string, $message, $replacement_text);

  # Create a color string of the form #RRGGBB, where R, G, & B are hex digits
  $color_string = &convert_color_to_string($color);

  # Get the warning message
  $message = $warning_label->get_label;

  # Set up the replacement text.
  $replacement_text = '<span '
    . 'font_desc="'  . $font_selection->get_font_name . '" '
    . 'foreground="' . $color_string                  . '">'
    . $location
    . '</span>';

  # Make the new message
  $message =~ s/to <span.*<\/span>/to $replacement_text/;

  # Update the label
  $warning_label->set_label($message);

  # Make sure the confirmation window is shown
  $confirm_close->show;
}

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

  my ($preferences, $are_you_sure, $font_sel, $info_label, $location);

  # Get the preferences and confirmation windows
  $preferences  = $the_widgets->get_widget('MainWindow');
  $are_you_sure = $the_widgets->get_widget('ConfirmClose');
  $font_sel     = $the_widgets->get_widget('FontSelection');

  # First, we handle setting up defaults and connect callbacks for
  # the confirmation window.

  # Have the delete event (window close) do nothing
  $are_you_sure->signal_connect( delete_event => sub { return TRUE; } );

  # Have the cancel button hide the confirmation window
  my $cancel_button = $the_widgets->get_widget('CancelButton');
  $cancel_button->signal_connect( clicked => sub {$are_you_sure->hide;} );

  # Have the "Exit anyway" button close everything
  my $exit_button = $the_widgets->get_widget('ExitButton');
  $exit_button->signal_connect( clicked => sub {Gtk2->main_quit;} );

  # Get the warning label so we can modify it later.
  $info_label = $the_widgets->get_widget('InfoLabel');

  # Make the confirm-close window starts hidden
  $are_you_sure->hide;

  # Second, we handle setting up defaults and connect callbacks for
  # the preferences window.

  # Keep track of when the location changes
  my $here_toggle = $the_widgets->get_widget('Here');
  $here_toggle->signal_connect( toggled => 
                                sub{$location = $here_toggle->get_name;} 
                              );
  my $there_toggle = $the_widgets->get_widget('There');
  $there_toggle->signal_connect( toggled => 
                                 sub{$location = $there_toggle->get_name;} 
                               );
  # Make 'There' be the default; note this also emits the toggled signal
  $there_toggle->set_active(TRUE);

  # Get the color selection widget
  my $color_widget = $the_widgets->get_widget('ColorSelection');

  # Set the default to whatever the ColorSelection widget defaults to
  my $color = $color_widget->get_current_color;

  # Keep track of when the color changes
  $color_widget->signal_connect( color_changed => 
                                 sub {$color=$color_widget->get_current_color;}
                               );

  # Turn off the opacity slider
  $color_widget->set_has_opacity_control(FALSE);

  # Have the quit button show the confirmation window
  my $quit_button = $the_widgets->get_widget('QuitButton');
  $quit_button->signal_connect( clicked => 
    sub {
      &time_to_quit($font_sel, $are_you_sure, $info_label, $color, $location);
    }
    );

  # Have the delete event (window close) also show the confirmation window
  $preferences->signal_connect( delete_event => 
    sub {
      &time_to_quit($font_sel, $are_you_sure, $info_label, $color, $location);
      return TRUE;
    }
    );
}


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

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

  # start the event loop
  Gtk2->main;

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 shows a preferences window, which contains
# RadioButtons, a color selection widget, and a font selection widget.
# It does manual signal connection the pygtk way (as opposed to either
# the autoconnect libglade method), pops up a (modal) window to
# confirm whether the user really wants to exit, and demonstrates how
# to use pango markup.

import gtk
import gtk.glade
import re

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

    #
    # FIRST, get the widgets I want to track
    #

    # Get the widgets I'm interested in
    self.preferences   = self.all_da_widgets.get_widget("MainWindow")
    self.color_sel     = self.all_da_widgets.get_widget("ColorSelection")
    self.font_sel      = self.all_da_widgets.get_widget("FontSelection")
    self.confirm_close = self.all_da_widgets.get_widget("ConfirmClose")
    self.warning_label = self.all_da_widgets.get_widget("InfoLabel")
    # Initialize the color and location to "not-yet-known" values
    self.location = "undefined"
    self.color = gtk.gdk.Color(0,0,0)

    #
    # SECOND, we handle setting up defaults and connect callbacks for
    # the confirmation window.
    #

    # Have the confirm-closing window's delete event (window close) do nothing
    self.confirm_close.connect("delete_event", self.do_nothing);

    # Have the cancel button hide the confirmation window
    cancel_button = self.all_da_widgets.get_widget("CancelButton")
    cancel_button.connect("clicked", self.cancel_button_pressed)

    # Have the "Exit anyway" button close everything
    exit_button = self.all_da_widgets.get_widget("ExitButton")
    exit_button.connect("clicked", gtk.mainquit)

    # Make the confirm-closing window start hidden
    self.confirm_close.hide()

    #
    # THIRD, we handle setting up defaults and connect callbacks for
    # the preferences window.
    #

    # Keep track of when the location changes
    here = self.all_da_widgets.get_widget("Here")
    here.connect("toggled", self.new_location_selected, "Here")
    there = self.all_da_widgets.get_widget("There")
    there.connect("toggled", self.new_location_selected, "There")

    # Make 'There' be the default; note this also emits the toggled signal
    there.set_active(gtk.TRUE)

    # Keep track of when the color changes
    self.color_sel.connect("color_changed", self.new_color_selected)
    # Set the default to whatever the ColorSelection widget defaults to
    self.color = self.color_sel.get_current_color()
    # Turn off the opacity slider
    self.color_sel.set_has_opacity_control(gtk.FALSE)

    # Have the quit button show the confirmation window
    quit_button = self.all_da_widgets.get_widget("QuitButton")
    quit_button.connect("clicked", self.time_to_quit)

    # Delete event taken care of by overriding the on_delete_event function...
    self.preferences.connect("delete_event", self.call_time_to_quit)

  def do_nothing(self,confirmation_dialog,event):
    # Return true to signify that this event has been fully handled
    return gtk.TRUE

  def cancel_button_pressed(self, cancel_button):
    self.confirm_close.hide()

  def new_location_selected(self, radio_button, location):
    self.location = location

  def new_color_selected(self, color_selection_widget):
    self.color = self.color_sel.get_current_color()

  def convert_color_to_string(self, color):
    """
    This simple helper function which converts an RGB triplet (which is
    part of a Gdk.Color) into a "#RRGGBB" string.
    """
    color_string = "#%.2X%.2X%.2X" % \
                   (color.red/256,color.green/256,color.blue/256)
    return color_string

  def time_to_quit(self, ignored_widget):
    color_string = self.convert_color_to_string(self.color);

    # Get the warning message
    message = self.warning_label.get_label()

    # Set up the replacement text.
    replacement_text = '<span '                                \
      + 'font_desc="'  + self.font_sel.get_font_name() + '" '  \
      + 'foreground="' + color_string                  + '">'  \
      + self.location                                          \
      + '</span>'

    # Make the new message
    old_regex = re.compile(r'to <span.*<\/span>')
    message = old_regex.sub("to " + replacement_text, message)

    # Update the label
    self.warning_label.set_label(message)

    # Make sure the confirmation window is shown
    self.confirm_close.show()

  def call_time_to_quit(self, window, event):
    self.time_to_quit(window)

    # No other handlers need be called...
    return gtk.TRUE

# Create the PreferencesWindow
window = PreferencesWindow("example-4.glade")

# start the event loop
gtk.main()