Fix bug #3881: Keep read thread during update if it is selected.
[claws.git] / src / summaryview.c
index 2bfb01dcba757e1bdaa3b0d6fbc91bbed56b59f5..8335ed94fe49ebe919ababd6f731bcf83fedb956 100644 (file)
@@ -163,7 +163,8 @@ static void summary_update_status   (SummaryView            *summaryview);
 static void summary_status_show                (SummaryView            *summaryview);
 static void summary_set_column_titles  (SummaryView            *summaryview);
 static void summary_set_ctree_from_list        (SummaryView            *summaryview,
-                                        GSList                 *mlist);
+                                        GSList                 *mlist,
+                                        guint                  selected_msgnum);
 static inline void summary_set_header  (SummaryView            *summaryview,
                                         gchar                  *text[],
                                         MsgInfo                *msginfo);
@@ -1447,7 +1448,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        /* set ctree and hash table from the msginfo list, and
           create the thread */
-       summary_set_ctree_from_list(summaryview, mlist);
+       summary_set_ctree_from_list(summaryview, mlist, selected_msgnum);
 
        g_slist_free(mlist);
 
@@ -1464,7 +1465,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                summary_select_by_msgnum(summaryview, selected_msgnum,
                                                OPEN_SELECTED_ON_SEARCH_RESULTS);
                        else
-                               summary_select_by_msgnum(summaryview, selected_msgnum, FALSE);
+                               summary_select_by_msgnum(summaryview, selected_msgnum,
+                                               OPEN_SELECTED_ON_FOLDER_OPEN);
 
                        summary_lock(summaryview);
                        if (!summaryview->selected) {
@@ -1483,7 +1485,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                        summary_select_node(summaryview, node,
                                                        OPEN_SELECTED_ON_SEARCH_RESULTS);
                                else
-                                       summary_select_node(summaryview, node, FALSE);
+                                       summary_select_node(summaryview, node,
+                                                       OPEN_SELECTED_ON_FOLDER_OPEN);
 
                                summary_lock(summaryview);
                        }
@@ -1516,15 +1519,27 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                        
                        switch(act) {
                        case ACTION_MARKED:
-                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                               if (summaryview->sort_type == SORT_ASCENDING)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                            MSG_MARKED, FALSE);
+                               else
+                                       node = summary_find_prev_flagged_msg(summaryview, NULL,
                                             MSG_MARKED, FALSE);
                                break;
                        case ACTION_NEW:
-                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                               if (summaryview->sort_type == SORT_ASCENDING)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                            MSG_NEW, FALSE);
+                               else
+                                       node = summary_find_prev_flagged_msg(summaryview, NULL,
                                             MSG_NEW, FALSE);
                                break;
                        case ACTION_UNREAD:
-                               node = summary_find_next_flagged_msg(summaryview, NULL,
+                               if (summaryview->sort_type == SORT_ASCENDING)
+                                       node = summary_find_next_flagged_msg(summaryview, NULL,
+                                            MSG_UNREAD, FALSE);
+                               else
+                                       node = summary_find_prev_flagged_msg(summaryview, NULL,
                                             MSG_UNREAD, FALSE);
                                break;
                        case ACTION_LAST_OPENED:
@@ -3076,6 +3091,35 @@ static gboolean summary_thread_is_read(GNode *gnode)
     return all_read;
 }
 
+typedef struct  _ThreadSelectedData {
+       guint msgnum;
+       gboolean is_selected;
+} ThreadSelectedData;
+
+static gboolean summary_update_is_selected(GNode *gnode, gpointer data)
+{
+       ThreadSelectedData *selected = (ThreadSelectedData *)data;
+       MsgInfo *msginfo = (MsgInfo *)gnode->data;
+
+       if (msginfo->msgnum == selected->msgnum) {
+               selected->is_selected = TRUE;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean summary_thread_is_selected(GNode *gnode, guint selected_msgnum)
+{
+       ThreadSelectedData selected;
+
+       selected.msgnum = selected_msgnum;
+       selected.is_selected = FALSE;
+       g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                       summary_update_is_selected, &selected);
+       return selected.is_selected;
+}
+
 static gboolean summary_insert_gnode_func(GtkCMCTree *ctree, guint depth, GNode *gnode,
                                   GtkCMCTreeNode *cnode, gpointer data)
 {
@@ -3127,7 +3171,7 @@ static gboolean summary_insert_gnode_func(GtkCMCTree *ctree, guint depth, GNode
 }
 
 static void summary_set_ctree_from_list(SummaryView *summaryview,
-                                       GSList *mlist)
+                                       GSList *mlist, guint selected_msgnum)
 {
        GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
        MsgInfo *msginfo;
@@ -3170,14 +3214,14 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
                
                for (gnode = root->children; gnode != NULL;
                     gnode = gnode->next) {
-            if (!summaryview->folder_item->hide_read_threads ||
-                    !summary_thread_is_read(gnode))
-            {
-                summary_find_thread_age(gnode);
-                node = gtk_sctree_insert_gnode
-                    (ctree, NULL, node, gnode,
-                     summary_insert_gnode_func, summaryview);
-            }
+                       if (!summaryview->folder_item->hide_read_threads ||
+                           !summary_thread_is_read(gnode) ||
+                           summary_thread_is_selected(gnode, selected_msgnum)) {
+                               summary_find_thread_age(gnode);
+                               node = gtk_sctree_insert_gnode
+                                       (ctree, NULL, node, gnode,
+                                        summary_insert_gnode_func, summaryview);
+                       }
                }
 
                g_node_destroy(root);