summaryrefslogtreecommitdiff
path: root/wrappers
diff options
context:
space:
mode:
authorGeorge Lebl <jirka@5z.com>2000-07-24 23:43:25 +0000
committerGeorge Lebl <jirka@src.gnome.org>2000-07-24 23:43:25 +0000
commit377edb91b0af687f6ae5784d94bc2320b8f38d44 (patch)
treedc27ef3f5a1922352e62f70c02f0bcd059e7c9d6 /wrappers
parenta42fa312c9a9d5c891de8be468fe8ffc67decfc6 (diff)
downloadgconf-377edb91b0af687f6ae5784d94bc2320b8f38d44.tar.gz
Allow adding overlapping subdirectories. What happens is that the real
Mon Jul 24 16:39:01 2000 George Lebl <jirka@5z.com> * wrappers/gtk/gconf-client.[ch]: Allow adding overlapping subdirectories. What happens is that the real gconf notify is not added for subdirectories. When directories are added or removed the hash is traversed and fixed up. This is done in a simple and incredibly inefficent manner and needs to be fixed. Also this change adds an "err" argument to the _remove_dir call as errors can now happen. Also fix a minor warning by casting. * wrappers/gtk/testgconfclient.c: Add some testing of overlapping directories. Add buttons to add/remove the main directory and the subdirectory. This way you can see if things get proper notifications.
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);
}