An example that shows how to monitor and set a couple Nautilus preferences 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="GtkWindow" id="MainWindow">
<property name="visible">True</property>
<property name="title" translatable="yes">Nautilus Preferences</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>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="n_rows">3</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">0</property>
<child>
<widget class="GtkLabel" id="ShowThumbnailsLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Show Image Thumnails:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="ThumbnailLimitLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Thumbnail Size Limit:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="ShowThumbnailsEntry">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">When to show thumbnails, "never", "local_only", or "always"</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char" translatable="yes">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="ThumbnailLimitEntry">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Largest picture size (in bytes) that will be thumbnailed</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char" translatable="yes">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="BrowserMode">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Whether to use the old Browser mode, or the newer "each directory in a separate window" spatilus mode</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Always use _browser mode</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="left_attach">0</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">7</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<property name="spacing">0</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>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
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/nautilus/preferences/always_use_browser,
* /apps/nautilus/preferences/show_image_thumbnails, and
* /apps/nautilus/preferences/thumbnail_limit gconf keys, and allows
* the user to change them as well.
*/
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <gconf/gconf-client.h>
static gboolean old_browser_setting;
static gchar* old_show_thumbnails_setting;
static gint old_thumbnail_limit;
/*********** callbacks for always_use_browser **********/
void
gconf_browser_key_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_browser_setting =
gconf_value_get_bool (gconf_entry_get_value (entry));
/* Try to handle asynchronous-ness of GConf and prevent calling
* browser_key_toggled_callback again if this function was
* called as a result of the gconf_client_set_bool function
* call.
*/
if (new_browser_setting != old_browser_setting)
{
old_browser_setting = new_browser_setting;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
new_browser_setting);
}
}
}
void
browser_key_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_browser_key_callback again if this function was called as a
* result of the gtk_toggle_button_set_active function call.
*/
if (is_set != old_browser_setting)
{
old_browser_setting = is_set;
gconf_client_set_bool (client,
"/apps/nautilus/preferences/always_use_browser",
is_set,
NULL);
}
}
/*********** callbacks for show_image_thumbnails **********/
void
gconf_show_thumbnails_callback (GConfClient* client,
guint cnxn_id,
GConfEntry* entry,
gpointer user_data)
{
GtkWidget* show_entry;
show_entry = GTK_WIDGET (user_data);
/* Make sure the preference has a string */
if (gconf_entry_get_value (entry) != NULL &&
gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
{
/* Get the new value */
const gchar* new_setting =
gconf_value_get_string (gconf_entry_get_value (entry));
/* Check if it seems valid, give a warning if it doesn't */
if (strcmp(new_setting, "always") != 0 &&
strcmp(new_setting, "local_only") != 0 &&
strcmp(new_setting, "never") != 0)
{
g_warning("Unrecognized value specified by external program...\n");
}
/* Use the new value if it's different than the old */
if (strcmp(new_setting,old_show_thumbnails_setting) != 0)
{
strcpy(old_show_thumbnails_setting, new_setting);
gtk_entry_set_text (GTK_ENTRY (show_entry), new_setting);
}
}
}
void
show_thumbnails_changed_callback (GtkWidget* show_entry, gpointer user_data)
{
GConfClient* client = GCONF_CLIENT (user_data);
/* Get the current value */
const gchar* cur_value =
gtk_entry_get_text (GTK_ENTRY (show_entry));
if (strcmp(cur_value, "always") == 0 ||
strcmp(cur_value, "local_only") == 0 ||
strcmp(cur_value, "never") == 0)
{
if (strcmp(cur_value, old_show_thumbnails_setting) != 0)
{
strcpy(old_show_thumbnails_setting, cur_value);
gconf_client_set_string (client,
"/apps/nautilus/preferences/show_image_thumbnails",
cur_value,
NULL);
}
}
else
{
g_warning("This program needs an error window to warn you that you typed an invalid value.\n");
gtk_entry_set_text (GTK_ENTRY (show_entry), old_show_thumbnails_setting);
}
}
/*********** callbacks for thumbnail_limit **********/
void
gconf_thumbnail_limit_callback (GConfClient* client,
guint cnxn_id,
GConfEntry* entry,
gpointer user_data)
{
GtkWidget* limit_entry;
limit_entry = GTK_WIDGET (user_data);
/* Make sure the preference has a string */
if (gconf_entry_get_value (entry) != NULL &&
gconf_entry_get_value (entry)->type == GCONF_VALUE_INT)
{
/* Get the new value */
gint new_value =
gconf_value_get_int (gconf_entry_get_value (entry));
/* Warn if the value seems invalid */
if (new_value < 0)
{
g_warning("Bad value seems to have been set by external program.\n");
}
if (new_value != old_thumbnail_limit)
{
old_thumbnail_limit = new_value;
gchar temp_string[20];
sprintf(temp_string, "%d", old_thumbnail_limit);
gtk_entry_set_text (GTK_ENTRY (limit_entry), temp_string);
}
}
}
void
thumbnail_limit_changed_callback (GtkWidget* limit_entry, gpointer user_data)
{
GConfClient* client = GCONF_CLIENT (user_data);
/* Get the current value */
const gchar* cur_value =
gtk_entry_get_text (GTK_ENTRY (limit_entry));
gboolean is_numeric = TRUE;
const gchar* temp_copy = cur_value;
while (g_ascii_isdigit (*temp_copy++))
;
temp_copy--;
if (*temp_copy)
is_numeric = FALSE;
gint new_value = 0;
if (is_numeric)
new_value = atoi(cur_value);
if (is_numeric && new_value >= 0)
{
if (new_value != old_thumbnail_limit)
{
old_thumbnail_limit = new_value;
gconf_client_set_int (client,
"/apps/nautilus/preferences/thumbnail_limit",
new_value,
NULL);
}
}
else
{
g_warning("This program needs an error window to warn you that you typed an invalid value.\n");
gchar temp_string[20];
sprintf(temp_string, "%d", old_thumbnail_limit);
gtk_entry_set_text (GTK_ENTRY (limit_entry), temp_string);
}
}
void
hook_up_callbacks_and_set_defaults (GladeXML * the_widgets)
{
GtkWidget *widget;
/* Get the GConfClient, tell it we want to monitor /apps/nautilus/preferences*/
GConfClient* client = gconf_client_get_default();
gconf_client_add_dir(client,
"/apps/nautilus/preferences",
GCONF_CLIENT_PRELOAD_NONE,
NULL);
/* First, setup the checkbutton for the always_use_browser key */
/* Get the check_button */
widget = glade_xml_get_widget (the_widgets, "BrowserMode");
/* 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/nautilus/preferences/always_use_browser",
gconf_browser_key_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 (browser_key_toggled_callback), client);
/* Determine whether button should start activated or not */
old_browser_setting =
gconf_client_get_bool (client,
"/apps/nautilus/preferences/always_use_browser",
NULL);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), old_browser_setting);
/* Second, setup the text entry for the show_image_thumbnails key */
/* Get the Entry */
widget = glade_xml_get_widget (the_widgets, "ShowThumbnailsEntry");
/* Connect the show thumbnail entry to a callback that can toggle it
* when the option is changed by some outside program.
*/
gconf_client_notify_add(client,
"/apps/nautilus/preferences/show_image_thumbnails",
gconf_show_thumbnails_callback,
widget,
NULL,
NULL);
/* Connect the show thumbnail entry's activated callback up so that
* it can change the gconf setting.
*/
g_signal_connect(G_OBJECT (widget), "activate",
G_CALLBACK (show_thumbnails_changed_callback), client);
/* Make space for storing the old value of the old show_thumbnails setting */
old_show_thumbnails_setting = (gchar*)malloc(sizeof(gchar[20]));
/* FIXME: Not necessary, but might consider freeing this later... */
/* Determine the starting value of this key */
const gchar* old_value =
gconf_client_get_string (client,
"/apps/nautilus/preferences/show_image_thumbnails",
NULL);
strcpy(old_show_thumbnails_setting, old_value);
gtk_entry_set_text (GTK_ENTRY (widget), old_show_thumbnails_setting);
/* Third, setup the text entry for the thumbnail_limit key */
/* Get the Entry */
widget = glade_xml_get_widget (the_widgets, "ThumbnailLimitEntry");
/* Connect the thumbnail limit entry to a callback that can toggle
* it when the option is changed by some outside program.
*/
gconf_client_notify_add(client,
"/apps/nautilus/preferences/thumbnail_limit",
gconf_thumbnail_limit_callback,
widget,
NULL,
NULL);
/* Connect the thumbnail limit entry's activated callback up so that
* it can change the gconf setting.
*/
g_signal_connect(G_OBJECT (widget), "activate",
G_CALLBACK (thumbnail_limit_changed_callback), client);
/* Determine the starting value of this key */
old_thumbnail_limit =
gconf_client_get_int (client,
"/apps/nautilus/preferences/thumbnail_limit",
NULL);
gchar temp_string[20];
sprintf(temp_string, "%d", old_thumbnail_limit);
gtk_entry_set_text (GTK_ENTRY (widget), temp_string);
/* 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-2.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;
}
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 browser_key_changed(guint cnxn_id, Gnome::Conf::Entry entry);
void browser_key_toggled();
void show_thumbnails_key_changed(guint cnxn_id, Gnome::Conf::Entry entry);
void show_thumbnails_modified();
void thumbnail_limit_key_changed(guint cnxn_id, Gnome::Conf::Entry entry);
void thumbnail_limit_modified();
Glib::RefPtr<Gnome::Conf::Client> d_conf_client;
Gtk::CheckButton* d_browser_checkbutton;
bool d_old_browser_setting;
Gtk::Entry* d_show_thumbnail_entry;
Glib::ustring d_old_show_thumbnails_setting;
Gtk::Entry* d_thumbnail_limit_entry;
gint d_old_thumbnail_limit;
};
#endif // EXAMPLE_WINDOW_H
Next is the ExampleWindow.cc file:
#include "ExampleWindow.h"
#include <sstream>
ExampleWindow::ExampleWindow(
BaseObjectType* base_object,
const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml)
: Gtk::Window(base_object)
{
// Get the client and tell it we want to monitor /apps/nautilus/preferences
d_conf_client = Gnome::Conf::Client::get_default_client();
d_conf_client->add_dir("/apps/nautilus/preferences");
/* First, setup the checkbutton for the always_use_browser key */
// Get the check_button
glade_xml->get_widget("BrowserMode", d_browser_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/nautilus/preferences/always_use_browser",
sigc::mem_fun(*this, &ExampleWindow::browser_key_changed)
);
// Connect the check_button's clicked callback up so that it can change the
// gconf setting.
d_browser_checkbutton->signal_clicked().connect(
sigc::mem_fun(*this, &ExampleWindow::browser_key_toggled) );
// Determine whether button should start activated or not
d_old_browser_setting =
d_conf_client->get_bool("/apps/nautilus/preferences/always_use_browser");
d_browser_checkbutton->set_active(d_old_browser_setting);
/* Second, setup the text entry for the show_image_thumbnails key */
// Get the Entry
glade_xml->get_widget("ShowThumbnailsEntry", d_show_thumbnail_entry);
// Connect the show thumbnail entry to a callback that can toggle it
// when the option is changed by some outside program.
d_conf_client->notify_add(
"/apps/nautilus/preferences/show_image_thumbnails",
sigc::mem_fun(*this, &ExampleWindow::show_thumbnails_key_changed)
);
// Connect the show thumbnail entry's activated callback up so that
// it can change the gconf setting.
d_show_thumbnail_entry->signal_activate().connect(
sigc::mem_fun(*this, &ExampleWindow::show_thumbnails_modified) );
// Determine the starting value of this key
d_old_show_thumbnails_setting =
d_conf_client->get_string(
"/apps/nautilus/preferences/show_image_thumbnails");
d_show_thumbnail_entry->set_text(d_old_show_thumbnails_setting);
/* Third, setup the text entry for the thumbnail_limit key */
// Get the Entry
glade_xml->get_widget("ThumbnailLimitEntry", d_thumbnail_limit_entry);
// Connect the thumbnail limit entry to a callback that can toggle
// it when the option is changed by some outside program.
d_conf_client->notify_add(
"/apps/nautilus/preferences/thumbnail_limit",
sigc::mem_fun(*this, &ExampleWindow::thumbnail_limit_key_changed)
);
// Connect the thumbnail limit entry's activated callback up so that
// it can change the gconf setting.
d_thumbnail_limit_entry->signal_activate().connect(
sigc::mem_fun(*this, &ExampleWindow::thumbnail_limit_modified) );
// Determine the starting value of this key
d_old_thumbnail_limit =
d_conf_client->get_int("/apps/nautilus/preferences/thumbnail_limit");
gchar temp_string[20];
sprintf(temp_string, "%d", d_old_thumbnail_limit);
d_thumbnail_limit_entry->set_text(temp_string);
// 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::browser_key_changed(guint cnxn_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_browser_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_browser_setting != d_old_browser_setting) {
d_old_browser_setting = new_browser_setting;
d_browser_checkbutton->set_active(new_browser_setting);
}
}
}
void
ExampleWindow::browser_key_toggled()
{
// Determine whether the checkbutton is already set or not
bool is_set = d_browser_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_browser_setting) {
d_old_browser_setting = is_set;
d_conf_client->set("/apps/nautilus/preferences/always_use_browser", is_set);
}
}
void
ExampleWindow::show_thumbnails_key_changed(
guint cnxn_id,
Gnome::Conf::Entry entry)
{
// Make sure the preference has a valid value
if (entry.get_value().get_type() == Gnome::Conf::VALUE_STRING) {
// Get the new value
Glib::ustring new_setting = entry.get_value().get_string();
// Check if it seems valid, give a warning if it doesn't
if ((new_setting != "always") &&
(new_setting != "local_only") &&
(new_setting != "never"))
{
g_warning("Unrecognized value specified by external program...\n");
}
// Use the new value if it's different than the old
if (new_setting != d_old_show_thumbnails_setting) {
d_old_show_thumbnails_setting = new_setting;
d_show_thumbnail_entry->set_text(new_setting);
}
}
}
void
ExampleWindow::show_thumbnails_modified()
{
// Get the current value
Glib::ustring cur_value = d_show_thumbnail_entry->get_text();
if ((cur_value == "always") ||
(cur_value == "local_only") ||
(cur_value == "never")) {
if (cur_value != d_old_show_thumbnails_setting) {
d_old_show_thumbnails_setting = cur_value;
d_conf_client->set("/apps/nautilus/preferences/show_image_thumbnails",
cur_value);
}
} else {
g_warning("This program needs an error window to warn you that you typed an invalid value.\n");
d_show_thumbnail_entry->set_text(d_old_show_thumbnails_setting);
}
}
void
ExampleWindow::thumbnail_limit_key_changed(
guint cnxn_id,
Gnome::Conf::Entry entry)
{
// Make sure the preference has a valid value
if (entry.get_value().get_type() == Gnome::Conf::VALUE_INT) {
// Get the new value
gint new_value = entry.get_value().get_int();
// Check if it seems valid, give a warning if it doesn't
if (new_value < 0) {
g_warning("Bad value seems to have been set by external program.\n");
}
// Use the new value if it's different than the old
if (new_value != d_old_thumbnail_limit) {
d_old_thumbnail_limit = new_value;
gchar temp_string[20];
sprintf(temp_string, "%d", d_old_thumbnail_limit);
d_thumbnail_limit_entry->set_text(temp_string);
}
}
}
void
ExampleWindow::thumbnail_limit_modified()
{
// Get the current value
Glib::ustring cur_value = d_thumbnail_limit_entry->get_text();
/*
size_type bad_char_position = cur_value.find_first_not_of("1234567890");
gint new_value = 0;
if (bad_char_position != string::npos)
new_value = atoi(cur_value->c_str());
*/
std::istringstream sstr(cur_value);
gint new_value;
sstr >> new_value;
if ( !sstr.fail() && new_value >= 0) {
if (new_value != d_old_thumbnail_limit) {
d_old_thumbnail_limit = new_value;
d_conf_client->set("/apps/nautilus/preferences/thumbnail_limit",
new_value);
}
} else {
g_warning("This program needs an error window to warn you that you typed an invalid value.\n");
gchar temp_string[20];
sprintf(temp_string, "%d", d_old_thumbnail_limit);
d_thumbnail_limit_entry->set_text(temp_string);
}
}
And finally, here is the example-2.cc file which glues everything together:
// This program monitors the
// /apps/nautilus/preferences/always_use_browser,
// /apps/nautilus/preferences/show_image_thumbnails, and
// /apps/nautilus/preferences/thumbnail_limit gconf keys, and allows
// the user to change them 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-2.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;
}
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/nautilus/preferences/always_use_browser,
# /apps/nautilus/preferences/show_image_thumbnails, and
# /apps/nautilus/preferences/thumbnail_limit gconf keys, and allows
# the user to change them 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_browser_key_callback
{
my ($check_button, $new_browser_setting, $old_browser_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_browser_setting != $$old_browser_setting) {
$$old_browser_setting = $new_browser_setting;
$check_button->set_active($new_browser_setting);
}
}
sub browser_key_toggled_callback
{
my ($check_button, $client, $old_browser_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_browser_key_callback again if this function was called as a
# result of the $check_button->set_active function call.
if ($is_set != $$old_browser_setting) {
$$old_browser_setting = $is_set;
$client->set("/apps/nautilus/preferences/always_use_browser",
{ type => 'bool', value => $is_set }
);
}
}
sub gconf_show_thumbnails_callback
{
my ($show_entry, $new_setting, $old_show_thumbnails_setting) = @_;
# Check if the new_setting seems valid, give a warning if it doesn't
if (($new_setting ne "always") &&
($new_setting ne "local_only") &&
($new_setting ne "never"))
{
warn "Unrecognized value specified by external program...\n";
}
# Use the new value if it's different than the old
if ($new_setting ne $$old_show_thumbnails_setting) {
$$old_show_thumbnails_setting = $new_setting;
$show_entry->set_text($new_setting);
}
}
sub show_thumbnails_changed_callback
{
my ($show_entry, $client, $old_show_thumbnails_setting) = @_;
# Get the current value
my $cur_value = $show_entry->get_text;
if (($cur_value eq "always") ||
($cur_value eq "local_only") ||
($cur_value eq "never"))
{
if ($cur_value ne $$old_show_thumbnails_setting) {
$$old_show_thumbnails_setting = $cur_value;
$client->set("/apps/nautilus/preferences/show_image_thumbnails",
{type => 'string', value => $cur_value }
);
}
} else {
warn "This program needs an error window to warn you" .
" that you typed an invalid value.\n";
$show_entry->set_text($$old_show_thumbnails_setting);
}
}
sub gconf_thumbnail_limit_callback
{
my ($limit_entry, $new_value, $old_thumbnail_limit) = @_;
# Warn if the value seems invalid
if ($new_value < 0) {
warn "Bad value seems to have been set by external program.\n";
}
if ($new_value != $$old_thumbnail_limit) {
$$old_thumbnail_limit = $new_value;
$limit_entry->set_text($new_value);
}
}
sub thumbnail_limit_changed_callback
{
my ($limit_entry, $client, $old_thumbnail_limit) = @_;
# Get the current value
my $new_value = $limit_entry->get_text;
if ( $new_value =~ /^\d+$/ ) {
if ($new_value != $$old_thumbnail_limit) {
$$old_thumbnail_limit = $new_value;
$client->set("/apps/nautilus/preferences/thumbnail_limit",
{type => 'int', value => $new_value }
);
}
} else {
warn "This program needs an error window to warn you" .
" that you typed an invalid value.\n";
$limit_entry->set_text($$old_thumbnail_limit);
}
}
sub hook_up_callbacks_and_set_defaults
{
my ($the_widgets) = @_;
my ($old_browser_setting, $old_show_thumbnails_setting, $old_thumbnail_limit);
# Get the GconfClient, tell it we want to monitor /apps/nautilus/preferences
my $client = Gnome2::GConf::Client->get_default;
$client->add_dir("/apps/nautilus/preferences", 'preload-none');
# FIRST, setup the checkbutton for the always_use_browser key
# Get the check_button
my $check_button = $the_widgets->get_widget('BrowserMode');
# Determine whether button should start activated or not
$old_browser_setting =
$client->get_bool("/apps/nautilus/preferences/always_use_browser");
$check_button->set_active($old_browser_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/nautilus/preferences/always_use_browser",
sub {
my ($client, $cnxn_id, $entry) = @_;
# Make sure the preference has a valid value
return unless $entry->{value} &&
$entry->{value}->{type} eq 'bool';
&gconf_browser_key_callback($check_button,
$entry->{value}->{value},
\$old_browser_setting);
}
);
# Connect the check_button's clicked callback up so that it can
# change the gconf setting.
$check_button->signal_connect( clicked =>
sub {
&browser_key_toggled_callback(
$check_button,
$client,
\$old_browser_setting);
}
);
# SECOND, setup the text entry for the show_image_thumbnails key
# Get the Entry
my $show_entry = $the_widgets->get_widget('ShowThumbnailsEntry');
# Determine the intial string for the show thumbnail entry
$old_show_thumbnails_setting =
$client->get_string("/apps/nautilus/preferences/show_image_thumbnails");
$show_entry->set_text($old_show_thumbnails_setting);
# Connect the show thumbnail entry to a callback that can toggle it
# when the option is changed by some outside program.
$client->notify_add("/apps/nautilus/preferences/show_image_thumbnails",
sub {
my ($client, $cnxn_id, $entry) = @_;
# Make sure the preference has a valid value
return unless $entry->{value} &&
$entry->{value}->{type} eq 'string';
&gconf_show_thumbnails_callback(
$show_entry,
$entry->{value}->{value},
\$old_show_thumbnails_setting);
}
);
# Connect the show thumbnail entry's activated callback up so that
# it can change the gconf setting.
$show_entry->signal_connect( activate =>
sub {
&show_thumbnails_changed_callback(
$show_entry,
$client,
\$old_show_thumbnails_setting);
}
);
# THIRD, setup the text entry for the thumbnail_limit key
# Get the Entry
my $limit_entry = $the_widgets->get_widget('ThumbnailLimitEntry');
# Determine the starting value of the limit
$old_thumbnail_limit =
$client->get_int ("/apps/nautilus/preferences/thumbnail_limit");
$limit_entry->set_text($old_thumbnail_limit);
# Connect the thumbnail limit entry to a callback that can toggle it
# when the option is changed by some outside program.
$client->notify_add("/apps/nautilus/preferences/thumbnail_limit",
sub {
my ($client, $cnxn_id, $entry) = @_;
# Make sure the preference has a valid value
return unless $entry->{value} &&
$entry->{value}->{type} eq 'int';
&gconf_thumbnail_limit_callback(
$limit_entry,
$entry->{value}->{value},
\$old_thumbnail_limit);
}
);
# Connect the thumbnail limit entry's activated callback up so that
# it can change the gconf setting.
$limit_entry->signal_connect( activate =>
sub {
&thumbnail_limit_changed_callback(
$limit_entry,
$client,
\$old_thumbnail_limit);
}
);
# 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-2.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;
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/nautilus/preferences/always_use_browser,
# /apps/nautilus/preferences/show_image_thumbnails, and
# /apps/nautilus/preferences/thumbnail_limit gconf keys, and allows
# the user to change them as well.
import gtk
import gtk.glade
import gconf
import re
class ExampleWindow:
def __init__(self, glade_file):
# Parse the glade file
self.all_da_widgets = gtk.glade.XML(glade_file)
# Get the client and tell it we want to monitor /apps/nautilus/preferences
self.conf_client = gconf.client_get_default()
self.conf_client.add_dir("/apps/nautilus/preferences", \
gconf.CLIENT_PRELOAD_NONE);
# First, setup the checkbutton for the always_use_browser key
# Get the check_button
self.browser_checkbutton = self.all_da_widgets.get_widget("BrowserMode")
# 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/nautilus/preferences/always_use_browser", \
self.browser_key_changed \
)
# Connect the check_button's clicked callback up so that it can change the
# gconf setting.
self.browser_checkbutton.connect("clicked", self.browser_key_toggled)
# Determine whether button should start activated or not
self.old_browser_setting = \
self.conf_client.get_bool("/apps/nautilus/preferences/always_use_browser")
self.browser_checkbutton.set_active(self.old_browser_setting)
# Second, setup the text entry for the show_image_thumbnails key
# Get the Entry
self.show_thumbnail_entry = \
self.all_da_widgets.get_widget("ShowThumbnailsEntry")
# Connect the show thumbnail entry to a callback that can toggle it
# when the option is changed by some outside program.
self.conf_client.notify_add( \
"/apps/nautilus/preferences/show_image_thumbnails", \
self.show_thumbnails_key_changed \
)
# Connect the show thumbnail entry's activated callback up so that
# it can change the gconf setting.
self.show_thumbnail_entry.connect("activate", self.show_thumbnails_modified)
# Determine the starting value of this key
self.old_show_thumbnails_setting = \
self.conf_client.get_string( \
"/apps/nautilus/preferences/show_image_thumbnails")
self.show_thumbnail_entry.set_text(self.old_show_thumbnails_setting)
# Third, setup the text entry for the thumbnail_limit key
# Get the Entry
self.thumbnail_limit_entry = \
self.all_da_widgets.get_widget("ThumbnailLimitEntry")
# Connect the thumbnail limit entry to a callback that can toggle
# it when the option is changed by some outside program.
self.conf_client.notify_add(
"/apps/nautilus/preferences/thumbnail_limit",
self.thumbnail_limit_key_changed
)
# Connect the thumbnail limit entry's activated callback up so that
# it can change the gconf setting.
self.thumbnail_limit_entry.connect("activate", self.thumbnail_limit_modified)
# Determine the starting value of this key
self.old_thumbnail_limit = \
self.conf_client.get_int("/apps/nautilus/preferences/thumbnail_limit");
self.thumbnail_limit_entry.set_text(str(self.old_thumbnail_limit));
# 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 browser_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_browser_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_browser_setting != self.old_browser_setting):
self.old_browser_setting = new_browser_setting
self.browser_checkbutton.set_active(new_browser_setting)
def browser_key_toggled(self, checkbutton_widget):
# Determine whether the checkbutton is already set or not
is_set = self.browser_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_browser_setting):
self.old_browser_setting = is_set;
self.conf_client.set_bool("/apps/nautilus/preferences/always_use_browser",\
is_set)
def show_thumbnails_key_changed(self, client, connection_id, entry, args):
# Make sure the preference has a valid value
if (entry.get_value().type == gconf.VALUE_STRING):
# Get the new value
new_setting = entry.get_value().get_string()
# Check if it seems valid, give a warning if it doesn't
if ((new_setting != "always") and \
(new_setting != "local_only") and \
(new_setting != "never")):
# I couldn't find an equivalent for g_warning
print "Unrecognized value specified by external program...\n"
# Use the new value if it's different than the old
if (new_setting != self.old_show_thumbnails_setting):
self.old_show_thumbnails_setting = new_setting
self.show_thumbnail_entry.set_text(new_setting)
def show_thumbnails_modified(self, show_thumbnail_entry):
# Get the current value
cur_value = self.show_thumbnail_entry.get_text()
if ((cur_value == "always") or
(cur_value == "local_only") or
(cur_value == "never")):
if (cur_value != self.old_show_thumbnails_setting):
self.old_show_thumbnails_setting = cur_value
self.conf_client.set_string(
"/apps/nautilus/preferences/show_image_thumbnails",
cur_value);
else:
# I couldn't find an equivalent for g_warning
print "This program needs an error window to warn you" + \
" that you typed an invalid value."
self.show_thumbnail_entry.set_text(self.old_show_thumbnails_setting)
def thumbnail_limit_key_changed(self, client, connection_id, entry, args):
# Make sure the preference has a valid value
if (entry.get_value().type == gconf.VALUE_INT):
# Get the new value
new_value = entry.get_value().get_int()
# Check if it seems valid, give a warning if it doesn't
if (new_value < 0):
# I couldn't find an equivalent for g_warning
print "Bad value seems to have been set by external program."
# Use the new value if it's different than the old
if (new_value != self.old_thumbnail_limit):
self.old_thumbnail_limit = new_value
self.thumbnail_limit_entry.set_text(str(new_value))
def thumbnail_limit_modified(self, thumbnail_limit_entry):
# Get the current value
new_value = self.thumbnail_limit_entry.get_text()
nonnegative_number_regex = re.compile(r'^\d+$')
if nonnegative_number_regex.match(new_value):
if (new_value != self.old_thumbnail_limit):
self.old_thumbnail_limit = new_value
self.conf_client.set_int("/apps/nautilus/preferences/thumbnail_limit",\
int(new_value))
else:
# I couldn't find an equivalent for g_warning
print "This program needs an error window to warn you" + \
" that you typed an invalid value."
self.thumbnail_limit_entry.set_text(str(self.old_thumbnail_limit))
# Create the ExampleWindow
window = ExampleWindow("example-2.glade")
# start the event loop
gtk.main()