summaryrefslogtreecommitdiff
path: root/wrappers
diff options
context:
space:
mode:
Diffstat (limited to 'wrappers')
-rw-r--r--wrappers/gtk/gconf-client.c168
-rw-r--r--wrappers/gtk/gconf-client.h3
-rw-r--r--wrappers/gtk/testgconfclient.c124
3 files changed, 258 insertions, 37 deletions
diff --git a/wrappers/gtk/gconf-client.c b/wrappers/gtk/gconf-client.c
index 9cf54515..9823fd2d 100644
--- a/wrappers/gtk/gconf-client.c
+++ b/wrappers/gtk/gconf-client.c
@@ -136,7 +136,8 @@ static gboolean gconf_client_lookup (GConfClient* client,
GConfValue** valp);
static void gconf_client_real_remove_dir (GConfClient* client,
- Dir* d);
+ Dir* d,
+ GConfError** err);
static guint client_signals[LAST_SIGNAL] = { 0 };
static GtkObjectClass* parent_class = NULL;
@@ -228,7 +229,8 @@ destroy_dir_foreach_remove(gpointer key, gpointer value, gpointer user_data)
/* remove notify for this dir */
- gconf_notify_remove(client->engine, d->notify_id);
+ if(d->notify_id != 0)
+ gconf_notify_remove(client->engine, d->notify_id);
d->notify_id = 0;
dir_destroy(value);
@@ -478,25 +480,62 @@ gconf_client_get_for_engine (GConfEngine* engine)
return client;
}
+typedef struct {
+ GConfClient *client;
+ Dir *lower_dir;
+ const char *dirname;
+} OverlapData;
-#ifdef GCONF_ENABLE_DEBUG
static void
-foreach_check_overlap(gpointer key, gpointer value, gpointer user_data)
+foreach_setup_overlap(gpointer key, gpointer value, gpointer user_data)
{
- /* Disallow overlap */
- g_return_if_fail(!gconf_key_is_below(key, user_data));
- g_return_if_fail(!gconf_key_is_below(user_data, key));
+ GConfClient *client;
+ Dir *dir = value;
+ OverlapData * od = user_data;
+
+ client = od->client;
+
+ /* if we have found the first (well there is only one anyway) directory
+ * that includes us that has a notify handler */
+#ifdef GCONF_ENABLE_DEBUG
+ if (dir->notify_id != 0 &&
+ gconf_key_is_below(dir->name, od->dirname))
+ {
+ g_assert(od->lower_dir == NULL);
+ od->lower_dir = dir;
+ }
+#else
+ if (od->lower_dir == NULL &&
+ dir->notify_id != 0 &&
+ gconf_key_is_below(dir->name, od->dirname))
+ od->lower_dir = dir;
+#endif
+ /* if we have found a directory that we include and it has
+ * a notify_id, remove the notify handler now
+ * FIXME: this is a race, from now on we can miss notifies, it is
+ * not an incredible amount of time so this is not a showstopper */
+ else if (dir->notify_id != 0 ||
+ gconf_key_is_below(od->dirname, dir->name))
+ {
+ if(dir->notify_id != 0)
+ gconf_notify_remove(client->engine, dir->notify_id);
+ dir->notify_id = 0;
+ }
}
-static void
-check_overlap(GConfClient* client, const gchar* dirname)
+static Dir *
+setup_overlaps(GConfClient* client, const gchar* dirname)
{
- g_hash_table_foreach(client->dir_hash, foreach_check_overlap,
- (gchar*)dirname);
+ OverlapData od;
+
+ od.client = client;
+ od.lower_dir = NULL;
+ od.dirname = dirname;
+
+ g_hash_table_foreach(client->dir_hash, foreach_setup_overlap, &od);
+
+ return od.lower_dir;
}
-#else
-#define check_overlap(x,y)
-#endif
void
gconf_client_add_dir (GConfClient* client,
@@ -514,23 +553,35 @@ gconf_client_add_dir (GConfClient* client,
if (d == NULL)
{
- check_overlap(client, dirname);
+ Dir *overlap_dir;
+
+ overlap_dir = setup_overlaps(client, dirname);
- notify_id = gconf_notify_add(client->engine,
- dirname,
- notify_from_server_callback,
- client,
- &error);
+ /* only if there is no directory that includes us
+ * already add a notify */
+ if (overlap_dir == NULL)
+ {
+
+ notify_id = gconf_notify_add(client->engine,
+ dirname,
+ notify_from_server_callback,
+ client,
+ &error);
- /* We got a notify ID or we got an error, not both */
- g_return_if_fail( (notify_id != 0 && error == NULL) ||
- (notify_id == 0 && error != NULL) );
+ /* We got a notify ID or we got an error, not both */
+ g_return_if_fail( (notify_id != 0 && error == NULL) ||
+ (notify_id == 0 && error != NULL) );
- if (handle_error(client, error, err))
- return;
+ if (handle_error(client, error, err))
+ return;
- g_assert(error == NULL);
+ g_assert(error == NULL);
+ }
+ else
+ {
+ notify_id = 0;
+ }
d = dir_new(dirname, notify_id);
@@ -546,10 +597,55 @@ gconf_client_add_dir (GConfClient* client,
d->add_count += 1;
}
+typedef struct {
+ GConfClient *client;
+ GConfError *error;
+} AddNotifiesData;
+
+static void
+foreach_add_notifies(gpointer key, gpointer value, gpointer user_data)
+{
+ AddNotifiesData *ad = user_data;
+ GConfClient *client;
+ Dir *dir = value;
+
+ client = ad->client;
+
+ if (ad->error != NULL)
+ return;
+
+ if (dir->notify_id == 0)
+ {
+ Dir *overlap_dir;
+ overlap_dir = setup_overlaps(client, dir->name);
+
+ /* only if there is no directory that includes us
+ * already add a notify */
+ if (overlap_dir == NULL)
+ {
+ dir->notify_id = gconf_notify_add(client->engine,
+ dir->name,
+ notify_from_server_callback,
+ client,
+ &ad->error);
+
+ /* We got a notify ID or we got an error, not both */
+ g_return_if_fail( (dir->notify_id != 0 && ad->error == NULL) ||
+ (dir->notify_id == 0 && ad->error != NULL) );
+
+ /* if error is returned, then we'll just ignore
+ * things until the end */
+ }
+ }
+}
+
static void
gconf_client_real_remove_dir (GConfClient* client,
- Dir* d)
+ Dir* d,
+ GConfError** err)
{
+ AddNotifiesData ad;
+
g_return_if_fail(d != NULL);
g_return_if_fail(d->add_count == 0);
@@ -557,15 +653,24 @@ gconf_client_real_remove_dir (GConfClient* client,
/* remove notify for this dir */
- gconf_notify_remove(client->engine, d->notify_id);
+ if(d->notify_id != 0)
+ gconf_notify_remove(client->engine, d->notify_id);
d->notify_id = 0;
dir_destroy(d);
+
+ ad.client = client;
+ ad.error = NULL;
+
+ g_hash_table_foreach(client->dir_hash, foreach_add_notifies, &ad);
+
+ handle_error(client, ad.error, err);
}
void
gconf_client_remove_dir (GConfClient* client,
- const gchar* dirname)
+ const gchar* dirname,
+ GConfError** err)
{
Dir* found = NULL;
@@ -579,7 +684,7 @@ gconf_client_remove_dir (GConfClient* client,
found->add_count -= 1;
if (found->add_count == 0)
- gconf_client_real_remove_dir(client, found);
+ gconf_client_real_remove_dir(client, found, err);
}
#ifndef G_DISABLE_CHECKS
else
@@ -1130,7 +1235,8 @@ gconf_client_get_string(GConfClient* client, const gchar* key,
g_assert(error == NULL);
if (check_type(key, val, GCONF_VALUE_STRING, &error))
- retval = gconf_value_string(val);
+ /* we cheat here (look below) so we have to cast this */
+ retval = (gchar *)gconf_value_string(val);
else
handle_error(client, error, err);
diff --git a/wrappers/gtk/gconf-client.h b/wrappers/gtk/gconf-client.h
index 6d6d46fd..9c1485b6 100644
--- a/wrappers/gtk/gconf-client.h
+++ b/wrappers/gtk/gconf-client.h
@@ -163,7 +163,8 @@ void gconf_client_add_dir (GConfClient* client,
/* This removes any notifications associated with the dir */
void gconf_client_remove_dir (GConfClient* client,
- const gchar* dir);
+ const gchar* dir,
+ GConfError** err);
/*
* The notification facility allows you to attach a callback to a single
diff --git a/wrappers/gtk/testgconfclient.c b/wrappers/gtk/testgconfclient.c
index 225d00c4..a3928aaf 100644
--- a/wrappers/gtk/testgconfclient.c
+++ b/wrappers/gtk/testgconfclient.c
@@ -153,14 +153,98 @@ quit_callback(GtkWidget* button, gpointer data)
gtk_main_quit();
}
+
+static void
+addsub_callback(GtkWidget* button, gpointer data)
+{
+ GtkWidget* win = data;
+ GConfClient* client = gtk_object_get_data(GTK_OBJECT(win), "client");
+ GtkWidget* label = gtk_object_get_data(GTK_OBJECT(win), "label");
+ int subdir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "subdir"));
+ int maindir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "maindir"));
+ char *s;
+
+ subdir++;
+
+ gtk_object_set_data(GTK_OBJECT(win), "subdir", GINT_TO_POINTER(subdir));
+
+ gconf_client_add_dir(client, "/apps/gnome/testgconfclient/subdir", GCONF_CLIENT_PRELOAD_NONE, NULL);
+
+ s = g_strdup_printf("Maindir added %d times\nSubdir added %d times", maindir, subdir);
+ gtk_label_set(GTK_LABEL(label), s);
+ g_free(s);
+}
+
+static void
+removesub_callback(GtkWidget* button, gpointer data)
+{
+ GtkWidget* win = data;
+ GConfClient* client = gtk_object_get_data(GTK_OBJECT(win), "client");
+ GtkWidget* label = gtk_object_get_data(GTK_OBJECT(win), "label");
+ int subdir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "subdir"));
+ int maindir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "maindir"));
+ char *s;
+
+ subdir--;
+
+ gtk_object_set_data(GTK_OBJECT(win), "subdir", GINT_TO_POINTER(subdir));
+
+ gconf_client_remove_dir(client, "/apps/gnome/testgconfclient/subdir", NULL);
+
+ s = g_strdup_printf("Maindir added %d times\nSubdir added %d times", maindir, subdir);
+ gtk_label_set(GTK_LABEL(label), s);
+ g_free(s);
+}
+
+static void
+addmain_callback(GtkWidget* button, gpointer data)
+{
+ GtkWidget* win = data;
+ GConfClient* client = gtk_object_get_data(GTK_OBJECT(win), "client");
+ GtkWidget* label = gtk_object_get_data(GTK_OBJECT(win), "label");
+ int subdir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "subdir"));
+ int maindir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "maindir"));
+ char *s;
+
+ maindir++;
+
+ gtk_object_set_data(GTK_OBJECT(win), "maindir", GINT_TO_POINTER(maindir));
+
+ gconf_client_add_dir(client, "/apps/gnome/testgconfclient", GCONF_CLIENT_PRELOAD_NONE, NULL);
+
+ s = g_strdup_printf("Maindir added %d times\nSubdir added %d times", maindir, subdir);
+ gtk_label_set(GTK_LABEL(label), s);
+ g_free(s);
+}
+static void
+removemain_callback(GtkWidget* button, gpointer data)
+{
+ GtkWidget* win = data;
+ GConfClient* client = gtk_object_get_data(GTK_OBJECT(win), "client");
+ GtkWidget* label = gtk_object_get_data(GTK_OBJECT(win), "label");
+ int subdir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "subdir"));
+ int maindir = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(win), "maindir"));
+ char *s;
+
+ maindir--;
+
+ gtk_object_set_data(GTK_OBJECT(win), "maindir", GINT_TO_POINTER(maindir));
+
+ gconf_client_remove_dir(client, "/apps/gnome/testgconfclient", NULL);
+
+ s = g_strdup_printf("Maindir added %d times\nSubdir added %d times", maindir, subdir);
+ gtk_label_set(GTK_LABEL(label), s);
+ g_free(s);
+}
static void
create_controls(GConfClient* client)
{
GtkWidget* win;
+ GtkWidget* label;
GtkWidget* vbox;
- GtkWidget* quit_button;
+ GtkWidget* button;
GtkWidget* entry;
/* Reference held by the window */
@@ -178,13 +262,37 @@ create_controls(GConfClient* client)
gtk_container_add(GTK_CONTAINER(win), vbox);
- quit_button = gtk_button_new_with_label("Quit");
+ label = gtk_label_new("Maindir added 1 times\nSubdir added 0 times");
+ gtk_box_pack_end(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_object_set_data(GTK_OBJECT(win), "label", label);
+ gtk_object_set_data(GTK_OBJECT(win), "subdir", GINT_TO_POINTER(0));
+ gtk_object_set_data(GTK_OBJECT(win), "maindir", GINT_TO_POINTER(1));
- gtk_signal_connect(GTK_OBJECT(quit_button), "clicked",
+ button = gtk_button_new_with_label("Quit");
+ gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(quit_callback), win);
+ gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0);
- gtk_box_pack_end(GTK_BOX(vbox), quit_button, FALSE, FALSE, 0);
-
+ button = gtk_button_new_with_label("Remove subdir");
+ gtk_signal_connect(GTK_OBJECT(button), "clicked",
+ GTK_SIGNAL_FUNC(removesub_callback), win);
+ gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label("Add subdir");
+ gtk_signal_connect(GTK_OBJECT(button), "clicked",
+ GTK_SIGNAL_FUNC(addsub_callback), win);
+ gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label("Remove maindir");
+ gtk_signal_connect(GTK_OBJECT(button), "clicked",
+ GTK_SIGNAL_FUNC(removemain_callback), win);
+ gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label("Add maindir");
+ gtk_signal_connect(GTK_OBJECT(button), "clicked",
+ GTK_SIGNAL_FUNC(addmain_callback), win);
+ gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
entry = entry_attached_to(client, "/apps/gnome/testgconfclient/blah");
gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
@@ -193,6 +301,12 @@ create_controls(GConfClient* client)
entry = entry_attached_to(client, "/apps/gnome/testgconfclient/bar");
gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+
+ entry = entry_attached_to(client, "/apps/gnome/testgconfclient/subdir/testsub1");
+ gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+
+ entry = entry_attached_to(client, "/apps/gnome/testgconfclient/subdir/testsub2");
+ gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
gtk_widget_show_all(win);
}