Take copies of ConversationListView's selection for undo ops

Undoable operations like trashing or marking messages need to take a
copy of the conversation lists's selection so that as the selection
changes over time, the op's underlying collection doesn't also change.
This commit is contained in:
Michael Gratton 2019-11-19 10:48:47 +11:00
parent 7f034107b0
commit c37a5412a7
4 changed files with 29 additions and 32 deletions

View file

@ -1021,13 +1021,9 @@ public class Application.Client : Gtk.Application {
// If there was an existing active main, select the same
// account/folder/conversation.
MainWindow? current = this.last_active_main_window;
// Make a copy of the selection so the underlying collection
// doesn't change as the selection does.
this.new_window.begin(
current.selected_folder,
Geary.traverse(
current.conversation_list_view.get_selected_conversations()
).to_linked_list()
current.conversation_list_view.copy_selected()
);
}

View file

@ -1576,7 +1576,7 @@ public class Application.MainWindow :
Gee.Collection<Geary.EmailIdentifier> ids =
new Gee.LinkedList<Geary.EmailIdentifier>();
foreach (Geary.App.Conversation convo in
this.conversation_list_view.get_selected_conversations()) {
this.conversation_list_view.get_selected()) {
ids.add_all(convo.get_email_ids());
}
try {
@ -1874,13 +1874,9 @@ public class Application.MainWindow :
private void on_conversation_activated(Geary.App.Conversation activated) {
if (this.selected_folder != null) {
if (this.selected_folder.special_folder_type != DRAFTS) {
// Make a copy of the selection so the underlying
// collection doesn't change as the selection does.
this.application.new_window.begin(
this.selected_folder,
Geary.traverse(
this.conversation_list_view.get_selected_conversations()
).to_linked_list()
this.conversation_list_view.copy_selected()
);
} else {
// TODO: Determine how to map between conversations
@ -1974,7 +1970,7 @@ public class Application.MainWindow :
bool starred_selected = false;
bool unstarred_selected = false;
foreach (Geary.App.Conversation conversation in
this.conversation_list_view.get_selected_conversations()) {
this.conversation_list_view.get_selected()) {
if (conversation.is_unread())
unread_selected = true;
@ -2031,7 +2027,7 @@ public class Application.MainWindow :
if (location != null) {
this.application.controller.mark_conversations.begin(
location,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
Geary.EmailFlags.UNREAD,
false,
(obj, res) => {
@ -2050,7 +2046,7 @@ public class Application.MainWindow :
if (location != null) {
this.application.controller.mark_conversations.begin(
location,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
Geary.EmailFlags.UNREAD,
true,
(obj, res) => {
@ -2069,7 +2065,7 @@ public class Application.MainWindow :
if (location != null) {
this.application.controller.mark_conversations.begin(
location,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
Geary.EmailFlags.FLAGGED,
true,
(obj, res) => {
@ -2088,7 +2084,7 @@ public class Application.MainWindow :
if (location != null) {
this.application.controller.mark_conversations.begin(
location,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
Geary.EmailFlags.FLAGGED,
false,
(obj, res) => {
@ -2112,7 +2108,7 @@ public class Application.MainWindow :
this.application.controller.move_conversations_special.begin(
source,
destination,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
(obj, res) => {
try {
this.application.controller.move_conversations_special.end(res);
@ -2131,7 +2127,7 @@ public class Application.MainWindow :
this.application.controller.move_conversations.begin(
source,
destination,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
(obj, res) => {
try {
this.application.controller.move_conversations.end(res);
@ -2151,7 +2147,7 @@ public class Application.MainWindow :
this.application.controller.copy_conversations.begin(
source,
destination,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
(obj, res) => {
try {
this.application.controller.copy_conversations.end(res);
@ -2170,7 +2166,7 @@ public class Application.MainWindow :
this.application.controller.move_conversations_special.begin(
source,
ARCHIVE,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
(obj, res) => {
try {
this.application.controller.move_conversations_special.end(res);
@ -2188,7 +2184,7 @@ public class Application.MainWindow :
this.application.controller.move_conversations_special.begin(
source,
Geary.SpecialFolderType.TRASH,
this.conversation_list_view.get_selected_conversations(),
this.conversation_list_view.copy_selected(),
(obj, res) => {
try {
this.application.controller.move_conversations_special.end(res);
@ -2204,7 +2200,7 @@ public class Application.MainWindow :
Geary.FolderSupport.Remove target =
this.selected_folder as Geary.FolderSupport.Remove;
Gee.Collection<Geary.App.Conversation> conversations =
this.conversation_list_view.get_selected_conversations();
this.conversation_list_view.copy_selected();
if (target != null && this.prompt_delete_conversations(conversations.size)) {
this.application.controller.delete_conversations.begin(
target,

View file

@ -131,11 +131,18 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
selection.changed.connect(on_selection_changed);
}
/** Returns a read-only collection of the current selection. */
public Gee.Set<Geary.App.Conversation> get_selected_conversations() {
/** Returns a read-only iteration of the current selection. */
public Gee.Set<Geary.App.Conversation> get_selected() {
return this.selected.read_only_view;
}
/** Returns a copy of the current selection. */
public Gee.Set<Geary.App.Conversation> copy_selected() {
var copy = new Gee.HashSet<Geary.App.Conversation>();
copy.add_all(this.selected);
return copy;
}
public void inhibit_next_autoselect() {
this.should_inhibit_autoselect = true;
}
@ -288,13 +295,11 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
// Get the current conversation. If it's selected, we'll apply the mark operation to
// all selected conversations; otherwise, it just applies to this one.
Geary.App.Conversation conversation = get_model().get_conversation_at_path(path);
Gee.Collection<Geary.App.Conversation> to_mark;
if (this.selected.contains(conversation))
// take a copy of currently selected for handling to
// the signal
to_mark = get_selected_conversations();
else
to_mark = Geary.Collection.single(conversation);
Gee.Collection<Geary.App.Conversation> to_mark = (
this.selected.contains(conversation)
? copy_selected()
: Geary.Collection.single(conversation)
);
if (read_clicked) {
mark_conversations(to_mark, Geary.EmailFlags.UNREAD);

View file

@ -156,7 +156,7 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
// XXX move the ConversationListView management code into
// MainWindow or somewhere more appropriate
ConversationListView conversation_list = main_window.conversation_list_view;
this.selection_while_composing = conversation_list.get_selected_conversations();
this.selection_while_composing = conversation_list.copy_selected();
conversation_list.get_selection().unselect_all();
box.vanished.connect(on_composer_closed);