[evolution] Bug #604994 - Folder state not preserved in Copy/Move Folder dialog



commit 5accac136eb35405cbb8069e0f12191391c58a1a
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jan 7 16:46:14 2010 +0100

    Bug #604994 - Folder state not preserved in Copy/Move Folder dialog

 mail/e-mail-reader.c              |    2 +
 mail/e-mail-sidebar.c             |   99 +-------------------------
 mail/em-composer-utils.c          |    1 +
 mail/em-folder-selection-button.c |    1 +
 mail/em-folder-tree.c             |  140 +++++++++++++++++++++++++++++++++++++
 mail/em-folder-tree.h             |    4 +
 mail/em-folder-utils.c            |    2 +
 mail/em-utils.c                   |   35 +++++++++
 mail/em-utils.h                   |    3 +
 mail/em-vfolder-rule.c            |    1 +
 10 files changed, 191 insertions(+), 97 deletions(-)
---
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 74b4f1a..5689a96 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -181,6 +181,7 @@ action_mail_copy_cb (GtkAction *action,
 	uids = e_mail_reader_get_selected_uids (reader);
 
 	folder_tree = em_folder_tree_new ();
+	emu_restore_folder_tree_state (EM_FOLDER_TREE (folder_tree));
 
 	em_folder_tree_set_excluded (
 		EM_FOLDER_TREE (folder_tree),
@@ -558,6 +559,7 @@ action_mail_move_cb (GtkAction *action,
 	window = e_mail_reader_get_window (reader);
 
 	folder_tree = em_folder_tree_new ();
+	emu_restore_folder_tree_state (EM_FOLDER_TREE (folder_tree));
 
 	em_folder_tree_set_excluded (
 		EM_FOLDER_TREE (folder_tree),
diff --git a/mail/e-mail-sidebar.c b/mail/e-mail-sidebar.c
index 95379e5..bde8c01 100644
--- a/mail/e-mail-sidebar.c
+++ b/mail/e-mail-sidebar.c
@@ -31,8 +31,6 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), E_TYPE_MAIL_SIDEBAR, EMailSidebarPrivate))
 
-#define STATE_KEY_EXPANDED	"Expanded"
-
 struct _EMailSidebarPrivate {
 	GKeyFile *key_file;  /* not owned */
 };
@@ -55,13 +53,8 @@ mail_sidebar_restore_state (EMailSidebar *sidebar)
 {
 	EMFolderTree *folder_tree;
 	GtkTreeModel *tree_model;
-	GtkTreeView *tree_view;
-	GtkTreeIter iter;
 	GKeyFile *key_file;
-	gboolean valid;
 	gchar *selected;
-	gchar **groups;
-	gint ii;
 
 	key_file = e_mail_sidebar_get_key_file (sidebar);
 
@@ -70,9 +63,7 @@ mail_sidebar_restore_state (EMailSidebar *sidebar)
 		return;
 
 	folder_tree = EM_FOLDER_TREE (sidebar);
-
-	tree_view = GTK_TREE_VIEW (sidebar);
-	tree_model = gtk_tree_view_get_model (tree_view);
+	tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (sidebar));
 
 	/* Restore selected folder. */
 
@@ -83,93 +74,7 @@ mail_sidebar_restore_state (EMailSidebar *sidebar)
 		g_free (selected);
 	}
 
