[evolution-data-server] Bug 638095 - Async ops in ENameSelectorEntry can exceed widget lifetime



commit 984f29d62b6f7394cf5f0786366d67e8f81b56c9
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Dec 27 09:16:46 2010 -0500

    Bug 638095 - Async ops in ENameSelectorEntry can exceed widget lifetime

 libedataserverui/e-name-selector-entry.c |   38 ++++++++++++++++++++++-------
 1 files changed, 29 insertions(+), 9 deletions(-)
---
diff --git a/libedataserverui/e-name-selector-entry.c b/libedataserverui/e-name-selector-entry.c
index 2057667..e135847 100644
--- a/libedataserverui/e-name-selector-entry.c
+++ b/libedataserverui/e-name-selector-entry.c
@@ -67,6 +67,9 @@ struct _ENameSelectorEntryPrivate {
 
 	gboolean is_completing;
 	GSList *user_query_fields;
+
+	/* For asynchronous operations. */
+	GQueue cancellables;
 };
 
 enum {
@@ -136,6 +139,15 @@ name_selector_entry_dispose (GObject *object)
 	g_slist_free (priv->user_query_fields);
 	priv->user_query_fields = NULL;
 
+	/* Cancel any stuck book loading operations. */
+	while (!g_queue_is_empty (&priv->cancellables)) {
+		GCancellable *cancellable;
+
+		cancellable = g_queue_pop_head (&priv->cancellables);
+		g_cancellable_cancel (cancellable);
+		g_object_unref (cancellable);
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (e_name_selector_entry_parent_class)->dispose (object);
 }
@@ -1974,10 +1986,9 @@ setup_contact_store (ENameSelectorEntry *name_selector_entry)
 static void
 book_loaded_cb (ESource *source,
                 GAsyncResult *result,
-                ENameSelectorEntry *name_selector_entry)
+                EContactStore *contact_store)
 {
 	EBook *book;
-	EContactStore *store;
 	GError *error = NULL;
 
 	book = e_load_book_source_finish (source, result, &error);
@@ -1996,18 +2007,17 @@ book_loaded_cb (ESource *source,
 	}
 
 	g_return_if_fail (E_IS_BOOK (book));
-
-	store = name_selector_entry->priv->contact_store;
-	e_contact_store_add_book (store, book);
+	e_contact_store_add_book (contact_store, book);
 	g_object_unref (book);
 
 exit:
-	g_object_unref (name_selector_entry);
+	g_object_unref (contact_store);
 }
 
 static void
 setup_default_contact_store (ENameSelectorEntry *name_selector_entry)
 {
+	EContactStore *contact_store;
 	GSList *groups;
 	GSList *l;
 
@@ -2015,7 +2025,8 @@ setup_default_contact_store (ENameSelectorEntry *name_selector_entry)
 
 	/* Create a book for each completion source, and assign them to the contact store */
 
-	name_selector_entry->priv->contact_store = e_contact_store_new ();
+	contact_store = e_contact_store_new ();
+	name_selector_entry->priv->contact_store = contact_store;
 	groups = e_source_list_peek_groups (name_selector_entry->priv->source_list);
 
 	for (l = groups; l; l = g_slist_next (l)) {
@@ -2025,6 +2036,7 @@ setup_default_contact_store (ENameSelectorEntry *name_selector_entry)
 
 		for (m = sources; m; m = g_slist_next (m)) {
 			ESource *source = m->data;
+			GCancellable *cancellable;
 			const gchar *completion;
 
 			/* Skip non-completion sources */
@@ -2032,10 +2044,16 @@ setup_default_contact_store (ENameSelectorEntry *name_selector_entry)
 			if (!completion || g_ascii_strcasecmp (completion, "true"))
 				continue;
 
+			cancellable = g_cancellable_new ();
+
+			g_queue_push_tail (
+				&name_selector_entry->priv->cancellables,
+				cancellable);
+
 			e_load_book_source_async (
-				source, NULL, NULL,
+				source, NULL, cancellable,
 				(GAsyncReadyCallback) book_loaded_cb,
-				g_object_ref (name_selector_entry));
+				g_object_ref (contact_store));
 		}
 	}
 
@@ -2822,6 +2840,8 @@ e_name_selector_entry_init (ENameSelectorEntry *name_selector_entry)
 	name_selector_entry->priv =
 		E_NAME_SELECTOR_ENTRY_GET_PRIVATE (name_selector_entry);
 
+	g_queue_init (&name_selector_entry->priv->cancellables);
+
 	/* Source list */
 
 	if (!e_book_get_addressbooks (&name_selector_entry->priv->source_list, NULL)) {



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