From ab27aff72c64183166fc6207d2ef0142e1ab8c83 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 13 Jun 2009 15:07:00 -0400 Subject: 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 94855ee68b..edea7cfa6f 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 7d2ef3475a..83e8b7d0a0 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 6c35a4e7e8..4b1d9aedce 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 ecdccc0af7..933393ae80 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 56c11bcfdf..5997eb6ca6 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 f7886bdb2c..d7c5261a7c 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 { @@ -229,6 +235,14 @@ account_removed_cb (EAccountList *accounts, em_folder_tree_model_remove_store (model, si->store); } +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,11 +292,36 @@ 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) { @@ -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 036002d74b..899a6ee1d8 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 0e0ff74417..b8ee5e354a 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -522,6 +522,51 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) return (GtkTreeView *) tree; } +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) { @@ -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 91827ac397..132c9a0b5c 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 fbd2450012..bdf67ecfa0 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 e9fd927894..d770afa2d4 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 900d949251..2f50f3a0cb 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); -- cgit v1.2.3