diff options
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); } |