[evolution] Bug #698275 - Enable/disable account yields to a several seconds busy loop



commit 996055c6e5176b9c6d561e1c40742eac8aa01427
Author: Milan Crha <mcrha redhat com>
Date:   Wed Aug 21 12:52:31 2013 +0200

    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 9491d70..bdb4f16 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 be250ff..dd980e7 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 4b2e550..1249288 100644
--- a/modules/settings/e-settings-deprecated.c
+++ b/modules/settings/e-settings-deprecated.c
@@ -98,6 +98,50 @@ settings_deprecated_header_start_element (GMarkupParseContext *context,
 }
 
 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);
 


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