aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2012-04-20 21:08:17 +0800
committerMilan Crha <mcrha@redhat.com>2012-04-20 21:08:17 +0800
commit61a15e4d9dd303c23b6e44af9d084e3f3c609192 (patch)
tree37795acabe923f9ec5da461736ba7725e72b3806
parent88005e204cac7cf6cdc2203d1e1e238708b07b83 (diff)
downloadgsoc2013-evolution-61a15e4d9dd303c23b6e44af9d084e3f3c609192.tar.gz
gsoc2013-evolution-61a15e4d9dd303c23b6e44af9d084e3f3c609192.tar.zst
gsoc2013-evolution-61a15e4d9dd303c23b6e44af9d084e3f3c609192.zip
Bug #668481 - Account order is not remembered
-rw-r--r--mail/e-mail-account-manager.c2
-rw-r--r--mail/e-mail-account-store.c190
-rw-r--r--mail/e-mail-account-store.h11
-rw-r--r--mail/e-mail-ui-session.c62
4 files changed, 178 insertions, 87 deletions
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;
@@ -463,18 +458,6 @@ main_get_filter_driver (CamelSession *session,
}
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)
{
EMailUISessionPrivate *priv;
@@ -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;