[evolution] Bug 595119 - Crash while trying to add a new category in contact



commit 28de5cf05a31122a72c4c4fe49d958f8ba952c1f
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Sep 20 22:32:33 2009 -0400

    Bug 595119 - Crash while trying to add a new category in contact

 e-util/e-categories-config.c                    |    8 ++-
 e-util/e-util.c                                 |   70 +++++++++++++++++++++++
 e-util/e-util.h                                 |    2 +
 modules/addressbook/e-book-shell-view-private.c |    4 +-
 modules/addressbook/e-book-shell-view-private.h |    1 +
 modules/calendar/e-cal-shell-view-private.c     |    4 +-
 modules/calendar/e-memo-shell-view-private.c    |    4 +-
 modules/calendar/e-task-shell-view-private.c    |    4 +-
 8 files changed, 87 insertions(+), 10 deletions(-)
---
diff --git a/e-util/e-categories-config.c b/e-util/e-categories-config.c
index 3dc3558..1abef79 100644
--- a/e-util/e-categories-config.c
+++ b/e-util/e-categories-config.c
@@ -20,12 +20,15 @@
  *
  */
 
+#include "e-categories-config.h"
+
 #include <string.h>
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <libedataserver/e-categories.h>
 #include <libedataserverui/e-categories-dialog.h>
-#include "e-categories-config.h"
+
+#include "e-util/e-util.h"
 
 static GHashTable *pixbufs_cache = NULL;
 
@@ -62,7 +65,8 @@ e_categories_config_get_icon_for (const gchar *category, GdkPixbuf **pixbuf)
 
 	if (!pixbufs_cache) {
 		pixbufs_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_pixbuf_cb);
-		e_categories_register_change_listener (G_CALLBACK (categories_changed_cb), NULL);
+		e_categories_add_change_hook (
+			(GHookFunc) categories_changed_cb, NULL);
 	} else {
 		gpointer key = NULL, value = NULL;
 
diff --git a/e-util/e-util.c b/e-util/e-util.c
index b2daca9..4e954a1 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -410,6 +410,76 @@ e_radio_action_get_current_action (GtkRadioAction *radio_action)
 	return NULL;
 }
 
