[evolution] I#302 - Improve restore of selected message in the message list after search



commit 76b6b079b94b2cc4d69083bfa2b8bb45d8d13f6b
Author: Milan Crha <mcrha redhat com>
Date:   Fri Feb 8 13:19:01 2019 +0100

    I#302 - Improve restore of selected message in the message list after search
    
    Closes https://gitlab.gnome.org/GNOME/evolution/issues/302

 src/mail/e-mail-paned-view.c | 139 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 112 insertions(+), 27 deletions(-)
---
diff --git a/src/mail/e-mail-paned-view.c b/src/mail/e-mail-paned-view.c
index 17f0c7c7f3..410cfd0188 100644
--- a/src/mail/e-mail-paned-view.c
+++ b/src/mail/e-mail-paned-view.c
@@ -57,6 +57,10 @@ struct _EMailPanedViewPrivate {
 
        /* Signal handler IDs */
        guint message_list_built_id;
+
+       /* TRUE when folder had been just set */
+       gboolean folder_just_set;
+       gchar *last_selected_uid;
 };
 
 enum {
@@ -118,6 +122,25 @@ mail_paned_view_save_boolean (EMailView *view,
        }
 }
 
+static gboolean
+mail_paned_view_message_list_is_empty (MessageList *message_list)
+{
+       ETreeModel *model;
+       ETreePath root;
+
+       g_return_val_if_fail (IS_MESSAGE_LIST (message_list), TRUE);
+
+       model = e_tree_get_model (E_TREE (message_list));
+       if (!model)
+               return TRUE;
+
+       root = e_tree_model_get_root (model);
+       if (!root)
+               return TRUE;
+
+       return !e_tree_model_node_get_first_child (model, root);
+}
+
 static void
 mail_paned_view_message_list_built_cb (EMailView *view,
                                        MessageList *message_list)