-	/* Set the initial folder tree expanded state in two stages:
-	 *
-	 * 1) Iterate over the "Store" and "Folder" state file groups
-	 *    and apply the "Expanded" keys where possible.
-	 *
-	 * 2) Iterate over the top-level nodes in the folder tree
-	 *    (these are all stores) and expand those that have no
-	 *    corresponding "Expanded" key in the state file.  This
-	 *    ensures that new stores are expanded by default.
-	 */
-
-	/* Stage 1 */
-
-	/* Collapse all so we have a clean slate. */
-	gtk_tree_view_collapse_all (tree_view);
-
-	groups = g_key_file_get_groups (key_file, NULL);
-
-	for (ii = 0; groups[ii] != NULL; ii++) {
-		GtkTreeRowReference *reference;
-		GtkTreePath *path;
-		GtkTreeIter iter;
-		const gchar *group_name = groups[ii];
-		const gchar *key = STATE_KEY_EXPANDED;
-		const gchar *uri;
-		gboolean expanded;
-
-		if (g_str_has_prefix (group_name, "Store ")) {
-			uri = group_name + 6;
-			expanded = TRUE;
-		} else if (g_str_has_prefix (group_name, "Folder ")) {
-			uri = group_name + 7;
-			expanded = FALSE;
-		} else
-			continue;
-
-		if (g_key_file_has_key (key_file, group_name, key, NULL))
-			expanded = g_key_file_get_boolean (
-				key_file, group_name, key, NULL);
-
-		if (!expanded)
-			continue;
-
-		reference = em_folder_tree_model_lookup_uri (
-			EM_FOLDER_TREE_MODEL (tree_model), uri);
-		if (reference == NULL)
-			continue;
-
-		path = gtk_tree_row_reference_get_path (reference);
-		gtk_tree_model_get_iter (tree_model, &iter, path);
-		gtk_tree_view_expand_row (tree_view, path, FALSE);
-		gtk_tree_path_free (path);
-	}
-
-	g_strfreev (groups);
-
-	/* Stage 2 */
-
-	valid = gtk_tree_model_get_iter_first (tree_model, &iter);
-
-	while (valid) {
-		const gchar *key = STATE_KEY_EXPANDED;
-		gchar *group_name;
-		gchar *uri;
-
-		gtk_tree_model_get (
-			tree_model, &iter, COL_STRING_URI, &uri, -1);
-
-		if (uri == NULL)
-			goto next;
-
-		group_name = g_strdup_printf ("Store %s", uri);
-
-		if (!g_key_file_has_key (key_file, group_name, key, NULL)) {
-			GtkTreePath *path;
-
-			path = gtk_tree_model_get_path (tree_model, &iter);
-			gtk_tree_view_expand_row (tree_view, path, FALSE);
-			gtk_tree_path_free (path);
-		}
-
-		g_free (group_name);
-		g_free (uri);
-
-	next:
-		valid = gtk_tree_model_iter_next (tree_model, &iter);
-	}
+	em_folder_tree_restore_state (folder_tree, key_file);
 }
 
 static void
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 1e2ceb0..f537ced 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -2309,6 +2309,7 @@ post_header_clicked_cb (EComposerPostHeader *header,
 	GList *list;
 
 	folder_tree = em_folder_tree_new ();
+	emu_restore_folder_tree_state (EM_FOLDER_TREE (folder_tree));
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index d3d44e5..48737a1 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -216,6 +216,7 @@ folder_selection_button_clicked (GtkButton *button)
 	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
 
 	emft = (EMFolderTree *) em_folder_tree_new ();
+	emu_restore_folder_tree_state (emft);
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (emft));
 	if (priv->multiple_select)
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index c439961..0709f28 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -2586,3 +2586,143 @@ em_folder_tree_set_skip_double_click (EMFolderTree *folder_tree, gboolean skip)
 {
 	folder_tree->priv->skip_double_click = skip;
 }