+/* Helper for e_categories_add_change_hook() */
+static void
+categories_changed_cb (GObject *useless_opaque_object,
+                       GHookList *hook_list)
+{
+	/* e_categories_register_change_listener() is broken because
+	 * it requires callbacks to allow for some opaque GObject as
+	 * the first argument (not does it document this). */
+	g_hook_list_invoke (hook_list, FALSE);
+}
+
+/* Helper for e_categories_add_change_hook() */
+static void
+categories_weak_notify_cb (GHookList *hook_list,
+                           gpointer where_the_object_was)
+{
+	GHook *hook;
+
+	/* This should not happen, but if we fail to find the hook for
+	 * some reason, g_hook_destroy_link() will warn about the NULL
+	 * pointer, which is all we would do anyway so no need to test
+	 * for it ourselves. */
+	hook = g_hook_find_data (hook_list, TRUE, where_the_object_was);
+	g_hook_destroy_link (hook_list, hook);
+}
+
+/**
+ * e_categories_add_change_hook:
+ * @func: a hook function
+ * @object: a #GObject to be passed to @func, or %NULL
+ *
+ * A saner alternative to e_categories_register_change_listener().
+ *
+ * Adds a hook function to be called when a category is added, removed or
+ * modified.  If @object is not %NULL, the hook function is automatically
+ * removed when @object is finalized.
+ **/
+void
+e_categories_add_change_hook (GHookFunc func,
+                              gpointer object)
+{
+	static gboolean initialized = FALSE;
+	static GHookList hook_list;
+	GHook *hook;
+
+	g_return_if_fail (func != NULL);
+
+	if (object != NULL)
+		g_return_if_fail (G_IS_OBJECT (object));
+
+	if (!initialized) {
+		g_hook_list_init (&hook_list, sizeof (GHook));
+		e_categories_register_change_listener (
+			G_CALLBACK (categories_changed_cb), &hook_list);
+		initialized = TRUE;
+	}
+
+	hook = g_hook_alloc (&hook_list);
+
+	hook->func = func;
+	hook->data = object;
+
+	if (object != NULL)
+		g_object_weak_ref (
+			G_OBJECT (object), (GWeakNotify)
+			categories_weak_notify_cb, &hook_list);
+
+	g_hook_append (&hook_list, hook);
+}
+
 /**
  * e_type_traverse:
  * @parent_type: the root #GType to traverse from
diff --git a/e-util/e-util.h b/e-util/e-util.h
index 83b3141..68abcd4 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -61,6 +61,8 @@ void		e_action_group_remove_all_actions
 						(GtkActionGroup *action_group);
 GtkRadioAction *e_radio_action_get_current_action
 						(GtkRadioAction *radio_action);
+void		e_categories_add_change_hook	(GHookFunc func,
+						 gpointer object);
 void		e_type_traverse			(GType parent_type,
 						 ETypeFunc func,
 						 gpointer user_data);
diff --git a/modules/addressbook/e-book-shell-view-private.c b/modules/addressbook/e-book-shell-view-private.c
index 55a2e8c..279cf87 100644
--- a/modules/addressbook/e-book-shell-view-private.c
+++ b/modules/addressbook/e-book-shell-view-private.c
@@ -484,8 +484,8 @@ e_book_shell_view_private_constructed (EBookShellView *book_shell_view)
 		G_CALLBACK (book_shell_view_activate_selected_source),
 		book_shell_view);
 
-	e_categories_register_change_listener (
-		G_CALLBACK (e_book_shell_view_update_search_filter),
+	e_categories_add_change_hook (
+		(GHookFunc) e_book_shell_view_update_search_filter,
 		book_shell_view);
 
 	e_book_shell_view_actions_init (book_shell_view);
diff --git a/modules/addressbook/e-book-shell-view-private.h b/modules/addressbook/e-book-shell-view-private.h
index 8b8da3f..fa86246 100644
--- a/modules/addressbook/e-book-shell-view-private.h
+++ b/modules/addressbook/e-book-shell-view-private.h
@@ -32,6 +32,7 @@
 #include <libedataserver/e-sexp.h>
 #include <libedataserverui/e-source-selector.h>
 
+#include "e-util/e-util.h"
 #include "e-util/e-binding.h"
 #include "e-util/gconf-bridge.h"
 #include "shell/e-shell-content.h"
diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c
index d88c148..98aacb9 100644
--- a/modules/calendar/e-cal-shell-view-private.c
+++ b/modules/calendar/e-cal-shell-view-private.c
@@ -528,8 +528,8 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view)
 		G_CALLBACK (e_cal_shell_view_taskpad_actions_update),
 		cal_shell_view);
 
-	e_categories_register_change_listener (
-		G_CALLBACK (e_cal_shell_view_update_search_filter),
+	e_categories_add_change_hook (
+		(GHookFunc) e_cal_shell_view_update_search_filter,
 		cal_shell_view);
 
 	e_cal_shell_view_actions_init (cal_shell_view);
diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c
index f1d331f..b0a6ee6 100644
--- a/modules/calendar/e-memo-shell-view-private.c
+++ b/modules/calendar/e-memo-shell-view-private.c
@@ -268,8 +268,8 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view)
 		G_CALLBACK (e_shell_view_update_actions),
 		memo_shell_view);
 
-	e_categories_register_change_listener (
-		G_CALLBACK (e_memo_shell_view_update_search_filter),
+	e_categories_add_change_hook (
+		(GHookFunc) e_memo_shell_view_update_search_filter,
 		memo_shell_view);
 
 	e_memo_shell_view_actions_init (memo_shell_view);
diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c
index 581ad88..74dd295 100644
--- a/modules/calendar/e-task-shell-view-private.c
+++ b/modules/calendar/e-task-shell-view-private.c
@@ -322,8 +322,8 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view)
 		G_CALLBACK (e_shell_view_update_actions),
 		task_shell_view);
 
-	e_categories_register_change_listener (
-		G_CALLBACK (e_task_shell_view_update_search_filter),
+	e_categories_add_change_hook (
+		(GHookFunc) e_task_shell_view_update_search_filter,
 		task_shell_view);
 
 	task_shell_view_update_timeout_cb (task_shell_view);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]