From 2e71c861438a25ceac5811d9d3aa528691e71410 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Thu, 5 Jun 2014 11:47:13 +0200 Subject: 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 9bea92f2dc..3caf71795d 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 10184ef725..0370997c32 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 21ec0229f4..f3343d9e5d 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 58877dc87d..dd89119c72 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 f90e51df94..795ece505c 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 bb21a5bc8a..f3a452b5af 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 ccd23dc158..c3c923aa7b 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 39e26e2edf..8210f72f60 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 f7be7af5ac..510dad39b2 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 06de228899..ebc860b91e 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 88ea6b0e8d..ffdb8b94bc 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 e4fcbedee8..c911890829 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 30d20fc4c8..697e88c800 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 fe91faab9a..5dc02860c7 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 b551b3e881..7815eb6a17 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 1eceaa0dd2..f48f1af10e 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, ¬ify_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); } -- cgit v1.2.3