[evolution] EClientCache: Add a "client-notify" signal.



commit 1abd497f66baa3fe278fdb02f2a85be27d5dd86e
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Feb 20 13:59:19 2013 -0500

    EClientCache: Add a "client-notify" signal.
    
    Rebroadcasts a GObject::notify signal emitted by a cached EClient.

 e-util/e-client-cache.c |  102 ++++++++++++++++++++++++++++++++++++++++++++++-
 e-util/e-client-cache.h |    3 +
 2 files changed, 104 insertions(+), 1 deletions(-)
---
diff --git a/e-util/e-client-cache.c b/e-util/e-client-cache.c
index 577ff7b..b1d9dcf 100644
--- a/e-util/e-client-cache.c
+++ b/e-util/e-client-cache.c
@@ -64,11 +64,13 @@ struct _ClientData {
        GQueue connecting;
        gulong backend_died_handler_id;
        gulong backend_error_handler_id;
+       gulong notify_handler_id;
 };
 
 struct _SignalClosure {
        EClientCache *cache;
        EClient *client;
+       GParamSpec *pspec;
        gchar *error_message;
 };
 
@@ -88,6 +90,7 @@ enum {
        BACKEND_DIED,
        BACKEND_ERROR,
        CLIENT_CREATED,
+       CLIENT_NOTIFY,
        LAST_SIGNAL
 };
 
@@ -130,6 +133,7 @@ client_data_unref (ClientData *client_data)
                 * have already been disconnected. */
                g_warn_if_fail (client_data->backend_died_handler_id == 0);
                g_warn_if_fail (client_data->backend_error_handler_id == 0);
+               g_warn_if_fail (client_data->notify_handler_id == 0);
 
                g_mutex_clear (&client_data->lock);
                g_clear_object (&client_data->client);
@@ -158,6 +162,11 @@ client_data_dispose (ClientData *client_data)
                        client_data->backend_error_handler_id);
                client_data->backend_error_handler_id = 0;
 
+               g_signal_handler_disconnect (
+                       client_data->client,
+                       client_data->notify_handler_id);
+               client_data->notify_handler_id = 0;
+
                g_clear_object (&client_data->client);
        }
 
@@ -172,6 +181,9 @@ signal_closure_free (SignalClosure *signal_closure)
        g_clear_object (&signal_closure->cache);
        g_clear_object (&signal_closure->client);
 
+       if (signal_closure->pspec != NULL)
+               g_param_spec_unref (signal_closure->pspec);
+
        g_free (signal_closure->error_message);
 
        g_slice_free (SignalClosure, signal_closure);
@@ -341,6 +353,24 @@ client_cache_emit_backend_error_idle_cb (gpointer user_data)
        return FALSE;
 }
 
+static gboolean
+client_cache_emit_client_notify_idle_cb (gpointer user_data)
+{
+       SignalClosure *signal_closure = user_data;
+       const gchar *name;
+
+       name = g_param_spec_get_name (signal_closure->pspec);
+
+       g_signal_emit (
+               signal_closure->cache,
+               signals[CLIENT_NOTIFY],
+               g_quark_from_string (name),
+               signal_closure->client,
+               signal_closure->pspec);
+
+       return FALSE;
+}
+
 static void
 client_cache_backend_died_cb (EClient *client,
                               ClientData *client_data)
@@ -402,6 +432,37 @@ client_cache_backend_error_cb (EClient *client,
 }
 
 static void
+client_cache_notify_cb (EClient *client,
+                        GParamSpec *pspec,
+                        ClientData *client_data)
+{
+       EClientCache *cache;
+
+       cache = g_weak_ref_get (&client_data->cache);
+
+       if (cache != NULL) {
+               GSource *idle_source;
+               SignalClosure *signal_closure;
+
+               signal_closure = g_slice_new0 (SignalClosure);
+               signal_closure->cache = g_object_ref (cache);
+               signal_closure->client = g_object_ref (client);
+               signal_closure->pspec = g_param_spec_ref (pspec);
+
+               idle_source = g_idle_source_new ();
+               g_source_set_callback (
+                       idle_source,
+                       client_cache_emit_client_notify_idle_cb,
+                       signal_closure,
+                       (GDestroyNotify) signal_closure_free);
+               g_source_attach (idle_source, cache->priv->main_context);
+               g_source_unref (idle_source);
+
+               g_object_unref (cache);
+       }
+}
+
+static void
 client_cache_process_results (ClientData *client_data,
                               EClient *client,
                               const GError *error)
@@ -449,6 +510,14 @@ client_cache_process_results (ClientData *client_data,
                                0);
                        client_data->backend_error_handler_id = handler_id;
 
+                       handler_id = g_signal_connect_data (
+                               client, "notify",
+                               G_CALLBACK (client_cache_notify_cb),
+                               client_data_ref (client_data),
+                               (GClosureNotify) client_data_unref,
+                               0);
+                       client_data->notify_handler_id = handler_id;
+
                        g_signal_emit (
                                cache, signals[CLIENT_CREATED], 0, client);
 
@@ -684,7 +753,7 @@ e_client_cache_class_init (EClientCacheClass *class)
 
        /**
         * EClientCache::client-created:
-        * @cache: the #EClientCache the received the signal
+        * @cache: the #EClientCache that received the signal
         * @client: the newly-created #EClient
         *
         * This signal is emitted when a call to e_client_cache_get_client()
@@ -698,6 +767,37 @@ e_client_cache_class_init (EClientCacheClass *class)
                NULL, NULL, NULL,
                G_TYPE_NONE, 1,
                E_TYPE_CLIENT);
+
+       /**
+        * EClientCache::client-notify:
+        * @cache: the #EClientCache that received the signal
+        * @client: the #EClient whose property changed
+        * @pspec: the #GParamSpec of the property that changed
+        *
+        * Rebroadcasts a #GObject::notify signal emitted by @client.
+        *
+        * This signal supports "::detail" appendices to the signal name
+        * just like the #GObject::notify signal, so you can connect to
+        * change notification signals for specific #EClient properties.
+        *
+        * As a convenience to signal handlers, this signal is always emitted
+        * from the #GMainContext that was thread-default when the @cache was
+        * created.
+        **/
+       signals[CLIENT_NOTIFY] = g_signal_new (
+               "client-notify",
+               G_TYPE_FROM_CLASS (class),
+               /* same flags as GObject::notify */
+               G_SIGNAL_RUN_FIRST |
+               G_SIGNAL_NO_RECURSE |
+               G_SIGNAL_DETAILED |
+               G_SIGNAL_NO_HOOKS |
+               G_SIGNAL_ACTION,
+               G_STRUCT_OFFSET (EClientCacheClass, client_notify),
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 2,
+               E_TYPE_CLIENT,
+               G_TYPE_PARAM);
 }
 
 static void
diff --git a/e-util/e-client-cache.h b/e-util/e-client-cache.h
index d4e3799..89a70c6 100644
--- a/e-util/e-client-cache.h
+++ b/e-util/e-client-cache.h
@@ -72,6 +72,9 @@ struct _EClientCacheClass {
        void            (*backend_error)        (EClientCache *cache,
                                                 EClient *client,
                                                 EAlert *alert);
+       void            (*client_notify)        (EClientCache *cache,
+                                                EClient *client,
+                                                GParamSpec *pspec);
        void            (*client_created)       (EClientCache *cache,
                                                 EClient *client);
 };


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