[evolution] I#806 - Mail: Preserve folder tree expand state in a new window



commit c4d53c3ce2ae9a5c33b6f4ec18d5361fa171800d
Author: Milan Crha <mcrha redhat com>
Date:   Wed Feb 26 15:45:34 2020 +0100

    I#806 - Mail: Preserve folder tree expand state in a new window
    
    Closes https://gitlab.gnome.org/GNOME/evolution/issues/806

 src/mail/e-mail-sidebar.c            |  21 ++++++--
 src/modules/mail/e-mail-shell-view.c | 100 +++++++++++++++++++++++++++++++++++
 src/shell/e-shell-view.c             |  20 ++++---
 src/shell/e-shell-view.h             |   2 +
 src/shell/e-shell-window-actions.c   |   6 +++
 5 files changed, 140 insertions(+), 9 deletions(-)
---
diff --git a/src/mail/e-mail-sidebar.c b/src/mail/e-mail-sidebar.c
index 92ee867457..ad0aafe26a 100644
--- a/src/mail/e-mail-sidebar.c
+++ b/src/mail/e-mail-sidebar.c
@@ -35,6 +35,7 @@ struct _EMailSidebarPrivate {
        GKeyFile *key_file;  /* not owned */
        GtkTreeModel *model;
        GtkTreeSelection *selection;
+       gboolean restoring_state;
 };
 
 enum {
@@ -71,14 +72,17 @@ mail_sidebar_restore_state (EMailSidebar *sidebar)
 
        /* Restore selected folder. */
 
-       selected = g_key_file_get_string (
-               key_file, "Folder Tree", "Selected", NULL);
+       sidebar->priv->restoring_state = TRUE;
+
+       em_folder_tree_restore_state (folder_tree, key_file);
+
+       selected = g_key_file_get_string (key_file, "Folder Tree", "Selected", NULL);
        if (selected != NULL) {
                em_folder_tree_set_selected (folder_tree, selected, FALSE);
                g_free (selected);
        }
 
-       em_folder_tree_restore_state (folder_tree, key_file);
+       sidebar->priv->restoring_state = FALSE;
 }
 
 static void
