From 61a15e4d9dd303c23b6e44af9d084e3f3c609192 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Fri, 20 Apr 2012 15:08:17 +0200 Subject: Bug #668481 - Account order is not remembered --- mail/e-mail-account-manager.c | 2 +- mail/e-mail-account-store.c | 190 ++++++++++++++++++++++++++++++------------ mail/e-mail-account-store.h | 11 ++- mail/e-mail-ui-session.c | 62 +++++++------- 4 files changed, 178 insertions(+), 87 deletions(-) (limited to 'mail') diff --git a/mail/e-mail-account-manager.c b/mail/e-mail-account-manager.c index 86a0bf5e4b..8015d9bbfd 100644 --- a/mail/e-mail-account-manager.c +++ b/mail/e-mail-account-manager.c @@ -161,7 +161,7 @@ mail_account_manager_info_bar_response_cb (EMailAccountManager *manager, store = e_mail_account_manager_get_store (manager); if (response == DEFAULT_ORDER_RESPONSE) - e_mail_account_store_reorder_services (store, NULL); + e_mail_account_store_reorder_services (store, TRUE); } static gboolean diff --git a/mail/e-mail-account-store.c b/mail/e-mail-account-store.c index 2dac692d82..0f505bc24b 100644 --- a/mail/e-mail-account-store.c +++ b/mail/e-mail-account-store.c @@ -45,6 +45,8 @@ struct _EMailAccountStorePrivate { gboolean express_mode; gpointer session; /* weak pointer */ guint busy_count; + gint reorder_freeze; + gboolean reorder_changed_frozen; }; struct _IndexItem { @@ -617,10 +619,19 @@ static void mail_account_store_services_reordered (EMailAccountStore *store, gboolean default_restored) { - /* XXX Should this be made asynchronous? */ - + GtkTreeModel *model; GError *error = NULL; + /* do not save order list if there are only two services - they + should be 'local' and 'vfolder' at start, and these may not rewrite + stored account order with other accounts + */ + model = GTK_TREE_MODEL (store); + if (!default_restored && + gtk_tree_model_iter_n_children (model, NULL) <= 2 && + e_list_length (E_LIST (e_get_account_list ())) != 0) + return; + if (default_restored) { const gchar *filename; @@ -1104,7 +1115,7 @@ e_mail_account_store_add_service (EMailAccountStore *store, * user has messed around with the ordering so leave the new * service at row 0. If not present, services are sorted in * their default order. So re-apply the default order using - * e_mail_account_store_reorder_services(store, NULL) so the + * e_mail_account_store_reorder_services(store, TRUE) so the * new service moves to its proper default position. */ gtk_list_store_prepend (GTK_LIST_STORE (store), &iter); @@ -1132,8 +1143,7 @@ e_mail_account_store_add_service (EMailAccountStore *store, filename = store->priv->sort_order_filename; - if (!g_file_test (filename, G_FILE_TEST_EXISTS)) - e_mail_account_store_reorder_services (store, NULL); + e_mail_account_store_reorder_services (store, !g_file_test (filename, G_FILE_TEST_EXISTS)); } void @@ -1169,6 +1179,18 @@ e_mail_account_store_remove_service (EMailAccountStore *store, } } +gboolean +e_mail_account_store_has_service (EMailAccountStore *store, + CamelService *service) +{ + GtkTreeIter iter; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE); + + return mail_account_store_get_iter (store, service, &iter); +} + void e_mail_account_store_enable_service (EMailAccountStore *store, GtkWindow *parent_window, @@ -1289,14 +1311,63 @@ e_mail_account_store_queue_enabled_services (EMailAccountStore *store, } } +static gboolean +mail_account_store_load_sort_order_queue (EMailAccountStore *store, + GQueue *service_queue, + GError **error) +{ + EMailSession *session; + GKeyFile *key_file; + const gchar *filename; + gchar **service_uids; + gboolean success = TRUE; + gsize ii, length; + + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + g_return_val_if_fail (service_queue != NULL, FALSE); + + session = e_mail_account_store_get_session (store); + + key_file = g_key_file_new (); + filename = store->priv->sort_order_filename; + + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + success = g_key_file_load_from_file ( + key_file, filename, G_KEY_FILE_NONE, error); + + if (!success) { + g_key_file_free (key_file); + return FALSE; + } + + /* If the key is not present, length is set to zero. */ + service_uids = g_key_file_get_string_list ( + key_file, "Accounts", "SortOrder", &length, NULL); + + for (ii = 0; ii < length; ii++) { + CamelService *service; + + service = camel_session_get_service ( + CAMEL_SESSION (session), service_uids[ii]); + if (service != NULL) + g_queue_push_tail (service_queue, service); + } + + g_strfreev (service_uids); + + g_key_file_free (key_file); + + return TRUE; +} + void e_mail_account_store_reorder_services (EMailAccountStore *store, - GQueue *ordered_services) + gboolean use_default_order) { GQueue *current_order = NULL; GQueue *default_order = NULL; GtkTreeModel *tree_model; - gboolean use_default_order; + GQueue *ordered_services = NULL; GList *head, *link; gint *new_order; gint n_children; @@ -1307,19 +1378,16 @@ e_mail_account_store_reorder_services (EMailAccountStore *store, tree_model = GTK_TREE_MODEL (store); n_children = gtk_tree_model_iter_n_children (tree_model, NULL); - /* Treat NULL queues and empty queues the same. */ - if (ordered_services != NULL && g_queue_is_empty (ordered_services)) - ordered_services = NULL; + if (!use_default_order) { + ordered_services = g_queue_new ();; - /* If the length of the custom ordering disagrees with the - * number of rows in the store, revert to default ordering. */ - if (ordered_services != NULL) { - if (g_queue_get_length (ordered_services) != n_children) + if (!mail_account_store_load_sort_order_queue (store, ordered_services, NULL)) { + g_queue_free (ordered_services); ordered_services = NULL; + use_default_order = TRUE; + } } - use_default_order = (ordered_services == NULL); - /* Build a queue of CamelServices in the order they appear in * the list store. We'll use this to construct the mapping to * pass to gtk_list_store_reorder(). */ @@ -1334,7 +1402,10 @@ e_mail_account_store_reorder_services (EMailAccountStore *store, default_order, (GCompareDataFunc) mail_account_store_default_compare, store); + if (ordered_services) + g_queue_free (ordered_services); ordered_services = default_order; + default_order = NULL; } new_order = g_new0 (gint, n_children); @@ -1357,9 +1428,12 @@ e_mail_account_store_reorder_services (EMailAccountStore *store, if (new_pos == n_children) { gtk_list_store_reorder (GTK_LIST_STORE (store), new_order); - g_signal_emit ( - store, signals[SERVICES_REORDERED], 0, - use_default_order); + if (!e_mail_account_store_reorder_is_frozen (store)) + g_signal_emit ( + store, signals[SERVICES_REORDERED], 0, + use_default_order); + else + store->priv->reorder_changed_frozen = TRUE; } g_free (new_order); @@ -1367,10 +1441,50 @@ e_mail_account_store_reorder_services (EMailAccountStore *store, if (current_order != NULL) g_queue_free (current_order); + if (ordered_services) + g_queue_free (ordered_services); + if (default_order != NULL) g_queue_free (default_order); } +void +e_mail_account_store_reorder_freeze (EMailAccountStore *store) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (store->priv->reorder_freeze + 1 > 0); + + g_atomic_int_add (&store->priv->reorder_freeze, 1); + + if (store->priv->reorder_freeze == 1) + store->priv->reorder_changed_frozen = FALSE; +} + +void +e_mail_account_store_reorder_thaw (EMailAccountStore *store) +{ + g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store)); + g_return_if_fail (store->priv->reorder_freeze > 0); + + g_atomic_int_add (&store->priv->reorder_freeze, -1); + + if (!store->priv->reorder_freeze && store->priv->reorder_changed_frozen) { + store->priv->reorder_changed_frozen = FALSE; + + g_signal_emit ( + store, signals[SERVICES_REORDERED], 0, + FALSE); + } +} + +gboolean +e_mail_account_store_reorder_is_frozen (EMailAccountStore *store) +{ + g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); + + return store->priv->reorder_freeze > 0; +} + gint e_mail_account_store_compare_services (EMailAccountStore *store, CamelService *service_a, @@ -1422,48 +1536,16 @@ e_mail_account_store_load_sort_order (EMailAccountStore *store, GError **error) { GQueue service_queue = G_QUEUE_INIT; - EMailSession *session; - GKeyFile *key_file; - const gchar *filename; - gchar **service_uids; - gboolean success = TRUE; - gsize ii, length; g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE); - session = e_mail_account_store_get_session (store); - - key_file = g_key_file_new (); - filename = store->priv->sort_order_filename; - - if (g_file_test (filename, G_FILE_TEST_EXISTS)) - success = g_key_file_load_from_file ( - key_file, filename, G_KEY_FILE_NONE, error); - - if (!success) { - g_key_file_free (key_file); + if (!mail_account_store_load_sort_order_queue (store, &service_queue, error)) return FALSE; - } - - /* If the key is not present, length is set to zero. */ - service_uids = g_key_file_get_string_list ( - key_file, "Accounts", "SortOrder", &length, NULL); - - for (ii = 0; ii < length; ii++) { - CamelService *service; - - service = camel_session_get_service ( - CAMEL_SESSION (session), service_uids[ii]); - if (service != NULL) - g_queue_push_tail (&service_queue, service); - } - - e_mail_account_store_reorder_services (store, &service_queue); g_queue_clear (&service_queue); - g_strfreev (service_uids); - g_key_file_free (key_file); + e_mail_account_store_reorder_services (store, + !g_file_test (store->priv->sort_order_filename, G_FILE_TEST_EXISTS)); return TRUE; } diff --git a/mail/e-mail-account-store.h b/mail/e-mail-account-store.h index 51d0afa088..e4b980d1f5 100644 --- a/mail/e-mail-account-store.h +++ b/mail/e-mail-account-store.h @@ -118,6 +118,9 @@ void e_mail_account_store_remove_service (EMailAccountStore *store, GtkWindow *parent_window, CamelService *service); +gboolean e_mail_account_store_has_service + (EMailAccountStore *store, + CamelService *service); void e_mail_account_store_enable_service (EMailAccountStore *store, GtkWindow *parent_window, @@ -134,7 +137,13 @@ void e_mail_account_store_queue_enabled_services GQueue *out_queue); void e_mail_account_store_reorder_services (EMailAccountStore *store, - GQueue *ordered_services); + gboolean use_default_order); +void e_mail_account_store_reorder_freeze + (EMailAccountStore *store); +void e_mail_account_store_reorder_thaw + (EMailAccountStore *store); +gboolean e_mail_account_store_reorder_is_frozen + (EMailAccountStore *store); gint e_mail_account_store_compare_services (EMailAccountStore *store, CamelService *service_a, diff --git a/mail/e-mail-ui-session.c b/mail/e-mail-ui-session.c index fd9a4a94f2..ee0b77cfe3 100644 --- a/mail/e-mail-ui-session.c +++ b/mail/e-mail-ui-session.c @@ -78,8 +78,6 @@ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_MAIL_UI_SESSION, EMailUISessionPrivate)) -typedef struct _SourceContext SourceContext; - struct _EMailUISessionPrivate { FILE *filter_logfile; EMailAccountStore *account_store; @@ -87,6 +85,8 @@ struct _EMailUISessionPrivate { EAccountList *account_list; gulong account_changed_handler_id; + + guint update_services_id; }; enum { @@ -108,11 +108,6 @@ G_DEFINE_TYPE_WITH_CODE ( E_TYPE_MAIL_SESSION, G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)) -struct _SourceContext { - EMailUISession *session; - CamelService *service; -}; - /* Support for CamelSession.alert_user() *************************************/ static gpointer user_message_dialog; @@ -462,18 +457,6 @@ main_get_filter_driver (CamelSession *session, return driver; } -static void -source_context_free (SourceContext *context) -{ - if (context->session != NULL) - g_object_unref (context->session); - - if (context->service != NULL) - g_object_unref (context->service); - - g_slice_free (SourceContext, context); -} - static void mail_ui_session_dispose (GObject *object) { @@ -613,7 +596,6 @@ mail_ui_session_constructed (GObject *object) account_list, "account-changed", G_CALLBACK (mail_ui_session_account_changed_cb), session); priv->account_changed_handler_id = handler_id; - } static gint @@ -702,12 +684,31 @@ mail_ui_session_get_property (GObject *object, } static gboolean -mail_ui_session_add_service_cb (SourceContext *context) +mail_ui_session_update_services_cb (EMailUISession *mail_session) { EMailAccountStore *store; + GList *list, *iter; + + g_return_val_if_fail (mail_session != NULL, FALSE); + + mail_session->priv->update_services_id = 0; + + store = e_mail_ui_session_get_account_store (mail_session); + e_mail_account_store_reorder_freeze (store); + + list = camel_session_list_services (CAMEL_SESSION (mail_session)); + for (iter = list; iter; iter = iter->next) { + CamelService *service = iter->data; + + if (!service || !CAMEL_IS_STORE (service)) + continue; + + if (!e_mail_account_store_has_service (store, service)) + e_mail_account_store_add_service (store, service); + } - store = e_mail_ui_session_get_account_store (context->session); - e_mail_account_store_add_service (store, context->service); + g_list_free (list); + e_mail_account_store_reorder_thaw (store); return FALSE; } @@ -729,16 +730,15 @@ mail_ui_session_add_service (CamelSession *session, * from an idle callback so the service has a chance to * fully initialize first. */ if (CAMEL_IS_STORE (service)) { - SourceContext *context; + EMailUISession *mail_session = E_MAIL_UI_SESSION (session); - context = g_slice_new0 (SourceContext); - context->session = g_object_ref (session); - context->service = g_object_ref (service); + g_return_val_if_fail (mail_session != NULL, service); - g_idle_add_full ( - G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc) mail_ui_session_add_service_cb, - context, (GDestroyNotify) source_context_free); + if (mail_session->priv->update_services_id == 0) + mail_session->priv->update_services_id = g_idle_add_full ( + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc) mail_ui_session_update_services_cb, + g_object_ref (session), g_object_unref); } return service; -- cgit v1.2.3