[evolution] contact-photos: Obtain an EClient asynchronously.



commit e403abb2e4eaace12e23749e4d8cf6ddf07950fe
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed May 8 09:10:58 2013 -0400

    contact-photos: Obtain an EClient asynchronously.
    
    Obtain an EClient for contact photo lookup asynchronously.  If an
    instance needs to be created, it's more likely created in a thread
    with a main loop so signal emissions can work.

 modules/contact-photos/e-contact-photo-source.c |  115 +++++++++++++++--------
 1 files changed, 76 insertions(+), 39 deletions(-)
---
diff --git a/modules/contact-photos/e-contact-photo-source.c b/modules/contact-photos/e-contact-photo-source.c
index b290a21..e124046 100644
--- a/modules/contact-photos/e-contact-photo-source.c
+++ b/modules/contact-photos/e-contact-photo-source.c
@@ -30,8 +30,10 @@ struct _EContactPhotoSourcePrivate {
 };
 
 struct _AsyncContext {
+       EBookClient *client;
        gchar *query_string;
        GInputStream *stream;
+       GCancellable *cancellable;
        gint priority;
 };
 
@@ -57,8 +59,10 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (
 static void
 async_context_free (AsyncContext *async_context)
 {
+       g_clear_object (&async_context->client);
        g_free (async_context->query_string);
        g_clear_object (&async_context->stream);
+       g_clear_object (&async_context->cancellable);
 
        g_slice_free (AsyncContext, async_context);
 }
@@ -85,51 +89,22 @@ contact_photo_source_get_photo_thread (GSimpleAsyncResult *simple,
                                        GObject *source_object,
                                        GCancellable *cancellable)
 {
-       EContactPhotoSource *photo_source;
        AsyncContext *async_context;
-       EClientCache *client_cache;
-       ESourceRegistry *registry;
-       EClient *client = NULL;
-       ESource *source;
        GSList *slist = NULL;
        GSList *slink;
        GError *error = NULL;
 
-       photo_source = E_CONTACT_PHOTO_SOURCE (source_object);
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       client_cache = e_contact_photo_source_ref_client_cache (photo_source);
-       source = e_contact_photo_source_ref_source (photo_source);
-       registry = e_client_cache_ref_registry (client_cache);
-
-       /* Return no result if the source is disabled. */
-       if (!e_source_registry_check_enabled (registry, source))
-               goto exit;
-
-       client = e_client_cache_get_client_sync (
-               client_cache, source,
-               E_SOURCE_EXTENSION_ADDRESS_BOOK,
-               cancellable, &error);
-
-       /* Sanity check. */
-       g_return_if_fail (
-               ((client != NULL) && (error == NULL)) ||
-               ((client == NULL) && (error != NULL)));
-
-       if (error != NULL) {
-               g_simple_async_result_take_error (simple, error);
-               goto exit;
-       }
-
        e_book_client_get_contacts_sync (
-               E_BOOK_CLIENT (client),
+               async_context->client,
                async_context->query_string,
                &slist, cancellable, &error);
 
        if (error != NULL) {
                g_warn_if_fail (slist == NULL);
                g_simple_async_result_take_error (simple, error);
-               goto exit;
+               return;
        }
 
        /* See if any of the contacts have a photo. */
@@ -181,12 +156,46 @@ contact_photo_source_get_photo_thread (GSimpleAsyncResult *simple,
        }
 
        g_slist_free_full (slist, (GDestroyNotify) g_object_unref);
+}
+
+static void
+contact_photo_source_get_client_cb (GObject *source_object,
+                                    GAsyncResult *result,
+                                    gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       EClient *client;
+       GError *error = NULL;
+
+       simple = G_SIMPLE_ASYNC_RESULT (user_data);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       client = e_client_cache_get_client_finish (
+               E_CLIENT_CACHE (source_object), result, &error);
+
+       /* Sanity check. */
+       g_return_if_fail (
+               ((client != NULL) && (error == NULL)) ||
+               ((client == NULL) && (error != NULL)));
+
+       if (client != NULL) {
+               async_context->client = g_object_ref (client);
+
+               /* The rest of the operation we can run from a
+                * worker thread to keep the logic flow simple. */
+               g_simple_async_result_run_in_thread (
+                       simple, contact_photo_source_get_photo_thread,
+                       G_PRIORITY_DEFAULT, async_context->cancellable);
+
+               g_object_unref (client);
+
+       } else {
+               g_simple_async_result_take_error (simple, error);
+               g_simple_async_result_complete_in_idle (simple);
+       }
 
-exit:
-       g_clear_object (&client_cache);
-       g_clear_object (&registry);
-       g_clear_object (&client);
-       g_clear_object (&source);
+       g_object_unref (simple);
 }
 
 static void
@@ -280,7 +289,10 @@ contact_photo_source_get_photo (EPhotoSource *photo_source,
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
+       EClientCache *client_cache;
+       ESourceRegistry *registry;
        EBookQuery *book_query;
+       ESource *source;
 
        book_query = e_book_query_field_test (
                E_CONTACT_EMAIL, E_BOOK_QUERY_IS, email_address);
@@ -288,6 +300,9 @@ contact_photo_source_get_photo (EPhotoSource *photo_source,
        async_context = g_slice_new0 (AsyncContext);
        async_context->query_string = e_book_query_to_string (book_query);
 
+       if (G_IS_CANCELLABLE (cancellable))
+               async_context->cancellable = g_object_ref (cancellable);
+
        e_book_query_unref (book_query);
 
        simple = g_simple_async_result_new (
@@ -299,9 +314,31 @@ contact_photo_source_get_photo (EPhotoSource *photo_source,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       g_simple_async_result_run_in_thread (
-               simple, contact_photo_source_get_photo_thread,
-               G_PRIORITY_DEFAULT, cancellable);
+       client_cache = e_contact_photo_source_ref_client_cache (
+               E_CONTACT_PHOTO_SOURCE (photo_source));
+       registry = e_client_cache_ref_registry (client_cache);
+
+       source = e_contact_photo_source_ref_source (
+               E_CONTACT_PHOTO_SOURCE (photo_source));
+
+       if (e_source_registry_check_enabled (registry, source)) {
+               /* Obtain the EClient asynchronously.  If an instance needs
+                * to be created, it's more likely created in a thread with
+                * a main loop so signal emissions can work. */
+               e_client_cache_get_client (
+                       client_cache, source,
+                       E_SOURCE_EXTENSION_ADDRESS_BOOK,
+                       cancellable,
+                       contact_photo_source_get_client_cb,
+                       g_object_ref (simple));
+       } else {
+               /* Return no result if the source is disabled. */
+               g_simple_async_result_complete_in_idle (simple);
+       }
+
+       g_object_unref (client_cache);
+       g_object_unref (registry);
+       g_object_unref (source);
 
        g_object_unref (simple);
 }


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