@@ -150,6 +154,9 @@ mail_sidebar_selection_changed_cb (GtkTreeSelection *selection,
        GKeyFile *key_file;
        gchar *uri = NULL;
 
+       if (sidebar->priv->restoring_state || !gtk_widget_get_realized (GTK_WIDGET (sidebar)))
+               return;
+
        key_file = e_mail_sidebar_get_key_file (sidebar);
 
        /* Make sure we have a key file to record state changes. */
@@ -300,6 +307,10 @@ mail_sidebar_row_expanded (GtkTreeView *tree_view,
        tree_view_class->row_expanded (tree_view, unused, path);
 
        sidebar = E_MAIL_SIDEBAR (tree_view);
+
+       if (sidebar->priv->restoring_state)
+               return;
+
        key_file = e_mail_sidebar_get_key_file (sidebar);
 
        /* Make sure we have a key file to record state changes. */
@@ -369,6 +380,10 @@ mail_sidebar_row_collapsed (GtkTreeView *tree_view,
        gchar *group_name;
 
        sidebar = E_MAIL_SIDEBAR (tree_view);
+
+       if (sidebar->priv->restoring_state)
+               return;
+
        key_file = e_mail_sidebar_get_key_file (sidebar);
 
        /* Make sure we have a key file to record state changes. */
diff --git a/src/modules/mail/e-mail-shell-view.c b/src/modules/mail/e-mail-shell-view.c
index 264cb2d015..4274751321 100644
--- a/src/modules/mail/e-mail-shell-view.c
+++ b/src/modules/mail/e-mail-shell-view.c
@@ -337,6 +337,105 @@ mail_shell_view_show_search_results_folder (EMailShellView *mail_shell_view,
        message_list_thaw (MESSAGE_LIST (message_list));
 }
 
+static void
+e_mail_shell_view_cleanup_state_key_file (EShellView *shell_view)
+{
+       EShellBackend *shell_backend;
+       EMailSession *mail_session;
+       CamelSession *session;
+       GKeyFile *key_file;
+       gchar **groups;
+       gboolean changed = FALSE;
+       gint ii;
+
+       g_return_if_fail (E_IS_MAIL_SHELL_VIEW (shell_view));
+
+       key_file = e_shell_view_get_state_key_file (shell_view);
+       if (!key_file)
+               return;
+
+       shell_backend = e_shell_view_get_shell_backend (shell_view);
+       mail_session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
+
+       if (!mail_session)
+               return;
+
+       session = CAMEL_SESSION (mail_session);
+
+       groups = g_key_file_get_groups (key_file, NULL);
+
+       if (!groups)
+               return;
+
+       for (ii = 0; groups[ii]; ii++) {
+               const gchar *group_name = groups[ii];
+
+               if (g_str_has_prefix (group_name, "Store ")) {
+                       CamelService *service;
+                       const gchar *uid = group_name + 6;
+
+                       service = camel_session_ref_service (session, uid);
+
+                       if (CAMEL_IS_STORE (service)) {
+                               g_object_unref (service);
+                       } else {
+                               changed = TRUE;
+                               g_key_file_remove_group (key_file, group_name, NULL);
+                       }
+               } else if (g_str_has_prefix (group_name, "Folder ")) {
+                       CamelStore *store = NULL;
+                       gchar *folder_name = NULL;
+                       const gchar *uri = group_name + 7;
+
+                       if (e_mail_folder_uri_parse (session, uri, &store, &folder_name, NULL)) {
+                               if (!g_str_has_prefix (uri, "folder:")) {
+                                       gchar *new_style_uri;
+
+                                       new_style_uri = e_mail_folder_uri_build (store, folder_name);
+                                       if (new_style_uri) {
+                                               if (!g_key_file_has_group (key_file, new_style_uri)) {
+                                                       gchar **keys;
+                                                       gint jj;
+
+                                                       keys = g_key_file_get_keys (key_file, group_name, 
NULL, NULL);
+
+                                                       for (jj = 0; keys && keys[jj]; jj++) {
+                                                               const gchar *key = keys[jj];
+                                                               gchar *value;
+
+                                                               value = g_key_file_get_value (key_file, 
group_name, key, NULL);
+
+                                                               if (value) {
+                                                                       g_key_file_set_value (key_file, 
group_name, key, value);
+                                                                       g_free (value);
+                                                               }
+                                                       }
+
+                                                       g_strfreev (keys);
+                                               }
+
+                                               changed = TRUE;
+                                               g_key_file_remove_group (key_file, group_name, NULL);
+                                       }
+                               }
+
+                               g_clear_object (&store);
+                               g_free (folder_name);
+
+                       /* One non-Folder section is named "Folder Tree", thus avoid erasing it and others 
not looking like URI */
+                       } else if (strstr (group_name, ":/")) {
+                               changed = TRUE;
+                               g_key_file_remove_group (key_file, group_name, NULL);
+                       }
+               }
+       }
+
+       g_strfreev (groups);
+
+       if (changed)
+               e_shell_view_set_state_dirty (shell_view);
+}
+
 static void
 mail_shell_view_set_vfolder_allow_expunge (EMailShellView *mail_shell_view,
                                           gboolean value)
@@ -419,6 +518,7 @@ mail_shell_view_constructed (GObject *object)
        G_OBJECT_CLASS (e_mail_shell_view_parent_class)->constructed (object);
 
        e_mail_shell_view_private_constructed (E_MAIL_SHELL_VIEW (object));
+       e_mail_shell_view_cleanup_state_key_file (E_SHELL_VIEW (object));
 }
 
 static void
diff --git a/src/shell/e-shell-view.c b/src/shell/e-shell-view.c
index be5530ddc7..9975da9c7b 100644
--- a/src/shell/e-shell-view.c
+++ b/src/shell/e-shell-view.c
@@ -328,6 +328,19 @@ shell_view_state_timeout_cb (gpointer user_data)
        return FALSE;
 }
 
+void
+e_shell_view_save_state_immediately (EShellView *shell_view)
+{
+       g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+
+       if (shell_view->priv->state_save_timeout_id > 0) {
+               g_source_remove (shell_view->priv->state_save_timeout_id);
+               shell_view->priv->state_save_timeout_id = 0;
+               if (!shell_view->priv->state_save_activity)
+                       shell_view_save_state (shell_view, TRUE);
+       }
+}
+
 static void
 shell_view_emit_toggled (EShellView *shell_view)
 {
@@ -517,12 +530,7 @@ shell_view_dispose (GObject *object)
        priv = E_SHELL_VIEW_GET_PRIVATE (object);
 
        /* Expedite any pending state saves. */
-       if (priv->state_save_timeout_id > 0) {
-               g_source_remove (priv->state_save_timeout_id);
-               priv->state_save_timeout_id = 0;
-               if (priv->state_save_activity == NULL)
-                       shell_view_save_state (E_SHELL_VIEW (object), TRUE);
-       }
+       e_shell_view_save_state_immediately (E_SHELL_VIEW (object));
 
        if (priv->update_actions_idle_id > 0) {
                g_source_remove (priv->update_actions_idle_id);
diff --git a/src/shell/e-shell-view.h b/src/shell/e-shell-view.h
index cdbebc4d1b..82d2970b92 100644
--- a/src/shell/e-shell-view.h
+++ b/src/shell/e-shell-view.h
@@ -222,6 +222,8 @@ EShellTaskbar *     e_shell_view_get_shell_taskbar  (EShellView *shell_view);
 EShellWindow * e_shell_view_get_shell_window   (EShellView *shell_view);
 GKeyFile *     e_shell_view_get_state_key_file (EShellView *shell_view);
 void           e_shell_view_set_state_dirty    (EShellView *shell_view);
+void           e_shell_view_save_state_immediately
+                                               (EShellView *shell_view);
 void           e_shell_view_clear_search       (EShellView *shell_view);
 void           e_shell_view_custom_search      (EShellView *shell_view,
                                                 EFilterRule *custom_rule);
diff --git a/src/shell/e-shell-window-actions.c b/src/shell/e-shell-window-actions.c
index f8c565f1cb..db7c078f66 100644
--- a/src/shell/e-shell-window-actions.c
+++ b/src/shell/e-shell-window-actions.c
@@ -298,11 +298,17 @@ action_new_window_cb (GtkAction *action,
                       EShellWindow *shell_window)
 {
        EShell *shell;
+       EShellView *shell_view;
        const gchar *view_name;
 
        shell = e_shell_window_get_shell (shell_window);
        view_name = e_shell_window_get_active_view (shell_window);
 
+       shell_view = e_shell_window_get_shell_view (shell_window, view_name);
+
+       if (shell_view)
+               e_shell_view_save_state_immediately (shell_view);
+
        e_shell_create_shell_window (shell, view_name);
 }
 


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