[evolution] Properly disconnect signal handlers added with e_signal_connect_notify*()



commit 2e71c861438a25ceac5811d9d3aa528691e71410
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jun 5 11:47:13 2014 +0200

    Properly disconnect signal handlers added with e_signal_connect_notify*()
    
    This is a follow-up for the previous commit, where e_signal_connect_notify*()
    functions had been added. Due to a different callback and user data being
    attached to the 'notify' signal, the g_signal_handlers_*() functions do not
    work properly, thus these e_signal_connect_notify*() functions need
    a different way for a signal handler disconnect.
    
    A side-change was done in e-settings-web-view-gtkhtml.c, checking for a real
    key change from GSettings.

 calendar/gui/e-meeting-time-sel.c              |    5 ++-
 calendar/gui/e-task-table.c                    |   22 ++++++--
 calendar/gui/e-week-view.c                     |   10 +++-
 calendar/gui/gnome-cal.c                       |    5 ++-
 e-util/e-activity-bar.c                        |    2 +-
 e-util/e-activity-proxy.c                      |    2 +-
 e-util/e-buffer-tagger.c                       |    2 +-
 e-util/e-category-completion.c                 |   11 +++-
 e-util/e-misc-utils.c                          |   65 ++++++++++++++++++++++++
 e-util/e-misc-utils.h                          |    3 +
 e-util/e-table-group-leaf.c                    |    6 +--
 e-util/e-table-group-leaf.h                    |    2 +
 e-util/e-tree.c                                |    4 +-
 mail/e-mail-display.c                          |   12 ++--
 modules/settings/e-settings-web-view-gtkhtml.c |   24 ++++++++-
 plugins/publish-calendar/publish-calendar.c    |    6 ++-
 16 files changed, 151 insertions(+), 30 deletions(-)
---
diff --git a/calendar/gui/e-meeting-time-sel.c b/calendar/gui/e-meeting-time-sel.c
index 9bea92f..3caf717 100644
--- a/calendar/gui/e-meeting-time-sel.c
+++ b/calendar/gui/e-meeting-time-sel.c
@@ -47,6 +47,7 @@
 
 struct _EMeetingTimeSelectorPrivate {
        gboolean use_24_hour_format;
+       gulong notify_free_busy_template_id;
 };
 
 /* An array of hour strings for 24 hour time, "0:00" .. "23:00". */
@@ -251,6 +252,8 @@ meeting_time_selector_dispose (GObject *object)
                g_signal_handlers_disconnect_matched (
                        mts->model, G_SIGNAL_MATCH_DATA,
                        0, 0, NULL, NULL, mts);
+               e_signal_disconnect_notify_handler (mts->model, &mts->priv->notify_free_busy_template_id);
+
                g_object_unref (mts->model);
                mts->model = NULL;
        }