@@ -127,14 +150,14 @@ mail_paned_view_message_list_built_cb (EMailView *view,
        EShellWindow *shell_window;
        CamelFolder *folder;
        GKeyFile *key_file;
+       gboolean ensure_message_selected;
 
        priv = E_MAIL_PANED_VIEW_GET_PRIVATE (view);
 
-       folder = message_list_ref_folder (message_list);
+       ensure_message_selected = priv->folder_just_set;
+       priv->folder_just_set = FALSE;
 
-       g_signal_handler_disconnect (
-               message_list, priv->message_list_built_id);
-       priv->message_list_built_id = 0;
+       folder = message_list_ref_folder (message_list);
 
        shell_view = e_mail_view_get_shell_view (view);
        shell_window = e_shell_view_get_shell_window (shell_view);
@@ -151,26 +174,52 @@ mail_paned_view_message_list_built_cb (EMailView *view,
                e_shell_window_set_safe_mode (shell_window, FALSE);
 
        else {
-               const gchar *key;
-               gchar *folder_uri;
-               gchar *group_name;
-               gchar *uid;
+               gchar *uid = NULL;
+
+               /* This is for regen when setting filter, or when folder changed or such */
+               if (!ensure_message_selected &&
+                   !message_list_selected_count (message_list) &&
+                   !mail_paned_view_message_list_is_empty (message_list)) {
+                       ensure_message_selected = TRUE;
+
+                       if (priv->last_selected_uid &&
+                           message_list_contains_uid (message_list, priv->last_selected_uid)) {
+                               g_free (uid);
+                               uid = g_strdup (priv->last_selected_uid);
+                       }
+               }
 
-               folder_uri = e_mail_folder_uri_from_folder (folder);
+               /* This is to prefer last selected message from the previous search folder
+                  over the stored message. The _set_folder() makes sure to unset
+                  priv->last_selected_uid, when it's not from this folder. */
+               if (ensure_message_selected && !uid && priv->last_selected_uid &&
+                   message_list_contains_uid (message_list, priv->last_selected_uid)) {
+                       uid = g_strdup (priv->last_selected_uid);
+               }
 
-               key = STATE_KEY_SELECTED_MESSAGE;
-               group_name = g_strdup_printf ("Folder %s", folder_uri);
-               uid = g_key_file_get_string (key_file, group_name, key, NULL);
-               g_free (group_name);
+               if (ensure_message_selected && !uid) {
+                       const gchar *key;
+                       gchar *folder_uri;
+                       gchar *group_name;
 
-               g_free (folder_uri);
+                       folder_uri = e_mail_folder_uri_from_folder (folder);
+
+                       key = STATE_KEY_SELECTED_MESSAGE;
+                       group_name = g_strdup_printf ("Folder %s", folder_uri);
+                       uid = g_key_file_get_string (key_file, group_name, key, NULL);
+                       g_free (group_name);
 
-               if (!message_list_contains_uid (message_list, uid) &&
+                       g_free (folder_uri);
+               }
+
+               if (ensure_message_selected && !message_list_contains_uid (message_list, uid) &&
                    e_mail_reader_get_mark_seen_always (E_MAIL_READER (view)))
                        e_mail_reader_unset_folder_just_selected (E_MAIL_READER (view));
 
-               /* Use selection fallbacks if UID is not found. */
-               message_list_select_uid (message_list, uid, TRUE);
+               if (ensure_message_selected) {
+                       /* Use selection fallbacks if UID is not found. */
+                       message_list_select_uid (message_list, uid, TRUE);
+               }
 
                g_free (uid);
        }
@@ -206,10 +255,17 @@ mail_paned_view_message_selected_cb (EMailView *view,
        key = STATE_KEY_SELECTED_MESSAGE;
        group_name = g_strdup_printf ("Folder %s", folder_uri);
 
-       if (message_uid != NULL)
+       /* Only overwrite changes, do not delete the stored selected message,
+          when the current view has nothing (or multiple messages) selected. */
+       if (message_uid != NULL) {
+               EMailPanedView *paned_view = E_MAIL_PANED_VIEW (view);
+
                g_key_file_set_string (key_file, group_name, key, message_uid);
-       else
-               g_key_file_remove_key (key_file, group_name, key, NULL);
+
+               g_clear_pointer (&paned_view->priv->last_selected_uid, g_free);
+               paned_view->priv->last_selected_uid = g_strdup (message_uid);
+       }
+
        e_shell_view_set_state_dirty (shell_view);
 
        g_free (group_name);
@@ -446,6 +502,14 @@ mail_paned_view_dispose (GObject *object)
        }
 
        if (priv->message_list != NULL) {
+               /* It can be disconnected by EMailReader in e_mail_reader_dispose() */
+               if (priv->message_list_built_id &&
+                   g_signal_handler_is_connected (priv->message_list, priv->message_list_built_id)) {
+                       g_signal_handler_disconnect (priv->message_list, priv->message_list_built_id);
+               }
+
+               priv->message_list_built_id = 0;
+
                g_object_unref (priv->message_list);
                priv->message_list = NULL;
        }
@@ -460,6 +524,8 @@ mail_paned_view_dispose (GObject *object)
                priv->view_instance = NULL;
        }
 
+       g_clear_pointer (&priv->last_selected_uid, g_free);
+
        priv->display = NULL;
 
        /* Chain up to parent's dispose() method. */
@@ -628,6 +694,26 @@ mail_paned_view_set_folder (EMailReader *reader,
                return;
        }
 
+       if (priv->last_selected_uid && previous_folder && folder &&
+           CAMEL_IS_VEE_FOLDER (previous_folder)) {
+               CamelFolder *real_folder = NULL;
+               gchar *message_uid = NULL;
+
+               em_utils_get_real_folder_and_message_uid (previous_folder, priv->last_selected_uid, 
&real_folder, NULL, &message_uid);
+
+               g_clear_pointer (&priv->last_selected_uid, g_free);
+
+               if (real_folder == folder && message_uid) {
+                       priv->last_selected_uid = message_uid;
+                       message_uid = NULL;
+               }
+
+               g_free (message_uid);
+               g_clear_object (&real_folder);
+       } else {
+               g_clear_pointer (&priv->last_selected_uid, g_free);
+       }
+
        g_clear_object (&previous_folder);
 
        shell_window = e_shell_view_get_shell_window (shell_view);
@@ -655,13 +741,7 @@ mail_paned_view_set_folder (EMailReader *reader,
        if (e_shell_get_online (shell))
                e_mail_reader_refresh_folder (reader, folder);
 
-       /* This is a one-time-only callback. */
-       if (MESSAGE_LIST (message_list)->cursor_uid == NULL &&
-               priv->message_list_built_id == 0)
-               priv->message_list_built_id = g_signal_connect_swapped (
-                       message_list, "message-list-built",
-                       G_CALLBACK (mail_paned_view_message_list_built_cb),
-                       reader);
+       priv->folder_just_set = TRUE;
 
        /* Restore the folder's preview and threaded state. */
 
@@ -807,6 +887,11 @@ mail_paned_view_constructed (GObject *object)
        priv->message_list = g_object_ref (widget);
        gtk_widget_show (widget);
 
+       priv->message_list_built_id = g_signal_connect_swapped (
+               priv->message_list, "message-list-built",
+               G_CALLBACK (mail_paned_view_message_list_built_cb),
+               object);
+
        container = priv->paned;
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);


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