diff options
author | George Lebl <jirka@5z.com> | 2000-07-24 23:43:25 +0000 |
---|---|---|
committer | George Lebl <jirka@src.gnome.org> | 2000-07-24 23:43:25 +0000 |
commit | 377edb91b0af687f6ae5784d94bc2320b8f38d44 (patch) | |
tree | dc27ef3f5a1922352e62f70c02f0bcd059e7c9d6 /wrappers | |
parent | a42fa312c9a9d5c891de8be468fe8ffc67decfc6 (diff) | |
download | gconf-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.c | 168 | ||||
-rw-r--r-- | wrappers/gtk/gconf-client.h | 3 | ||||
-rw-r--r-- | wrappers/gtk/testgconfclient.c | 124 |
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); } |