From 996055c6e5176b9c6d561e1c40742eac8aa01427 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Wed, 21 Aug 2013 12:52:31 +0200 Subject: Bug #698275 - Enable/disable account yields to a several seconds busy loop --- mail/e-mail-label-list-store.c | 87 ++++++++++++++++++++++++++++++-- modules/mail/e-mail-shell-view-private.c | 12 +---- modules/settings/e-settings-deprecated.c | 74 +++++++++++++++++++++------ 3 files changed, 142 insertions(+), 31 deletions(-) diff --git a/mail/e-mail-label-list-store.c b/mail/e-mail-label-list-store.c index 9491d70dda..bdb4f16a76 100644 --- a/mail/e-mail-label-list-store.c +++ b/mail/e-mail-label-list-store.c @@ -36,9 +36,17 @@ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_MAIL_LABEL_LIST_STORE, EMailLabelListStorePrivate)) +enum { + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + struct _EMailLabelListStorePrivate { GHashTable *tag_index; GSettings *mail_settings; + guint idle_changed_id; }; static struct { @@ -180,6 +188,11 @@ mail_label_list_store_dispose (GObject *object) priv = E_MAIL_LABEL_LIST_STORE_GET_PRIVATE (object); + if (priv->idle_changed_id) { + g_source_remove (priv->idle_changed_id); + priv->idle_changed_id = 0; + } + if (priv->mail_settings != NULL) { g_object_unref (priv->mail_settings); priv->mail_settings = NULL; @@ -204,14 +217,17 @@ mail_label_list_store_finalize (GObject *object) finalize (object); } -static void -labels_model_changed_cb (EMailLabelListStore *store) +static gboolean +labels_model_changed_idle_cb (gpointer user_data) { + EMailLabelListStore *store = user_data; GPtrArray *array; GtkTreeIter tmp_iter; gboolean iter_set; - g_return_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store)); + g_return_val_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store), FALSE); + + store->priv->idle_changed_id = 0; /* Make sure we don't enter an infinite synchronizing loop */ g_signal_handlers_block_by_func ( @@ -249,6 +265,21 @@ labels_model_changed_cb (EMailLabelListStore *store) g_signal_handlers_unblock_by_func ( store->priv->mail_settings, labels_settings_changed_cb, store); + + g_signal_emit (store, signals[CHANGED], 0); + + return FALSE; +} + +static void +labels_model_changed_cb (EMailLabelListStore *store) +{ + g_return_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store)); + + /* do the actual save and signal emission on idle, + to accumulate as many changes as possible */ + if (!store->priv->idle_changed_id) + store->priv->idle_changed_id = g_idle_add (labels_model_changed_idle_cb, store); } static void @@ -257,10 +288,50 @@ labels_settings_changed_cb (GSettings *settings, gpointer user_data) { EMailLabelListStore *store; + GtkTreeModel *model; + GtkTreeIter iter; + GHashTable *changed_labels; gchar **strv; gint i; store = E_MAIL_LABEL_LIST_STORE (user_data); + model = GTK_TREE_MODEL (store); + + strv = g_settings_get_strv (store->priv->mail_settings, "labels"); + + /* Check if any label changed first, because GSettings can claim + change when nothing changed at all */ + changed_labels = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + if (gtk_tree_model_get_iter_first (model, &iter)) { + do { + gchar *label_str = NULL; + + gtk_tree_model_get (model, &iter, 0, &label_str, -1); + + if (label_str) + g_hash_table_insert (changed_labels, label_str, NULL); + } while (gtk_tree_model_iter_next (model, &iter)); + + + for (i = 0; strv[i] != NULL; i++) { + if (!g_hash_table_remove (changed_labels, strv[i])) { + g_hash_table_insert (changed_labels, g_strdup (""), NULL); + break; + } + } + } else { + /* nothing in the store, thus fill it (pretend change) */ + g_hash_table_insert (changed_labels, g_strdup (""), NULL); + } + + /* Nothing changed */ + if (g_hash_table_size (changed_labels) == 0) { + g_hash_table_destroy (changed_labels); + g_strfreev (strv); + return; + } + + g_hash_table_destroy (changed_labels); /* Make sure we don't enter an infinite synchronizing loop */ g_signal_handlers_block_by_func ( @@ -268,8 +339,6 @@ labels_settings_changed_cb (GSettings *settings, gtk_list_store_clear (GTK_LIST_STORE (store)); - strv = g_settings_get_strv (store->priv->mail_settings, "labels"); - for (i = 0; strv[i] != NULL; i++) { GtkTreeIter iter; @@ -359,6 +428,14 @@ e_mail_label_list_store_class_init (EMailLabelListStoreClass *class) class->icon_factory = gtk_icon_factory_new (); gtk_icon_factory_add_default (class->icon_factory); + + signals[CHANGED] = g_signal_new ( + "changed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c index be250ff6b2..dd980e7fd6 100644 --- a/modules/mail/e-mail-shell-view-private.c +++ b/modules/mail/e-mail-shell-view-private.c @@ -734,17 +734,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) mail_shell_view, G_CONNECT_SWAPPED); g_signal_connect_object ( - label_store, "row-changed", - G_CALLBACK (e_mail_shell_view_update_search_filter), - mail_shell_view, G_CONNECT_SWAPPED); - - g_signal_connect_object ( - label_store, "row-deleted", - G_CALLBACK (e_mail_shell_view_update_search_filter), - mail_shell_view, G_CONNECT_SWAPPED); - - g_signal_connect_object ( - label_store, "row-inserted", + label_store, "changed", G_CALLBACK (e_mail_shell_view_update_search_filter), mail_shell_view, G_CONNECT_SWAPPED); diff --git a/modules/settings/e-settings-deprecated.c b/modules/settings/e-settings-deprecated.c index 4b2e55009c..1249288d92 100644 --- a/modules/settings/e-settings-deprecated.c +++ b/modules/settings/e-settings-deprecated.c @@ -97,6 +97,50 @@ settings_deprecated_header_start_element (GMarkupParseContext *context, builder, "(sb)", name, (enabled != NULL)); } +static void +e_settings_deprecated_set_int_with_change_test (GSettings *settings, + const gchar *key, + gint value) +{ + if (g_settings_get_int (settings, key) != value) + g_settings_set_int (settings, key, value); +} + +static void +e_settings_deprecated_set_string_with_change_test (GSettings *settings, + const gchar *key, + const gchar *value) +{ + gchar *stored = g_settings_get_string (settings, key); + + if (g_strcmp0 (stored, value) != 0) + g_settings_set_string (settings, key, value); + + g_free (stored); +} + +static void +e_settings_deprecated_set_strv_with_change_test (GSettings *settings, + const gchar *key, + const gchar * const *value) +{ + gchar **stored = g_settings_get_strv (settings, key); + gboolean changed; + gint ii; + + changed = !stored || !value; + for (ii = 0; !changed && stored[ii] && value[ii]; ii++) { + changed = g_strcmp0 (stored[ii], value[ii]) != 0; + } + + changed = changed || stored[ii] != NULL || value[ii] != NULL; + + if (changed) + g_settings_set_strv (settings, key, value); + + g_strfreev (stored); +} + static void settings_deprecated_header_parse_xml (const gchar *xml, GVariantBuilder *builder) @@ -141,7 +185,7 @@ settings_deprecated_week_start_day_name_cb (GSettings *settings, weekday = g_settings_get_enum (settings, "week-start-day-name"); tm_wday = e_weekday_to_tm_wday (weekday); - g_settings_set_int (settings, "week-start-day", tm_wday); + e_settings_deprecated_set_int_with_change_test (settings, "week-start-day", tm_wday); } static void @@ -155,7 +199,7 @@ settings_deprecated_work_day_monday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_MONDAY; else flags &= ~DEPRECATED_WORKING_DAYS_MONDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -169,7 +213,7 @@ settings_deprecated_work_day_tuesday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_TUESDAY; else flags &= ~DEPRECATED_WORKING_DAYS_TUESDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -183,7 +227,7 @@ settings_deprecated_work_day_wednesday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_WEDNESDAY; else flags &= ~DEPRECATED_WORKING_DAYS_WEDNESDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -197,7 +241,7 @@ settings_deprecated_work_day_thursday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_THURSDAY; else flags &= ~DEPRECATED_WORKING_DAYS_THURSDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -211,7 +255,7 @@ settings_deprecated_work_day_friday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_FRIDAY; else flags &= ~DEPRECATED_WORKING_DAYS_FRIDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -225,7 +269,7 @@ settings_deprecated_work_day_saturday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_SATURDAY; else flags &= ~DEPRECATED_WORKING_DAYS_SATURDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -239,7 +283,7 @@ settings_deprecated_work_day_sunday_cb (GSettings *settings, flags |= DEPRECATED_WORKING_DAYS_SUNDAY; else flags &= ~DEPRECATED_WORKING_DAYS_SUNDAY; - g_settings_set_int (settings, "working-days", flags); + e_settings_deprecated_set_int_with_change_test (settings, "working-days", flags); } static void @@ -250,15 +294,15 @@ settings_deprecated_browser_close_on_reply_policy_cb (GSettings *settings, switch (g_settings_get_enum (settings, key)) { case E_AUTOMATIC_ACTION_POLICY_ALWAYS: - g_settings_set_string ( + e_settings_deprecated_set_string_with_change_test ( settings, deprecated_key, "always"); break; case E_AUTOMATIC_ACTION_POLICY_NEVER: - g_settings_set_string ( + e_settings_deprecated_set_string_with_change_test ( settings, deprecated_key, "never"); break; default: - g_settings_set_string ( + e_settings_deprecated_set_string_with_change_test ( settings, deprecated_key, "ask"); break; } @@ -271,7 +315,7 @@ settings_deprecated_forward_style_name_cb (GSettings *settings, EMailForwardStyle style; style = g_settings_get_enum (settings, "forward-style-name"); - g_settings_set_int (settings, "forward-style", style); + e_settings_deprecated_set_int_with_change_test (settings, "forward-style", style); } static void @@ -281,7 +325,7 @@ settings_deprecated_reply_style_name_cb (GSettings *settings, EMailReplyStyle style; style = g_settings_get_enum (settings, "reply-style-name"); - g_settings_set_int (settings, "reply-style", style); + e_settings_deprecated_set_int_with_change_test (settings, "reply-style", style); } static void @@ -291,7 +335,7 @@ settings_deprecated_image_loading_policy_cb (GSettings *settings, EMailImageLoadingPolicy policy; policy = g_settings_get_enum (settings, "image-loading-policy"); - g_settings_set_int (settings, "load-http-images", policy); + e_settings_deprecated_set_int_with_change_test (settings, "load-http-images", policy); } static void @@ -320,7 +364,7 @@ settings_deprecated_show_headers_cb (GSettings *settings, name, enabled ? " enabled=\"\"" : ""); } - g_settings_set_strv ( + e_settings_deprecated_set_strv_with_change_test ( settings, "headers", (const gchar * const *) strv); -- cgit v1.2.3