[evolution/kill-bonobo: 65/65] Thought of a better way to copy folder tree state.



commit ab27aff72c64183166fc6207d2ef0142e1ab8c83
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat Jun 13 15:07:00 2009 -0400

    Thought of a better way to copy folder tree state.
    
    Revert the expanded tree model column and add a "selection"property to
    EMFolderTreeModel, which the sidebar sets.  If set, all new EMFolderTree
    instances will automatically mimic its expanded and selected state.

 mail/e-mail-reader.c                             |    4 -
 mail/e-mail-shell-sidebar.c                      |   33 +------
 mail/em-composer-utils.c                         |    1 -
 mail/em-folder-selection-button.c                |    1 -
 mail/em-folder-selection.c                       |    1 -
 mail/em-folder-tree-model.c                      |   93 ++++++++++++++++++++-
 mail/em-folder-tree-model.h                      |    7 ++-
 mail/em-folder-tree.c                            |  100 +++++++++++++---------
 mail/em-folder-tree.h                            |    1 -
 mail/em-folder-utils.c                           |    1 -
 plugins/groupwise-features/install-shared.c      |    1 -
 plugins/groupwise-features/share-folder-common.c |    1 -
 12 files changed, 162 insertions(+), 82 deletions(-)
---
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 94855ee..edea7cf 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -167,8 +167,6 @@ action_mail_copy_cb (GtkAction *action,
 
 	folder = message_list->folder;
 
-	em_folder_tree_clone_expanded (folder_tree);
-
 	em_folder_tree_set_excluded (
 		EM_FOLDER_TREE (folder_tree),
 		EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL |
@@ -579,8 +577,6 @@ action_mail_move_cb (GtkAction *action,
 
 	folder = message_list->folder;
 
-	em_folder_tree_clone_expanded (folder_tree);
-
 	em_folder_tree_set_excluded (
 		EM_FOLDER_TREE (folder_tree),
 		EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL |
diff --git a/mail/e-mail-shell-sidebar.c b/mail/e-mail-shell-sidebar.c
index 7d2ef34..83e8b7d 100644
--- a/mail/e-mail-shell-sidebar.c
+++ b/mail/e-mail-shell-sidebar.c
@@ -91,10 +91,6 @@ mail_shell_sidebar_restore_state (EMailShellSidebar *mail_shell_sidebar)
 	 *    (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.
-	 *
-	 * The expanded state is recorded and maintained in the tree model
-	 * so that folder trees in other contexts can duplicate it using
-	 * em_folder_tree_clone_expanded().
 	 */
 
 	/* Stage 1 */
@@ -135,12 +131,6 @@ mail_shell_sidebar_restore_state (EMailShellSidebar *mail_shell_sidebar)
 		gtk_tree_model_get_iter (tree_model, &iter, path);
 		gtk_tree_view_expand_row (tree_view, path, FALSE);
 		gtk_tree_path_free (path);
-
-		/* The expanded column is used to clone the sidebar's
-		 * expanded state in other EMFolderTree instances. */
-		gtk_tree_store_set (
-			GTK_TREE_STORE (tree_model), &iter,
-			COL_BOOL_EXPANDED, TRUE, -1);
 	}
 
 	g_strfreev (groups);
@@ -168,12 +158,6 @@ mail_shell_sidebar_restore_state (EMailShellSidebar *mail_shell_sidebar)
 			path = gtk_tree_model_get_path (tree_model, &iter);
 			gtk_tree_view_expand_row (tree_view, path, FALSE);
 			gtk_tree_path_free (path);
-
-			/* The expanded column is used to clone the sidebar's
-			 * expanded state in other EMFolderTree instances. */
-			gtk_tree_store_set (
-				GTK_TREE_STORE (tree_model), &iter,
-				COL_BOOL_EXPANDED, TRUE, -1);
 		}
 
 		g_free (group_name);
@@ -212,12 +196,6 @@ mail_shell_sidebar_row_collapsed_cb (EShellSidebar *shell_sidebar,
 
 	g_return_if_fail (is_store || is_folder);
 
-	/* The expanded column is used to clone the sidebar's
-	 * expanded state in other EMFolderTree instances. */
-	gtk_tree_store_set (
-		GTK_TREE_STORE (model), iter,
-		COL_BOOL_EXPANDED, FALSE, -1);
-
 	key = STATE_KEY_EXPANDED;
 	if (is_store)
 		group_name = g_strdup_printf ("Store %s", uri);
@@ -266,12 +244,6 @@ mail_shell_sidebar_row_expanded_cb (EShellSidebar *shell_sidebar,
 
 		g_return_if_fail (is_store || is_folder);
 
-		/* The expanded column is used to clone the sidebar's
-		 * expanded state in other EMFolderTree instances. */
-		gtk_tree_store_set (
-			GTK_TREE_STORE (model), &iter,
-			COL_BOOL_EXPANDED, TRUE, -1);
-
 		key = STATE_KEY_EXPANDED;
 		if (is_store)
 			group_name = g_strdup_printf ("Store %s", uri);
@@ -487,7 +459,10 @@ mail_shell_sidebar_constructed (GObject *object)
 	tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree);
 	selection = gtk_tree_view_get_selection (tree_view);
 
-	mail_shell_sidebar_restore_state (mail_shell_sidebar);
+	if (em_folder_tree_model_get_selection (folder_tree_model) == NULL)
+		mail_shell_sidebar_restore_state (mail_shell_sidebar);
+
+	em_folder_tree_model_set_selection (folder_tree_model, selection);
 
 	g_signal_connect_swapped (
 		tree_view, "row-collapsed",
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 6c35a4e..4b1d9ae 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -2408,7 +2408,6 @@ post_header_clicked_cb (EComposerPostHeader *header,
 	model = e_mail_shell_backend_get_folder_tree_model (mail_shell_backend);
 	folder_tree = em_folder_tree_new_with_model (model);
 
-	em_folder_tree_clone_expanded (EM_FOLDER_TREE (folder_tree));
 	em_folder_tree_set_multiselect (EM_FOLDER_TREE (folder_tree), TRUE);
 
 	em_folder_tree_set_excluded (
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index ecdccc0..933393a 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -256,7 +256,6 @@ folder_selection_button_clicked (GtkButton *button)
 
 	emft = (EMFolderTree *) em_folder_tree_new_with_model (priv->model);
 
-	em_folder_tree_clone_expanded (emft);
 	em_folder_tree_set_multiselect (emft, priv->multiple_select);
 	em_folder_tree_set_excluded (
 		emft, EMFT_EXCLUDE_NOSELECT |
diff --git a/mail/em-folder-selection.c b/mail/em-folder-selection.c
index 56c11bc..5997eb6 100644
--- a/mail/em-folder-selection.c
+++ b/mail/em-folder-selection.c
@@ -52,7 +52,6 @@ em_select_folder (EMFolderTreeModel *model,
 
 	/* XXX Do we leak this reference? */
 	emft = (EMFolderTree *) em_folder_tree_new_with_model (model);
-	em_folder_tree_clone_expanded (emft);
 
 	if (exclude)
 		em_folder_tree_set_excluded_func (emft, exclude, user_data);
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index f7886bd..d7c5261 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -63,6 +63,11 @@
 struct _EMFolderTreeModelPrivate {
 	gpointer shell_backend;  /* weak pointer */
 
+	/* This is set by EMailShellSidebar.  It allows new EMFolderTree
+	 * instances to initialize their selection and expanded states to
+	 * mimic the sidebar. */
+	GtkTreeSelection *selection;  /* weak reference */
+
 	EAccountList *accounts;
 
 	/* EAccount -> EMFolderTreeStoreInfo */
@@ -80,7 +85,8 @@ struct _EMFolderTreeModelPrivate {
 
 enum {
 	PROP_0,
-	PROP_SHELL_BACKEND
+	PROP_SHELL_BACKEND,
+	PROP_SELECTION
 };
 
 enum {
@@ -230,6 +236,14 @@ account_removed_cb (EAccountList *accounts,
 }
 
 static void
+folder_tree_model_selection_finalized_cb (EMFolderTreeModel *model)
+{
+	model->priv->selection = NULL;
+
+	g_object_notify (G_OBJECT (model), "selection");
+}
+
+static void
 folder_tree_model_set_shell_backend (EMFolderTreeModel *model,
                                     EShellBackend *shell_backend)
 {
@@ -254,6 +268,12 @@ folder_tree_model_set_property (GObject *object,
 				EM_FOLDER_TREE_MODEL (object),
 				g_value_get_object (value));
 			return;
+
+		case PROP_SELECTION:
+			em_folder_tree_model_set_selection (
+				EM_FOLDER_TREE_MODEL (object),
+				g_value_get_object (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -272,12 +292,37 @@ folder_tree_model_get_property (GObject *object,
 				em_folder_tree_model_get_mail_shell_backend (
 				EM_FOLDER_TREE_MODEL (object)));
 			return;
+
+		case PROP_SELECTION:
+			g_value_set_object (
+				value,
+				em_folder_tree_model_get_selection (
+				EM_FOLDER_TREE_MODEL (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
 static void
+folder_tree_model_dispose (GObject *object)
+{
+	EMFolderTreeModelPrivate *priv;
+
+	priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (object);
+
+	if (priv->selection != NULL) {
+		g_object_weak_unref (
+			G_OBJECT (priv->selection), (GWeakNotify)
+			folder_tree_model_selection_finalized_cb, object);
+		priv->selection = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
 folder_tree_model_finalize (GObject *object)
 {
 	EMFolderTreeModelPrivate *priv;
@@ -308,6 +353,7 @@ folder_tree_model_class_init (EMFolderTreeModelClass *class)
 	object_class = G_OBJECT_CLASS (class);
 	object_class->set_property = folder_tree_model_set_property;
 	object_class->get_property = folder_tree_model_get_property;
+	object_class->dispose = folder_tree_model_dispose;
 	object_class->finalize = folder_tree_model_finalize;
 
 	g_object_class_install_property (
@@ -321,6 +367,16 @@ folder_tree_model_class_init (EMFolderTreeModelClass *class)
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT_ONLY));
 
+	g_object_class_install_property (
+		object_class,
+		PROP_SELECTION,
+		g_param_spec_object (
+			"selection",
+			"Selection",
+			NULL,
+			GTK_TYPE_TREE_SELECTION,
+			G_PARAM_READWRITE));
+
 	signals[LOADING_ROW] = g_signal_new (
 		"loading-row",
 		G_OBJECT_CLASS_TYPE (object_class),
@@ -369,7 +425,6 @@ folder_tree_model_init (EMFolderTreeModel *model)
 		G_TYPE_STRING,   /* uri */
 		G_TYPE_UINT,     /* unread count */
 		G_TYPE_UINT,     /* flags */
-		G_TYPE_BOOLEAN,  /* is expanded in sidebar */
 		G_TYPE_BOOLEAN,  /* is a store node */
 		G_TYPE_BOOLEAN,  /* is a folder node */
 		G_TYPE_BOOLEAN,  /* has not-yet-loaded subfolders */
@@ -457,6 +512,40 @@ em_folder_tree_model_get_mail_shell_backend (EMFolderTreeModel *model)
 	return model->priv->shell_backend;
 }
 
+GtkTreeSelection *
+em_folder_tree_model_get_selection (EMFolderTreeModel *model)
+{
+	g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL);
+
+	return GTK_TREE_SELECTION (model->priv->selection);
+}
+
+void
+em_folder_tree_model_set_selection (EMFolderTreeModel *model,
+                                    GtkTreeSelection *selection)
+{
+	g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
+
+	if (selection != NULL)
+		g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
+
+	if (model->priv->selection != NULL) {
+		g_object_weak_unref (
+			G_OBJECT (model->priv->selection), (GWeakNotify)
+			folder_tree_model_selection_finalized_cb, model);
+		model->priv->selection = NULL;
+	}
+
+	model->priv->selection = selection;
+
+	if (model->priv->selection != NULL)
+		g_object_weak_ref (
+			G_OBJECT (model->priv->selection), (GWeakNotify)
+			folder_tree_model_selection_finalized_cb, model);
+
+	g_object_notify (G_OBJECT (model), "selection");
+}
+
 void
 em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
                                       GtkTreeIter *iter,
diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
index 036002d..899a6ee 100644
--- a/mail/em-folder-tree-model.h
+++ b/mail/em-folder-tree-model.h
@@ -63,7 +63,6 @@ enum {
 	COL_UINT_UNREAD,          /* unread count */
 	COL_UINT_FLAGS,		/* FolderInfo.flags */
 
-	COL_BOOL_EXPANDED,        /* node is expanded in sidebar */
 	COL_BOOL_IS_STORE,        /* toplevel store node? */
 	COL_BOOL_IS_FOLDER,       /* folder (not a store) */
 	COL_BOOL_LOAD_SUBDIRS,    /* %TRUE only if the store/folder
@@ -116,6 +115,12 @@ EMFolderTreeModel *
 EMailShellBackend *
 		em_folder_tree_model_get_mail_shell_backend
 					(EMFolderTreeModel *model);
+GtkTreeSelection *
+		em_folder_tree_model_get_selection
+					(EMFolderTreeModel *model);
+void		em_folder_tree_model_set_selection
+					(EMFolderTreeModel *model,
+					 GtkTreeSelection *selection);
 void		em_folder_tree_model_set_folder_info
 					(EMFolderTreeModel *model,
 					 GtkTreeIter *iter,
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 0e0ff74..b8ee5e3 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -523,6 +523,51 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model)
 }
 
 static void
+folder_tree_copy_expanded_cb (GtkTreeView *unused,
+                              GtkTreePath *path,
+                              GtkTreeView *tree_view)
+{
+	gtk_tree_view_expand_row (tree_view, path, FALSE);
+}
+
+static void
+folder_tree_copy_selection_cb (GtkTreeModel *model,
+                               GtkTreePath *path,
+                               GtkTreeIter *iter,
+                               GtkTreeView *tree_view)
+{
+	GtkTreeSelection *selection;
+
+	selection = gtk_tree_view_get_selection (tree_view);
+	gtk_tree_selection_select_path (selection, path);
+
+	/* Center the tree view on the selected path. */
+	gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.0);
+}
+
+static void
+folder_tree_copy_state (EMFolderTree *emft,
+                        EMFolderTreeModel *model)
+{
+	GtkTreeSelection *selection;
+	GtkTreeView *tree_view;
+
+	selection = em_folder_tree_model_get_selection (model);
+	if (selection == NULL)
+		return;
+
+	tree_view = gtk_tree_selection_get_tree_view (selection);
+
+	gtk_tree_view_map_expanded_rows (
+		tree_view, (GtkTreeViewMappingFunc)
+		folder_tree_copy_expanded_cb, emft);
+
+	gtk_tree_selection_selected_foreach (
+		selection, (GtkTreeSelectionForeachFunc)
+		folder_tree_copy_selection_cb, emft);
+}
+
+static void
 em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model)
 {
 	struct _EMFolderTreePrivate *priv = emft->priv;
@@ -530,6 +575,7 @@ em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model)
 
 	priv->model = model;
 	folder_tree_new (emft, model);
+	folder_tree_copy_state (emft, model);
 	gtk_widget_show (GTK_WIDGET (emft));
 
 	g_signal_connect (emft, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft);
@@ -703,38 +749,6 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model)
 	return (GtkWidget *) emft;
 }
 
-static gboolean
-folder_tree_clone_expanded (GtkTreeModel *model,
-                            GtkTreePath *path,
-                            GtkTreeIter *iter,
-                            GtkTreeView *tree_view)
-{
-	gboolean expanded;
-
-	gtk_tree_model_get (model, iter, COL_BOOL_EXPANDED, &expanded, -1);
-
-	if (expanded)
-		gtk_tree_view_expand_row (tree_view, path, FALSE);
-	else
-		gtk_tree_view_collapse_row (tree_view, path);
-
-	return FALSE;
-}
-
-void
-em_folder_tree_clone_expanded (EMFolderTree *emft)
-{
-	GtkTreeModel *model;
-
-	g_return_if_fail (EM_IS_FOLDER_TREE (emft));
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (emft));
-
-	gtk_tree_model_foreach (
-		model, (GtkTreeModelForeachFunc)
-		folder_tree_clone_expanded, emft);
-}
-
 static void
 tree_drag_begin (GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft)
 {
@@ -2042,7 +2056,8 @@ emft_tree_user_event (GtkTreeView *treeview, GdkEvent *e, EMFolderTree *emft)
 }
 
 static void
-emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft)
+emft_tree_selection_changed (GtkTreeSelection *selection,
+                             EMFolderTree *emft)
 {
 	gchar *full_name, *uri;
 	GtkTreeModel *model;
@@ -2075,10 +2090,14 @@ emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft)
 }
 
 void
-em_folder_tree_set_selected (EMFolderTree *emft, const gchar *uri, gboolean expand_only)
+em_folder_tree_set_selected (EMFolderTree *emft,
+                             const gchar *uri,
+                             gboolean expand_only)
 {
 	GList *l = NULL;
 
+	g_return_if_fail (EM_IS_FOLDER_TREE (emft));
+
 	if (uri && uri[0])
 		l = g_list_append(l, (gpointer)uri);
 
@@ -2231,7 +2250,6 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders)
 	return;
 }
 
-
 gchar *
 em_folder_tree_get_selected_uri (EMFolderTree *emft)
 {
@@ -2246,8 +2264,10 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft)
 	tree_view = GTK_TREE_VIEW (emft);
 	selection = gtk_tree_view_get_selection (tree_view);
 
-	if (gtk_tree_selection_get_selected(selection, &model, &iter))
-		gtk_tree_model_get(model, &iter, COL_STRING_URI, &uri, -1);
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+		return NULL;
+
+	gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1);
 
 	return uri;
 }
@@ -2266,8 +2286,10 @@ em_folder_tree_get_selected_path (EMFolderTree *emft)
 	tree_view = GTK_TREE_VIEW (emft);
 	selection = gtk_tree_view_get_selection (tree_view);
 
-	if (gtk_tree_selection_get_selected(selection, &model, &iter))
-		gtk_tree_model_get(model, &iter, COL_STRING_FULL_NAME, &name, -1);
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+		return NULL;
+
+	gtk_tree_model_get (model, &iter, COL_STRING_FULL_NAME, &name, -1);
 
 	return name;
 }
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index 91827ac..132c9a0 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -84,7 +84,6 @@ struct _EMFolderTreeClass {
 
 GType em_folder_tree_get_type (void);
 GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model);
-void em_folder_tree_clone_expanded (EMFolderTree *emft);
 
 void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft);
 
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index fbd2450..bdf67ec 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -706,7 +706,6 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft,
 
 	model = e_mail_shell_backend_get_folder_tree_model (global_mail_shell_backend);
 	folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (model);
-	em_folder_tree_clone_expanded (folder_tree);
 
 	dialog = em_folder_selector_create_new (folder_tree, 0, _("Create Folder"), _("Specify where to create the folder:"));
 	if (folderinfo != NULL)
diff --git a/plugins/groupwise-features/install-shared.c b/plugins/groupwise-features/install-shared.c
index e9fd927..d770afa 100644
--- a/plugins/groupwise-features/install-shared.c
+++ b/plugins/groupwise-features/install-shared.c
@@ -166,7 +166,6 @@ accept_clicked(GnomeDruidPage *page, GtkWidget *druid, CamelMimeMessage *msg)
 	accept_data = g_new0(struct AcceptData, 1);
 	model = mail_component_peek_tree_model (NULL);
 	folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (model);
-	em_folder_tree_clone_expanded (folder_tree);
 
 	dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:"));
 	uri = em_folder_tree_get_selected_uri(folder_tree);
diff --git a/plugins/groupwise-features/share-folder-common.c b/plugins/groupwise-features/share-folder-common.c
index 900d949..2f50f3a 100644
--- a/plugins/groupwise-features/share-folder-common.c
+++ b/plugins/groupwise-features/share-folder-common.c
@@ -383,7 +383,6 @@ create_shared_folder(EPopup *ep, EPopupItem *p, gpointer data)
 
 	model = mail_component_peek_tree_model (mail_component_peek ());
 	folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (model);
-	em_folder_tree_clone_expanded (folder_tree);
 
 	dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:"));
 	uri = em_folder_tree_get_selected_uri(folder_tree);



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