[evolution/gnome-3-4] Bug #668481 - Account order is not remembered



commit 0d575867bea88ffd6d697dbc508a778dffbada48
Author: Milan Crha <mcrha redhat com>
Date:   Fri Apr 20 15:09:21 2012 +0200

    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(-)
---
diff --git a/mail/e-mail-account-manager.c b/mail/e-mail-account-manager.c
index 86a0bf5..8015d9b 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 2dac692..0f505bc 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 51d0afa..e4b980d 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 fd9a4a9..ee0b77c 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;



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