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);