Blob Blame History Raw
diff -up evolution-3.8.5/e-util/e-table-item.c.message-list-select-with-collapsed-threads evolution-3.8.5/e-util/e-table-item.c
--- evolution-3.8.5/e-util/e-table-item.c.message-list-select-with-collapsed-threads	2014-08-25 19:05:29.946290850 +0200
+++ evolution-3.8.5/e-util/e-table-item.c	2014-08-25 19:05:29.995290548 +0200
@@ -1179,6 +1179,24 @@ eti_unfreeze (ETableItem *eti)
 	}
 }
 
+void
+e_table_item_freeze (ETableItem *eti)
+{
+	if (!eti)
+		return;
+
+	eti_freeze (eti);
+}
+
+void
+e_table_item_thaw (ETableItem *eti)
+{
+	if (!eti)
+		return;
+
+	eti_unfreeze (eti);
+}
+
 /*
  * Callback routine: invoked before the ETableModel suffers a change
  */
diff -up evolution-3.8.5/e-util/e-table-item.h.message-list-select-with-collapsed-threads evolution-3.8.5/e-util/e-table-item.h
--- evolution-3.8.5/e-util/e-table-item.h.message-list-select-with-collapsed-threads	2013-08-03 15:22:52.000000000 +0200
+++ evolution-3.8.5/e-util/e-table-item.h	2014-08-25 19:05:29.995290548 +0200
@@ -260,6 +260,9 @@ gboolean	e_table_item_is_editing		(ETabl
 
 void		e_table_item_cursor_scrolled	(ETableItem *eti);
 
+void		e_table_item_freeze		(ETableItem *eti);
+void		e_table_item_thaw		(ETableItem *eti);
+
 G_END_DECLS
 
 #endif /* _E_TABLE_ITEM_H_ */
diff -up evolution-3.8.5/mail/message-list.c.message-list-select-with-collapsed-threads evolution-3.8.5/mail/message-list.c
--- evolution-3.8.5/mail/message-list.c.message-list-select-with-collapsed-threads	2014-08-25 19:05:29.959290770 +0200
+++ evolution-3.8.5/mail/message-list.c	2014-08-25 19:05:29.996290542 +0200
@@ -3224,10 +3224,6 @@ build_tree (MessageList *ml,
 #ifndef BROKEN_ETREE
 	ETreePath *top;
 #endif
-	gchar *saveuid = NULL;
-#ifdef BROKEN_ETREE
-	GPtrArray *selected;
-#endif
 #ifdef TIMEIT
 	struct timeval start, end;
 	gulong diff;
@@ -3247,35 +3243,19 @@ build_tree (MessageList *ml,
 		ml->tree_root =	e_tree_memory_node_insert (E_TREE_MEMORY (etm), NULL, 0, NULL);
 	}
 
-	if (ml->cursor_uid)
-		saveuid = find_next_selectable (ml);
-
 #ifndef BROKEN_ETREE
 	top = e_tree_model_node_get_first_child (etm, ml->tree_root);
 	if (top == NULL || changes == NULL) {
-#else
-		selected = message_list_get_selected (ml);
 #endif
+		if (table_item)
+			e_table_item_freeze (table_item);
+
 		e_tree_memory_freeze (E_TREE_MEMORY (etm));
 		clear_tree (ml, FALSE);
 
 		build_subtree (ml, ml->tree_root, thread->tree, &row);
 
-		if (!can_scroll_to_cursor && table_item)
-			table_item->queue_show_cursor = FALSE;
-
-		e_tree_memory_thaw (E_TREE_MEMORY (etm));
 #ifdef BROKEN_ETREE
-
-		/* it's required to thaw & freeze, to propagate changes */
-		e_tree_memory_freeze (E_TREE_MEMORY (etm));
-
-		message_list_set_selected (ml, selected);
-		em_utils_uids_free (selected);
-
-		if (!can_scroll_to_cursor && table_item)
-			table_item->queue_show_cursor = FALSE;
-
 		e_tree_memory_thaw (E_TREE_MEMORY (etm));
 #else
 	} else {
@@ -3286,42 +3266,13 @@ build_tree (MessageList *ml,
 		tree_equal (ml->model, top, thread->tree);
 	}
 #endif
-	if (!saveuid && ml->cursor_uid && g_hash_table_lookup (ml->uid_nodemap, ml->cursor_uid)) {
-		/* this makes sure a visible node is selected, like when
-		 * collapsing all nodes and a children had been selected
-		*/
-		saveuid = g_strdup (ml->cursor_uid);
-	}
-
-	if (saveuid) {
-		ETreePath node = g_hash_table_lookup (ml->uid_nodemap, saveuid);
-		if (node == NULL) {
-			g_free (ml->cursor_uid);
-			ml->cursor_uid = NULL;
-			g_signal_emit (ml, message_list_signals[MESSAGE_SELECTED], 0, NULL);
-		} else {
-			ETree *tree = E_TREE (ml);
-			ETreePath parent = node;
-
-			while (parent = e_tree_model_node_get_parent (etm, parent), parent) {
-				if (!e_tree_node_is_expanded (tree, parent))
-					node = parent;
-			}
-
-			e_tree_memory_freeze (E_TREE_MEMORY (etm));
 
-			e_tree_set_cursor (E_TREE (ml), node);
-
-			if (!can_scroll_to_cursor && table_item)
-				table_item->queue_show_cursor = FALSE;
-
-			e_tree_memory_thaw (E_TREE_MEMORY (etm));
-		}
-		g_free (saveuid);
-	} else if (ml->cursor_uid && !g_hash_table_lookup (ml->uid_nodemap, ml->cursor_uid)) {
-		g_free (ml->cursor_uid);
-		ml->cursor_uid = NULL;
-		g_signal_emit (ml, message_list_signals[MESSAGE_SELECTED], 0, NULL);
+	if (table_item) {
+		/* Show the cursor unless we're responding to a
+		 * "folder-changed" signal from our CamelFolder. */
+		if (!can_scroll_to_cursor)
+			table_item->queue_show_cursor = FALSE;
+		e_table_item_thaw (table_item);
 	}
 
 #ifdef TIMEIT
@@ -4863,6 +4814,9 @@ regen_list_done (struct _regen_list_msg
 	searching = m->ml->search && *m->ml->search;
 
 	if (m->dotree) {
+		ETableItem *table_item = e_tree_get_item (E_TREE (m->ml));
+		GPtrArray *selected;
+		gchar *saveuid = NULL;
 		gboolean forcing_expand_state = m->ml->expand_all || m->ml->collapse_all;
 
 		if (m->ml->just_set_folder) {
@@ -4877,6 +4831,11 @@ regen_list_done (struct _regen_list_msg
 		if (forcing_expand_state || searching)
 			e_tree_force_expanded_state (tree, (m->ml->expand_all || searching) ? 1 : -1);
 
+		if (m->ml->cursor_uid != NULL)
+			saveuid = find_next_selectable (m->ml);
+
+		selected = message_list_get_selected (m->ml);
+
 		build_tree (m->ml, m->tree, m->changes, m->scroll_to_cursor);
 		if (m->ml->thread_tree)
 			camel_folder_thread_messages_unref (m->ml->thread_tree);
@@ -4893,6 +4852,67 @@ regen_list_done (struct _regen_list_msg
 
 		m->ml->expand_all = 0;
 		m->ml->collapse_all = 0;
+
+		/* restore cursor position only after the expand state is restored,
+		   thus the row numbers will actually match their real rows in UI */
+
+		e_table_item_freeze (table_item);
+
+		message_list_set_selected (m->ml, selected);
+		g_ptr_array_unref (selected);
+
+		/* Show the cursor unless we're responding to a
+		 * "folder-changed" signal from our CamelFolder. */
+		if (!m->scroll_to_cursor && table_item != NULL)
+			table_item->queue_show_cursor = FALSE;
+
+		e_table_item_thaw (table_item);
+
+		if (!saveuid && m->ml->cursor_uid && g_hash_table_lookup (m->ml->uid_nodemap, m->ml->cursor_uid)) {
+			/* this makes sure a visible node is selected, like when
+			 * collapsing all nodes and a children had been selected
+			*/
+			saveuid = g_strdup (m->ml->cursor_uid);
+		}
+
+		if (saveuid) {
+			ETreePath node;
+
+			node = g_hash_table_lookup (m->ml->uid_nodemap, saveuid);
+			if (node == NULL) {
+				g_free (m->ml->cursor_uid);
+				m->ml->cursor_uid = NULL;
+				g_signal_emit (m->ml, message_list_signals[MESSAGE_SELECTED], 0, NULL);
+
+			} else {
+				ETree *tree = E_TREE (m->ml);
+				ETreeModel *etm = m->ml->model;
+				ETreePath parent = node;
+
+				while (parent = e_tree_model_node_get_parent (etm, parent), parent) {
+					if (!e_tree_node_is_expanded (tree, parent))
+						node = parent;
+				}
+
+				e_table_item_freeze (table_item);
+
+				e_tree_set_cursor (E_TREE (m->ml), node);
+
+				/* Show the cursor unless we're responding to a
+				 * "folder-changed" signal from our CamelFolder. */
+				if (!m->scroll_to_cursor && table_item != NULL)
+					table_item->queue_show_cursor = FALSE;
+
+				e_table_item_thaw (table_item);
+			}
+			g_free (saveuid);
+		} else if (m->ml->cursor_uid && !g_hash_table_lookup (m->ml->uid_nodemap, m->ml->cursor_uid)) {
+			g_free (m->ml->cursor_uid);
+			m->ml->cursor_uid = NULL;
+			g_signal_emit (
+				m->ml,
+				message_list_signals[MESSAGE_SELECTED], 0, NULL);
+		}
 	} else
 		build_flat (m->ml, m->summary, m->changes);