+
+/* stores come first, then by uri */
+static gint
+sort_by_store_and_uri (gconstpointer name1, gconstpointer name2)
+{
+	const gchar *n1 = name1, *n2 = name2;
+	gboolean is_store1, is_store2;
+
+	if (n1 == NULL || n2 == NULL) {
+		if (n1 == n2)
+			return 0;
+		else
+			return n1 ? -1 : 1;
+	}
+
+	is_store1 = g_str_has_prefix (n1, "Store ");
+	is_store2 = g_str_has_prefix (n2, "Store ");
+
+	if ((is_store1 || is_store2) && (!is_store1 || !is_store2)) {
+		return is_store1 ? -1 : 1;
+	}
+
+	return strcmp (n1, n2);
+}
+
+/* restores state of a tree (collapsed/expanded) as stores in the given key_file */
+void
+em_folder_tree_restore_state (EMFolderTree *folder_tree, GKeyFile *key_file)
+{
+	GtkTreeModel *tree_model;
+	GtkTreeView *tree_view;
+	GtkTreeIter iter;
+	gboolean valid;
+	gchar **groups_arr;
+	GSList *groups, *group;
+	gint ii;
+
+	/* Make sure we have a key file to restore state from. */
+	if (key_file == NULL)
+		return;
+
+	tree_view = GTK_TREE_VIEW (folder_tree);
+	tree_model = gtk_tree_view_get_model (tree_view);
+
+	/* Set the initial folder tree expanded state in two stages:
+	 *
+	 * 1) Iterate over the "Store" and "Folder" state file groups
+	 *    and apply the "Expanded" keys where possible.
+	 *
+	 * 2) Iterate over the top-level nodes in the folder tree
+	 *    (these are all stores) and expand those that have no
+	 *    corresponding "Expanded" key in the state file.  This
+	 *    ensures that new stores are expanded by default.
+	 */
+
+	/* Stage 1 */
+
+	/* Collapse all so we have a clean slate. */
+	gtk_tree_view_collapse_all (tree_view);
+
+	groups_arr = g_key_file_get_groups (key_file, NULL);
+	groups = NULL;
+
+	for (ii = 0; groups_arr[ii] != NULL; ii++) {
+		groups = g_slist_prepend (groups, groups_arr [ii]);
+	}
+
+	groups = g_slist_sort (groups, sort_by_store_and_uri);
+
+	for (group = groups; group != NULL; group = group->next) {
+		GtkTreeRowReference *reference;
+		GtkTreePath *path;
+		GtkTreeIter iter;
+		const gchar *group_name = group->data;
+		const gchar *key = STATE_KEY_EXPANDED;
+		const gchar *uri;
+		gboolean expanded;
+
+		if (g_str_has_prefix (group_name, "Store ")) {
+			uri = group_name + 6;
+			expanded = TRUE;
+		} else if (g_str_has_prefix (group_name, "Folder ")) {
+			uri = group_name + 7;
+			expanded = FALSE;
+		} else
+			continue;
+
+		if (g_key_file_has_key (key_file, group_name, key, NULL))
+			expanded = g_key_file_get_boolean (
+				key_file, group_name, key, NULL);
+
+		if (!expanded)
+			continue;
+
+		reference = em_folder_tree_model_lookup_uri (
+			EM_FOLDER_TREE_MODEL (tree_model), uri);
+		if (reference == NULL)
+			continue;
+
+		path = gtk_tree_row_reference_get_path (reference);
+		gtk_tree_model_get_iter (tree_model, &iter, path);
+		gtk_tree_view_expand_row (tree_view, path, FALSE);
+		gtk_tree_path_free (path);
+	}
+
+	g_slist_free (groups);
+	g_strfreev (groups_arr);
+
+	/* Stage 2 */
+
+	valid = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+	while (valid) {
+		const gchar *key = STATE_KEY_EXPANDED;
+		gchar *group_name;
+		gchar *uri;
+
+		gtk_tree_model_get (
+			tree_model, &iter, COL_STRING_URI, &uri, -1);
+
+		if (uri == NULL)
+			goto next;
+
+		group_name = g_strdup_printf ("Store %s", uri);
+
+		if (!g_key_file_has_key (key_file, group_name, key, NULL)) {
+			GtkTreePath *path;
+
+			path = gtk_tree_model_get_path (tree_model, &iter);
+			gtk_tree_view_expand_row (tree_view, path, FALSE);
+			gtk_tree_path_free (path);
+		}
+
+		g_free (group_name);
+		g_free (uri);
+
+	next:
+		valid = gtk_tree_model_iter_next (tree_model, &iter);
+	}
+}
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index 02730cb..a5722e1 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -53,6 +53,8 @@ typedef struct _EMFolderTree EMFolderTree;
 typedef struct _EMFolderTreeClass EMFolderTreeClass;
 typedef struct _EMFolderTreePrivate EMFolderTreePrivate;
 