@@ -396,7 +399,7 @@ e_meeting_time_selector_construct (EMeetingTimeSelector *mts,
        if (mts->model)
                g_object_ref (mts->model);
 
-       e_signal_connect_notify_swapped (
+       mts->priv->notify_free_busy_template_id = e_signal_connect_notify_swapped (
                mts->model, "notify::free-busy-template",
                G_CALLBACK (free_busy_template_changed_cb), mts);
 
diff --git a/calendar/gui/e-task-table.c b/calendar/gui/e-task-table.c
index 10184ef..0370997 100644
--- a/calendar/gui/e-task-table.c
+++ b/calendar/gui/e-task-table.c
@@ -58,6 +58,11 @@ struct _ETaskTablePrivate {
 
        GtkTargetList *copy_target_list;
        GtkTargetList *paste_target_list;
+
+       gulong notify_highlight_due_today_id;
+       gulong notify_color_due_today_id;
+       gulong notify_highlight_overdue_id;
+       gulong notify_color_overdue_id;
 };
 
 enum {
@@ -315,26 +320,25 @@ task_table_set_model (ETaskTable *task_table,
                task_table);
 
        /* redraw on drawing options change */
-       e_signal_connect_notify (
+       task_table->priv->notify_highlight_due_today_id = e_signal_connect_notify (
                model, "notify::highlight-due-today",
                G_CALLBACK (task_table_queue_draw_cb),
                task_table);
 
-       e_signal_connect_notify (
+       task_table->priv->notify_color_due_today_id = e_signal_connect_notify (
                model, "notify::color-due-today",
                G_CALLBACK (task_table_queue_draw_cb),
                task_table);
 
-       e_signal_connect_notify (
+       task_table->priv->notify_highlight_overdue_id = e_signal_connect_notify (
                model, "notify::highlight-overdue",
                G_CALLBACK (task_table_queue_draw_cb),
                task_table);
 
-       e_signal_connect_notify (
+       task_table->priv->notify_color_overdue_id = e_signal_connect_notify (
                model, "notify::color-overdue",
                G_CALLBACK (task_table_queue_draw_cb),
                task_table);
-
 }
 
 static void
@@ -428,7 +432,13 @@ task_table_dispose (GObject *object)
        }
 
        if (priv->model != NULL) {
-               g_signal_handlers_disconnect_by_func (priv->model, task_table_queue_draw_cb, object);
+               g_signal_handlers_disconnect_by_data (priv->model, object);
+
+               e_signal_disconnect_notify_handler (priv->model, &priv->notify_highlight_due_today_id);
+               e_signal_disconnect_notify_handler (priv->model, &priv->notify_color_due_today_id);
+               e_signal_disconnect_notify_handler (priv->model, &priv->notify_highlight_overdue_id);
+               e_signal_disconnect_notify_handler (priv->model, &priv->notify_color_overdue_id);
+
                g_object_unref (priv->model);
                priv->model = NULL;
        }
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 21ec022..f3343d9 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -102,6 +102,8 @@ struct _EWeekViewPrivate {
         * week_start_day, but if the Sat & Sun are compressed and the
         * week starts on Sunday then we have to use Saturday. */
        GDateWeekday display_start_day;
+
+       gulong notify_week_start_day_id;
 };
 
 typedef struct {
@@ -724,8 +726,10 @@ week_view_dispose (GObject *object)
 
        e_week_view_cancel_layout (week_view);
 
-       if (model)
+       if (model) {
                g_signal_handlers_disconnect_by_data (model, object);
+               e_signal_disconnect_notify_handler (model, &week_view->priv->notify_week_start_day_id);
+       }
 
        if (week_view->events) {
                e_week_view_free_events (week_view);
@@ -761,18 +765,20 @@ week_view_dispose (GObject *object)
 static void
 week_view_constructed (GObject *object)
 {
+       EWeekView *week_view;
        ECalModel *model;
        ECalendarView *calendar_view;
 
        /* Chain up to parent's constructed() method. */
        G_OBJECT_CLASS (e_week_view_parent_class)->constructed (object);
 
+       week_view = E_WEEK_VIEW (object);
        calendar_view = E_CALENDAR_VIEW (object);
        model = e_calendar_view_get_model (calendar_view);
 
        e_week_view_recalc_display_start_day (E_WEEK_VIEW (object));
 
-       e_signal_connect_notify_swapped (
+       week_view->priv->notify_week_start_day_id = e_signal_connect_notify_swapped (
                model, "notify::week-start-day",
                G_CALLBACK (week_view_notify_week_start_day_cb), object);
 
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 58877dc..dd89119 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -123,6 +123,8 @@ struct _GnomeCalendarPrivate {
        gboolean lview_select_daten_range;
 
        GCancellable *cancellable;
+
+       gulong notify_week_start_day_id;
 };
 
 struct _ViewData {
@@ -591,7 +593,7 @@ gnome_calendar_constructed (GObject *object)
                calendar_view, "selection-changed",
                G_CALLBACK (view_selection_changed_cb), gcal);
 
-       e_signal_connect_notify_swapped (
+       gcal->priv->notify_week_start_day_id = e_signal_connect_notify_swapped (
                model, "notify::week-start-day",
                G_CALLBACK (gnome_calendar_notify_week_start_day_cb), gcal);
 
@@ -1575,6 +1577,7 @@ gnome_calendar_do_dispose (GObject *object)
 
        if (priv->model != NULL) {
                g_signal_handlers_disconnect_by_data (priv->model, object);
+               e_signal_disconnect_notify_handler (priv->model, &priv->notify_week_start_day_id);
                g_object_unref (priv->model);
                priv->model = NULL;
        }
diff --git a/e-util/e-activity-bar.c b/e-util/e-activity-bar.c
index f90e51d..795ece5 100644
--- a/e-util/e-activity-bar.c
+++ b/e-util/e-activity-bar.c
@@ -389,7 +389,7 @@ e_activity_bar_set_activity (EActivityBar *bar,
                        G_OBJECT (activity), (GWeakNotify)
                        activity_bar_weak_notify_cb, bar);
 
-               e_signal_connect_notify_swapped (
+               g_signal_connect_swapped (
                        activity, "notify::state",
                        G_CALLBACK (activity_bar_feedback), bar);
 
diff --git a/e-util/e-activity-proxy.c b/e-util/e-activity-proxy.c
index bb21a5b..f3a452b 100644
--- a/e-util/e-activity-proxy.c
+++ b/e-util/e-activity-proxy.c
@@ -362,7 +362,7 @@ e_activity_proxy_set_activity (EActivityProxy *proxy,
                        G_OBJECT (activity), (GWeakNotify)
                        activity_proxy_weak_notify_cb, proxy);
 
-               e_signal_connect_notify_swapped (
+               g_signal_connect_swapped (
                        activity, "notify::state",
                        G_CALLBACK (activity_proxy_feedback), proxy);
 
diff --git a/e-util/e-buffer-tagger.c b/e-util/e-buffer-tagger.c
index ccd23dc..c3c923a 100644
--- a/e-util/e-buffer-tagger.c
+++ b/e-util/e-buffer-tagger.c
@@ -609,7 +609,7 @@ e_buffer_tagger_connect (GtkTextView *textview)
        g_signal_connect (
                buffer, "delete-range",
                G_CALLBACK (buffer_delete_range), NULL);
-       e_signal_connect_notify (
+       g_signal_connect (
                buffer, "notify::cursor-position",
                G_CALLBACK (buffer_cursor_position), NULL);
 
diff --git a/e-util/e-category-completion.c b/e-util/e-category-completion.c
index 39e26e2..8210f72 100644
--- a/e-util/e-category-completion.c
+++ b/e-util/e-category-completion.c
@@ -35,6 +35,9 @@ struct _ECategoryCompletionPrivate {
        GtkWidget *last_known_entry;
        gchar *create;
        gchar *prefix;
+
+       gulong notify_cursor_position_id;
+       gulong notify_text_id;
 };
 
 enum {
@@ -346,6 +349,8 @@ category_completion_track_entry (GtkEntryCompletion *completion)
                g_signal_handlers_disconnect_matched (
                        priv->last_known_entry, G_SIGNAL_MATCH_DATA,
                        0, 0, NULL, NULL, completion);
+               e_signal_disconnect_notify_handler (priv->last_known_entry, &priv->notify_cursor_position_id);
+               e_signal_disconnect_notify_handler (priv->last_known_entry, &priv->notify_text_id);
                g_object_unref (priv->last_known_entry);
        }
 
@@ -358,11 +363,11 @@ category_completion_track_entry (GtkEntryCompletion *completion)
 
        g_object_ref (priv->last_known_entry);
 
-       e_signal_connect_notify_swapped (
+       priv->notify_cursor_position_id = e_signal_connect_notify_swapped (
                priv->last_known_entry, "notify::cursor-position",
                G_CALLBACK (category_completion_update_prefix), completion);
 
-       e_signal_connect_notify_swapped (
+       priv->notify_text_id = e_signal_connect_notify_swapped (
                priv->last_known_entry, "notify::text",
                G_CALLBACK (category_completion_update_prefix), completion);
 
@@ -417,6 +422,8 @@ category_completion_dispose (GObject *object)
                g_signal_handlers_disconnect_matched (
                        priv->last_known_entry, G_SIGNAL_MATCH_DATA,
                        0, 0, NULL, NULL, object);
+               e_signal_disconnect_notify_handler (priv->last_known_entry, &priv->notify_cursor_position_id);
+               e_signal_disconnect_notify_handler (priv->last_known_entry, &priv->notify_text_id);
                g_object_unref (priv->last_known_entry);
                priv->last_known_entry = NULL;
        }
diff --git a/e-util/e-misc-utils.c b/e-util/e-misc-utils.c
index f7be7af..510dad3 100644
--- a/e-util/e-misc-utils.c
+++ b/e-util/e-misc-utils.c
@@ -2394,6 +2394,16 @@ e_signal_connect_notify_cb (gpointer instance,
        }
 }
 
+/**
+ * e_signal_connect_notify:
+ *
+ * This installs a special handler in front of @c_handler, which will
+ * call the @c_handler only if the property value changed since the last
+ * time it was checked. Due to this, these handlers cannot be disconnected
+ * by by any of the g_signal_handlers_* functions, but only with the returned
+ * handler ID. A convenient e_signal_disconnect_notify_handler() was added
+ * to make it easier.
+ **/
 gulong
 e_signal_connect_notify (gpointer instance,
                         const gchar *notify_name,
@@ -2414,6 +2424,16 @@ e_signal_connect_notify (gpointer instance,
                                      0);
 }
 
+/**
+ * e_signal_connect_notify_after:
+ *
+ * This installs a special handler in front of @c_handler, which will
+ * call the @c_handler only if the property value changed since the last
+ * time it was checked. Due to this, these handlers cannot be disconnected
+ * by by any of the g_signal_handlers_* functions, but only with the returned
+ * handler ID. A convenient e_signal_disconnect_notify_handler() was added
+ * to make it easier.
+ **/
 gulong
 e_signal_connect_notify_after (gpointer instance,
                               const gchar *notify_name,
@@ -2434,6 +2454,16 @@ e_signal_connect_notify_after (gpointer instance,
                                      G_CONNECT_AFTER);
 }
 
+/**
+ * e_signal_connect_notify_swapped:
+ *
+ * This installs a special handler in front of @c_handler, which will
+ * call the @c_handler only if the property value changed since the last
+ * time it was checked. Due to this, these handlers cannot be disconnected
+ * by by any of the g_signal_handlers_* functions, but only with the returned
+ * handler ID. A convenient e_signal_disconnect_notify_handler() was added
+ * to make it easier.
+ **/
 gulong
 e_signal_connect_notify_swapped (gpointer instance,
                                 const gchar *notify_name,
@@ -2454,6 +2484,16 @@ e_signal_connect_notify_swapped (gpointer instance,
                                      0);
 }
 
+/**
+ * e_signal_connect_notify_object:
+ *
+ * This installs a special handler in front of @c_handler, which will
+ * call the @c_handler only if the property value changed since the last
+ * time it was checked. Due to this, these handlers cannot be disconnected
+ * by by any of the g_signal_handlers_* functions, but only with the returned
+ * handler ID. A convenient e_signal_disconnect_notify_handler() was added
+ * to make it easier.
+ **/
 gulong
 e_signal_connect_notify_object (gpointer instance,
                                const gchar *notify_name,
@@ -2492,3 +2532,28 @@ e_signal_connect_notify_object (gpointer instance,
                                         closure,
                                         connect_flags & G_CONNECT_AFTER);
 }
+
+/**
+ * e_signal_disconnect_notify_handler:
+ *
+ * Convenient handler disconnect function to be used with
+ * returned handler IDs from:
+ *    e_signal_connect_notify()
+ *    e_signal_connect_notify_after()
+ *    e_signal_connect_notify_swapped()
+ *    e_signal_connect_notify_object()
+ * but not necessarily only with these functions.
+ **/
+void
+e_signal_disconnect_notify_handler (gpointer instance,
+                                   gulong *handler_id)
+{
+       g_return_if_fail (instance != NULL);
+       g_return_if_fail (handler_id != NULL);
+
+       if (!*handler_id)
+               return;
+
+       g_signal_handler_disconnect (instance, *handler_id);
+       *handler_id = 0;
+}
diff --git a/e-util/e-misc-utils.h b/e-util/e-misc-utils.h
index 06de228..ebc860b 100644
--- a/e-util/e-misc-utils.h
+++ b/e-util/e-misc-utils.h
@@ -228,6 +228,9 @@ gulong              e_signal_connect_notify_object  (gpointer instance,
                                                 GCallback c_handler,
                                                 gpointer gobject,
                                                 GConnectFlags connect_flags);
+void           e_signal_disconnect_notify_handler
+                                               (gpointer instance,
+                                                gulong *handler_id);
 
 G_END_DECLS
 
diff --git a/e-util/e-table-group-leaf.c b/e-util/e-table-group-leaf.c
index 88ea6b0..ffdb8b9 100644
--- a/e-util/e-table-group-leaf.c
+++ b/e-util/e-table-group-leaf.c
@@ -108,9 +108,7 @@ etgl_dispose (GObject *object)
                                etgl->item,
                                etgl->etgl_start_drag_id);
 
-               g_signal_handlers_disconnect_by_func (
-                       etgl->item,
-                       etgl_item_is_editing_changed_cb, etgl);
+               e_signal_disconnect_notify_handler (etgl->item, &etgl->notify_is_editing_id);
 
                etgl->etgl_cursor_change_id = 0;
                etgl->etgl_cursor_activated_id = 0;
@@ -368,7 +366,7 @@ etgl_realize (GnomeCanvasItem *item)
                etgl->item, "start_drag",
                G_CALLBACK (etgl_start_drag), etgl);
 
-       e_signal_connect_notify (
+       etgl->notify_is_editing_id = e_signal_connect_notify (
                etgl->item, "notify::is-editing",
                G_CALLBACK (etgl_item_is_editing_changed_cb), etgl);
 
diff --git a/e-util/e-table-group-leaf.h b/e-util/e-table-group-leaf.h
index e4fcbed..c911890 100644
--- a/e-util/e-table-group-leaf.h
+++ b/e-util/e-table-group-leaf.h
@@ -90,6 +90,8 @@ struct _ETableGroupLeaf {
        gint etgl_start_drag_id;
 
        ESelectionModel *selection_model;
+
+       gulong notify_is_editing_id;
 };
 
 struct _ETableGroupLeafClass {
diff --git a/e-util/e-tree.c b/e-util/e-tree.c
index 30d20fc..697e88c 100644
--- a/e-util/e-tree.c
+++ b/e-util/e-tree.c
@@ -1283,7 +1283,7 @@ et_setup_table_canvas_vadjustment (ETree *tree)
 
        if (vadjustment) {
                tree->priv->table_canvas_vadjustment = g_object_ref (vadjustment);
-               e_signal_connect_notify (
+               g_signal_connect (
                        vadjustment, "notify::value",
                        G_CALLBACK (e_tree_table_canvas_scrolled_cb), tree);
        }
@@ -1336,7 +1336,7 @@ e_tree_setup_table (ETree *tree)
                G_CALLBACK (tree_canvas_reflow), tree);
 
        et_setup_table_canvas_vadjustment (tree);
-       e_signal_connect_notify_swapped (
+       g_signal_connect_swapped (
                tree->priv->table_canvas, "notify::vadjustment",
                G_CALLBACK (et_setup_table_canvas_vadjustment), tree);
 
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index fe91faa..5dc0286 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -606,18 +606,18 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 
                /* When EAttachmentBar is expanded/collapsed it does not
                 * emit size-allocate signal despite it changes it's height. */
-               e_signal_connect_notify (
+               g_signal_connect (
                        widget, "notify::expanded",
                        G_CALLBACK (mail_display_plugin_widget_resize),
                        display);
-               e_signal_connect_notify (
+               g_signal_connect (
                        widget, "notify::active-view",
                        G_CALLBACK (mail_display_plugin_widget_resize),
                        display);
 
                /* Always hide an attachment bar without attachments */
                store = e_attachment_bar_get_store (E_ATTACHMENT_BAR (widget));
-               e_signal_connect_notify (
+               g_signal_connect (
                        store, "notify::num-attachments",
                        G_CALLBACK (mail_display_attachment_count_changed),
                        box);
@@ -668,11 +668,11 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 
                        /* Show/hide the attachment when the EAttachmentButton
                         * is expanded/collapsed or shown/hidden. */
-                       e_signal_connect_notify (
+                       g_signal_connect (
                                widget, "notify::expanded",
                                G_CALLBACK (attachment_button_expanded),
                                display);
-                       e_signal_connect_notify (
+                       g_signal_connect (
                                widget, "notify::visible",
                                G_CALLBACK (attachment_button_expanded),
                                display);
@@ -994,7 +994,7 @@ mail_display_frame_created (WebKitWebView *web_view,
        d (printf ("Frame %s created!\n", webkit_web_frame_get_name (frame)));
 
        /* Call bind_func of all parts written in this frame */
-       e_signal_connect_notify (
+       g_signal_connect (
                frame, "notify::load-status",
                G_CALLBACK (mail_parts_bind_dom), NULL);
 }
diff --git a/modules/settings/e-settings-web-view-gtkhtml.c b/modules/settings/e-settings-web-view-gtkhtml.c
index b551b3e..7815eb6 100644
--- a/modules/settings/e-settings-web-view-gtkhtml.c
+++ b/modules/settings/e-settings-web-view-gtkhtml.c
@@ -33,6 +33,7 @@
 struct _ESettingsWebViewGtkHTMLPrivate {
        GtkCssProvider *css_provider;
        GSettings *settings;
+       GHashTable *old_values;
 };
 
 G_DEFINE_DYNAMIC_TYPE (
@@ -148,7 +149,21 @@ settings_web_view_gtkhtml_changed_cb (GSettings *settings,
                                       const gchar *key,
                                       ESettingsWebViewGtkHTML *extension)
 {
-       settings_web_view_gtkhtml_load_style (extension);
+       GVariant *new_value, *old_value;
+
+       new_value = g_settings_get_value (settings, key);
+       old_value = g_hash_table_lookup (extension->priv->old_values, key);
+
+       if (!new_value || !old_value || !g_variant_equal (new_value, old_value)) {
+               if (new_value)
+                       g_hash_table_insert (extension->priv->old_values, g_strdup (key), new_value);
+               else
+                       g_hash_table_remove (extension->priv->old_values, key);
+
+               settings_web_view_gtkhtml_load_style (extension);
+       } else if (new_value) {
+               g_variant_unref (new_value);
+       }
 }
 
 static void
@@ -227,6 +242,11 @@ settings_web_view_gtkhtml_dispose (GObject *object)
                        settings_web_view_gtkhtml_changed_cb, object);
        }
 
+       if (priv->old_values) {
+               g_hash_table_destroy (priv->old_values);
+               priv->old_values = NULL;
+       }
+
        g_clear_object (&priv->css_provider);
        g_clear_object (&priv->settings);
 
@@ -289,6 +309,8 @@ e_settings_web_view_gtkhtml_init (ESettingsWebViewGtkHTML *extension)
 
        settings = g_settings_new ("org.gnome.evolution.mail");
        extension->priv->settings = settings;
+
+       extension->priv->old_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
(GDestroyNotify) g_variant_unref);
 }
 
 void
diff --git a/plugins/publish-calendar/publish-calendar.c b/plugins/publish-calendar/publish-calendar.c
index 1eceaa0..f48f1af 100644
--- a/plugins/publish-calendar/publish-calendar.c
+++ b/plugins/publish-calendar/publish-calendar.c
@@ -1006,10 +1006,12 @@ e_plugin_lib_enable (EPlugin *ep,
        EShell *shell = e_shell_get_default ();
 
        if (shell) {
-               g_signal_handlers_disconnect_by_func (shell, G_CALLBACK (online_state_changed), NULL);
+               static gulong notify_online_id = 0;
+
+               e_signal_disconnect_notify_handler (shell, &notify_online_id);
                if (enable) {
                        online = e_shell_get_online (shell);
-                       e_signal_connect_notify (
+                       notify_online_id = e_signal_connect_notify (
                                shell, "notify::online",
                                G_CALLBACK (online_state_changed), NULL);
                }


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