+#define STATE_KEY_EXPANDED	"Expanded"
+
 /* not sure this api is the best, but its the easiest to implement and will cover what we need */
 #define EMFT_EXCLUDE_NOSELECT CAMEL_FOLDER_NOSELECT
 #define EMFT_EXCLUDE_NOINFERIORS CAMEL_FOLDER_NOINFERIORS
@@ -122,6 +124,8 @@ void		em_folder_tree_set_skip_double_click
 						(EMFolderTree *folder_tree,
 						 gboolean skip);
 
+void		em_folder_tree_restore_state	(EMFolderTree *folder_tree,
+						 GKeyFile *key_file);
 G_END_DECLS
 
 #endif /* EM_FOLDER_TREE_H */
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index 2838e82..447237f 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -374,6 +374,7 @@ em_folder_utils_copy_folder (GtkWindow *parent,
 
 	/* XXX Do we leak this reference. */
 	emft = (EMFolderTree *) em_folder_tree_new ();
+	emu_restore_folder_tree_state (emft);
 
 	em_folder_tree_set_excluded_func (
 		emft, emfu_copy_folder_exclude, cfd);
@@ -651,6 +652,7 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft,
 	GtkWidget *dialog;
 
 	folder_tree = (EMFolderTree *) em_folder_tree_new ();
+	emu_restore_folder_tree_state (folder_tree);
 
 	dialog = em_folder_selector_create_new (
 		parent, folder_tree, 0,
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 63d3234..eab434d 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -2210,3 +2210,38 @@ em_utils_guess_account (CamelMimeMessage *message, CamelFolder *folder)
 
 	return account;
 }
+
+void
+emu_restore_folder_tree_state (EMFolderTree *folder_tree)
+{
+	EShell *shell;
+	EShellBackend *backend;
+	GKeyFile *key_file;
+	const gchar *config_dir;
+	gchar *filename;
+	GError *error = NULL;
+
+	g_return_if_fail (folder_tree != NULL);
+	g_return_if_fail (EM_IS_FOLDER_TREE (folder_tree));
+
+	shell = e_shell_get_default ();
+	backend = e_shell_get_backend_by_name (shell, "mail");
+	g_return_if_fail (backend != NULL);
+
+	config_dir = e_shell_backend_get_config_dir (backend);
+	g_return_if_fail (config_dir != NULL);
+
+	filename = g_build_filename (config_dir, "state", NULL);
+
+	key_file = g_key_file_new ();
+	g_key_file_load_from_file (key_file, filename, 0, &error);
+	g_free (filename);
+
+	if (error) {
+		g_error_free (error);
+	} else {
+		em_folder_tree_restore_state (folder_tree, key_file);
+	}
+
+	g_key_file_free (key_file);
+}
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 2293dfa..4e3b95e 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -33,6 +33,7 @@
 #include <camel/camel-stream.h>
 
 #include <mail/e-mail-reader.h>
+#include <mail/em-folder-tree.h>
 
 G_BEGIN_DECLS
 
@@ -109,6 +110,8 @@ void emu_remove_from_mail_cache (const GSList *addresses);
 void emu_remove_from_mail_cache_1 (const gchar *address);
 void emu_free_mail_cache (void);
 
+void emu_restore_folder_tree_state (EMFolderTree *folder_tree);
+
 G_END_DECLS
 
 #endif /* __EM_UTILS_H__ */
diff --git a/mail/em-vfolder-rule.c b/mail/em-vfolder-rule.c
index b094cce..4932470 100644
--- a/mail/em-vfolder-rule.c
+++ b/mail/em-vfolder-rule.c
@@ -514,6 +514,7 @@ source_add(GtkWidget *widget, struct _source_data *data)
 	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
 
 	emft =(EMFolderTree *) em_folder_tree_new ();
+	emu_restore_folder_tree_state (emft);
 	em_folder_tree_set_excluded (emft, EMFT_EXCLUDE_NOSELECT);
 
 	dialog = em_folder_selector_new (



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