[geary/wip/730682-refine-convo-list] Remove support for traditional multiple selected conversations.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/730682-refine-convo-list] Remove support for traditional multiple selected conversations.
- Date: Sun, 24 Dec 2017 08:10:56 +0000 (UTC)
commit 7dff2f033d596243730ed39e48da12b69255df45
Author: Michael James Gratton <mike vee net>
Date: Sat Dec 23 14:54:46 2017 +1030
Remove support for traditional multiple selected conversations.
In preparation for moving to using selection-mode for the conversation
list, convert it to only supporting a single traditionally selected
conversation. As an added benefit, it does/will lets us simplify a whole
lot of complicated code paths.
* src/client/conversation-list/conversation-list.vala (ConversationList):
Replace get_selected_conversations() with `selected` property. Make arg
for conversation_selection_changed be a single nullable Conversation,
updated when the selection changes. Fix call sites.
* src/client/components/main-toolbar.vala (MainToolbar): Remove
`selected_conversations` property and support code for doing
singular/plural translations of tooltips, just set them in
ui/main-toolbar.ui. Manage visibility of trash vs delete explicitly,
rather than a property + notify handler.
* src/client/components/main-window.vala (MainWindow): Remove
`selected_conversations` and related accessor since we don't need it
anymore. When the selection changes, just load it in the conversation
viewer or clear it.
* src/client/conversation-viewer/conversation-viewer.vala
(ConversationViewer): Remove support for displaying the multiple
conversations placeholder.
src/client/application/geary-controller.vala | 145 +++++++-------------
src/client/components/main-toolbar.vala | 70 +---------
src/client/components/main-window.vala | 50 ++-----
.../conversation-list/conversation-list-item.vala | 5 +-
.../conversation-list/conversation-list-view.vala | 10 +-
.../conversation-list/conversation-list.vala | 66 ++++++----
.../conversation-viewer/conversation-viewer.vala | 26 +---
src/engine/app/app-conversation-monitor.vala | 4 +
ui/conversation-viewer.ui | 14 --
ui/main-toolbar.ui | 37 +++++-
10 files changed, 165 insertions(+), 262 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 6d54410..6d407b6 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -1210,15 +1210,6 @@ public class GearyController : Geary.BaseObject {
return num;
}
- // Update widgets and such to match capabilities of the current folder ... sensitivity is handled
- // by other utility methods
- private void update_ui() {
- main_window.main_toolbar.selected_conversations =
- this.main_window.get_selected_conversations().size;
- main_window.main_toolbar.show_trash_button = current_folder_supports_trash() ||
- !(current_folder is Geary.FolderSupport.Remove);
- }
-
private void on_folder_selected(Geary.Folder? folder) {
debug("Folder %s selected", folder != null ? folder.to_string() : "(null)");
if (folder == null) {
@@ -1324,8 +1315,11 @@ public class GearyController : Geary.BaseObject {
main_window.main_toolbar.copy_folder_menu.enable_disable_folder(current_folder, false);
main_window.main_toolbar.move_folder_menu.enable_disable_folder(current_folder, false);
}
-
- update_ui();
+
+ this.main_window.main_toolbar.update_trash_buttons(
+ current_folder_supports_trash() ||
+ !(current_folder is Geary.FolderSupport.Remove)
+ );
current_conversations = new Geary.App.ConversationMonitor(
current_folder,
@@ -1541,9 +1535,11 @@ public class GearyController : Geary.BaseObject {
private void on_shift_key(bool pressed) {
if (main_window != null && main_window.main_toolbar != null
&& current_account != null && current_folder != null) {
- main_window.main_toolbar.show_trash_button =
- (!pressed && current_folder_supports_trash()) ||
- !(current_folder is Geary.FolderSupport.Remove);
+ main_window.main_toolbar.update_trash_buttons(
+ current_folder_supports_trash() &&
+ current_folder is Geary.FolderSupport.Remove &&
+ !pressed
+ );
}
}
@@ -1555,28 +1551,24 @@ public class GearyController : Geary.BaseObject {
// latest_sent_only uses Email's Date: field, which corresponds to how they're sorted in the
// ConversationViewer
- private Gee.ArrayList<Geary.EmailIdentifier> get_conversation_email_ids(
- Geary.App.Conversation conversation, bool latest_sent_only,
- Gee.ArrayList<Geary.EmailIdentifier> add_to) {
- if (latest_sent_only) {
- Geary.Email? latest = conversation.get_latest_sent_email(
- Geary.App.Conversation.Location.IN_FOLDER_OUT_OF_FOLDER);
- if (latest != null)
- add_to.add(latest.id);
- } else {
- add_to.add_all(conversation.get_email_ids());
- }
-
- return add_to;
- }
-
private Gee.ArrayList<Geary.EmailIdentifier> get_selected_email_ids(bool latest_sent_only) {
- Gee.ArrayList<Geary.EmailIdentifier> ids = new Gee.ArrayList<Geary.EmailIdentifier>();
- foreach (Geary.App.Conversation conversation in this.main_window.get_selected_conversations())
- get_conversation_email_ids(conversation, latest_sent_only, ids);
+ Geary.App.Conversation? conversation =
+ this.main_window.conversation_list.selected;
+ Gee.ArrayList<Geary.EmailIdentifier> ids =
+ new Gee.ArrayList<Geary.EmailIdentifier>();
+ if (conversation != null) {
+ if (latest_sent_only) {
+ Geary.Email? latest = conversation.get_latest_sent_email(
+ Geary.App.Conversation.Location.IN_FOLDER_OUT_OF_FOLDER);
+ if (latest != null)
+ ids.add(latest.id);
+ } else {
+ ids.add_all(conversation.get_email_ids());
+ }
+ }
return ids;
}
-
+
private void mark_email(Gee.Collection<Geary.EmailIdentifier> ids,
Geary.EmailFlags? flags_to_add, Geary.EmailFlags? flags_to_remove) {
if (ids.size > 0) {
@@ -1584,32 +1576,32 @@ public class GearyController : Geary.BaseObject {
ids, flags_to_add, flags_to_remove, cancellable_folder);
}
}
-
+
private void on_show_mark_menu() {
- bool unread_selected = false;
+ Geary.App.Conversation conversation =
+ this.main_window.conversation_list.selected;
+
+ bool unread_selected = conversation.is_unread();
bool read_selected = false;
bool starred_selected = false;
bool unstarred_selected = false;
- foreach (Geary.App.Conversation conversation in this.main_window.get_selected_conversations()) {
- if (conversation.is_unread())
- unread_selected = true;
-
- // Only check the messages that "Mark as Unread" would mark, so we
- // don't add the menu option and have it not do anything.
- //
- // Sort by Date: field to correspond with ConversationViewer ordering
- Geary.Email? latest = conversation.get_latest_sent_email(
- Geary.App.Conversation.Location.IN_FOLDER_OUT_OF_FOLDER);
- if (latest != null && latest.email_flags != null
- && !latest.email_flags.contains(Geary.EmailFlags.UNREAD))
- read_selected = true;
-
- if (conversation.is_flagged()) {
- starred_selected = true;
- } else {
- unstarred_selected = true;
- }
+
+ // Only check the messages that "Mark as Unread" would mark, so we
+ // don't add the menu option and have it not do anything.
+ //
+ // Sort by Date: field to correspond with ConversationViewer ordering
+ Geary.Email? latest = conversation.get_latest_sent_email(
+ Geary.App.Conversation.Location.IN_FOLDER_OUT_OF_FOLDER);
+ if (latest != null && latest.email_flags != null
+ && !latest.email_flags.contains(Geary.EmailFlags.UNREAD))
+ read_selected = true;
+
+ if (conversation.is_flagged()) {
+ starred_selected = true;
+ } else {
+ unstarred_selected = true;
}
+
get_window_action(ACTION_MARK_AS_READ).set_enabled(unread_selected);
get_window_action(ACTION_MARK_AS_UNREAD).set_enabled(read_selected);
get_window_action(ACTION_MARK_AS_STARRED).set_enabled(unstarred_selected);
@@ -1752,16 +1744,11 @@ public class GearyController : Geary.BaseObject {
if (ids.size == 0)
return;
- this.main_window.conversation_list.set_changing_selection(true);
-
Geary.FolderSupport.Move? supports_move = current_folder as Geary.FolderSupport.Move;
if (supports_move != null)
move_conversation_async.begin(
- supports_move, ids, destination.path, cancellable_folder,
- (obj, ret) => {
- move_conversation_async.end(ret);
- this.main_window.conversation_list.set_changing_selection(false);
- });
+ supports_move, ids, destination.path, cancellable_folder
+ );
}
private async void move_conversation_async(Geary.FolderSupport.Move source_folder,
@@ -2312,14 +2299,12 @@ public class GearyController : Geary.BaseObject {
return;
}
- Gee.Set<Geary.App.Conversation> selected_conversations =
this.main_window.get_selected_conversations();
- if (selected_conversations.size == 0)
+ Geary.App.Conversation? selected =
+ this.main_window.conversation_list.selected;
+ if (selected == null)
return;
- last_deleted_conversation = selected_conversations.size > 0
- ? Geary.traverse<Geary.App.Conversation>(selected_conversations).first() : null;
-
- this.main_window.conversation_list.set_changing_selection(true);
+ this.last_deleted_conversation = selected;
Gee.List<Geary.EmailIdentifier> ids = get_selected_email_ids(false);
if (archive) {
@@ -2368,14 +2353,13 @@ public class GearyController : Geary.BaseObject {
last_deleted_conversation = null;
}
}
-
+
private void on_archive_or_delete_selection_finished(Object? source, AsyncResult result) {
try {
archive_or_delete_selection_async.end(result);
} catch (Error e) {
debug("Unable to archive/trash/delete messages: %s", e.message);
}
- this.main_window.conversation_list.set_changing_selection(false);
}
private void save_revokable(Geary.Revokable? new_revokable, string? description) {
@@ -2530,31 +2514,8 @@ public class GearyController : Geary.BaseObject {
return (SimpleAction) this.main_window.lookup_action(action_name);
}
- // Disables all single-message buttons and enables all multi-message buttons.
- public void enable_multiple_message_buttons() {
- main_window.main_toolbar.selected_conversations =
- this.main_window.get_selected_conversations().size;
-
- // Single message only buttons.
- get_window_action(ACTION_REPLY_TO_MESSAGE).set_enabled(false);
- get_window_action(ACTION_REPLY_ALL_MESSAGE).set_enabled(false);
- get_window_action(ACTION_FORWARD_MESSAGE).set_enabled(false);
-
- // Mutliple message buttons.
- get_window_action(ACTION_MOVE_MENU).set_enabled(current_folder is Geary.FolderSupport.Move);
- get_window_action(ACTION_ARCHIVE_CONVERSATION).set_enabled(current_folder is
Geary.FolderSupport.Archive);
- get_window_action(ACTION_TRASH_CONVERSATION).set_enabled(current_folder_supports_trash());
- get_window_action(ACTION_DELETE_CONVERSATION).set_enabled(current_folder is
Geary.FolderSupport.Remove);
-
- cancel_context_dependent_buttons();
- enable_context_dependent_buttons_async.begin(true, cancellable_context_dependent_buttons);
- }
-
// Enables or disables the message buttons on the toolbar.
public void enable_message_buttons(bool sensitive) {
- main_window.main_toolbar.selected_conversations =
- this.main_window.get_selected_conversations().size;
-
// No reply/forward in drafts folder.
bool respond_sensitive = sensitive;
if (current_folder != null && current_folder.special_folder_type == Geary.SpecialFolderType.DRAFTS)
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
index 795a3a3..0ea4749 100644
--- a/src/client/components/main-toolbar.vala
+++ b/src/client/components/main-toolbar.vala
@@ -22,10 +22,6 @@ public class MainToolbar : Gtk.Box {
// Copy and Move popovers
public FolderPopover copy_folder_menu { get; private set; default = new FolderPopover(); }
public FolderPopover move_folder_menu { get; private set; default = new FolderPopover(); }
- // How many conversations are selected right now. Should automatically be updated.
- public int selected_conversations { get; set; }
- // Whether to show the trash or the delete button
- public bool show_trash_button { get; set; default = true; }
// The tooltip of the Undo-button
public string undo_tooltip {
owned get { return this.undo_button.tooltip_text; }
@@ -51,9 +47,9 @@ public class MainToolbar : Gtk.Box {
[GtkChild]
public Gtk.MenuButton move_conversation_button;
[GtkChild]
- private Gtk.Button archive_button;
+ private Gtk.Button trash_button;
[GtkChild]
- private Gtk.Button trash_delete_button;
+ private Gtk.Button delete_button;
[GtkChild]
private Gtk.ToggleButton find_button;
@@ -61,24 +57,6 @@ public class MainToolbar : Gtk.Box {
[GtkChild]
private Gtk.Button undo_button;
- // Load these at construction time
- private Gtk.Image trash_image = new Gtk.Image.from_icon_name("user-trash-symbolic", Gtk.IconSize.MENU);
- private Gtk.Image delete_image = new Gtk.Image.from_icon_name("edit-delete-symbolic", Gtk.IconSize.MENU);
-
- // Tooltips
- private const string DELETE_CONVERSATION_TOOLTIP_SINGLE = _("Delete conversation (Shift+Delete)");
- private const string DELETE_CONVERSATION_TOOLTIP_MULTIPLE = _("Delete conversations (Shift+Delete)");
- private const string TRASH_CONVERSATION_TOOLTIP_SINGLE = _("Move conversation to Trash (Delete,
Backspace)");
- private const string TRASH_CONVERSATION_TOOLTIP_MULTIPLE = _("Move conversations to Trash (Delete,
Backspace)");
- private const string ARCHIVE_CONVERSATION_TOOLTIP_SINGLE = _("Archive conversation (A)");
- private const string ARCHIVE_CONVERSATION_TOOLTIP_MULTIPLE = _("Archive conversations (A)");
- private const string MARK_CONVERSATION_MENU_TOOLTIP_SINGLE = _("Mark conversation");
- private const string MARK_CONVERSATION_MENU_TOOLTIP_MULTIPLE = _("Mark conversations");
- private const string LABEL_CONVERSATION_TOOLTIP_SINGLE = _("Add label to conversation");
- private const string LABEL_CONVERSATION_TOOLTIP_MULTIPLE = _("Add label to conversations");
- private const string MOVE_CONVERSATION_TOOLTIP_SINGLE = _("Move conversation");
- private const string MOVE_CONVERSATION_TOOLTIP_MULTIPLE = _("Move conversations");
-
public MainToolbar(Configuration config) {
// Instead of putting a separator between the two headerbars, as other applications do,
// we put a separator at the right end of the left headerbar. This greatly improves
@@ -113,8 +91,6 @@ public class MainToolbar : Gtk.Box {
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
// Setup conversation header elements
- this.notify["selected-conversations"].connect(() => update_conversation_buttons());
- this.notify["show-trash-button"].connect(() => update_conversation_buttons());
this.mark_conversation_button.popover = new Gtk.Popover.from_model(null, mark_menu);
this.copy_conversation_button.popover = copy_folder_menu;
this.move_conversation_button.popover = move_folder_menu;
@@ -146,6 +122,11 @@ public class MainToolbar : Gtk.Box {
conversation_header.show();
}
+ internal void update_trash_buttons(bool show_trash) {
+ this.trash_button.set_visible(show_trash);
+ this.delete_button.set_visible(!show_trash);
+ }
+
private void set_window_buttons() {
string[] buttons = Gtk.Settings.get_default().gtk_decoration_layout.split(":");
if (buttons.length != 2) {
@@ -158,41 +139,4 @@ public class MainToolbar : Gtk.Box {
conversation_header.decoration_layout = ":" + buttons[1];
}
- // Updates tooltip text depending on number of conversations selected.
- private void update_conversation_buttons() {
- this.mark_conversation_button.tooltip_text = ngettext(
- MARK_CONVERSATION_MENU_TOOLTIP_SINGLE,
- MARK_CONVERSATION_MENU_TOOLTIP_MULTIPLE,
- this.selected_conversations
- );
- this.copy_conversation_button.tooltip_text = ngettext(
- LABEL_CONVERSATION_TOOLTIP_SINGLE,
- LABEL_CONVERSATION_TOOLTIP_MULTIPLE,
- this.selected_conversations
- );
- this.move_conversation_button.tooltip_text = ngettext(
- MOVE_CONVERSATION_TOOLTIP_SINGLE,
- MOVE_CONVERSATION_TOOLTIP_MULTIPLE,
- this.selected_conversations
- );
- this.archive_button.tooltip_text = ngettext(
- ARCHIVE_CONVERSATION_TOOLTIP_SINGLE,
- ARCHIVE_CONVERSATION_TOOLTIP_MULTIPLE,
- this.selected_conversations
- );
-
- if (this.show_trash_button) {
- this.trash_delete_button.action_name = "win."+GearyController.ACTION_TRASH_CONVERSATION;
- this.trash_delete_button.image = trash_image;
- this.trash_delete_button.tooltip_text = ngettext(TRASH_CONVERSATION_TOOLTIP_SINGLE,
- TRASH_CONVERSATION_TOOLTIP_MULTIPLE,
- this.selected_conversations);
- } else {
- this.trash_delete_button.action_name = "win."+GearyController.ACTION_DELETE_CONVERSATION;
- this.trash_delete_button.image = delete_image;
- this.trash_delete_button.tooltip_text = ngettext(DELETE_CONVERSATION_TOOLTIP_SINGLE,
- DELETE_CONVERSATION_TOOLTIP_MULTIPLE,
- this.selected_conversations);
- }
- }
}
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index f5978fe..3e81caf 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -1,6 +1,6 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
- * Copyright 2016 Michael Gratton <mike vee net>
+ * Copyright 2016-2017 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
@@ -32,7 +32,6 @@ public class MainWindow : Gtk.ApplicationWindow {
private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
private Geary.ProgressMonitor? folder_progress = null;
- private Gee.Set<Geary.App.Conversation> selected_conversations = new
Gee.HashSet<Geary.App.Conversation>();
private MonitoredSpinner spinner = new MonitoredSpinner();
@@ -87,19 +86,6 @@ public class MainWindow : Gtk.ApplicationWindow {
on_change_orientation();
}
- ~MainWindow() {
- this.conversation_list.conversation_selection_changed.disconnect(on_conversation_selection_changed);
- this.conversation_list.conversation_activated.disconnect(on_conversation_activated);
- this.conversation_list.load_more.disconnect(on_load_more);
- }
-
- /**
- * Returns a read-only set of currently selected conversations.
- */
- public Gee.Set<Geary.App.Conversation> get_selected_conversations() {
- return this.selected_conversations.read_only_view;
- }
-
public void show_infobar(MainWindowInfoBar info_bar) {
this.info_bar_container.add(info_bar);
this.info_bar_frame.show();
@@ -442,24 +428,20 @@ public class MainWindow : Gtk.ApplicationWindow {
return (SimpleAction) lookup_action(name);
}
- private void on_conversation_selection_changed(Gee.Set<Geary.App.Conversation> selection) {
- this.selected_conversations = selection;
+ private void on_conversation_selection_changed(Geary.App.Conversation? selection) {
+ Geary.App.Conversation? current = null;
+ ConversationListBox? listbox = this.conversation_viewer.current_list;
+ if (listbox != null) {
+ current = listbox.conversation;
+ }
SimpleAction find_action = get_action(
GearyController.ACTION_FIND_IN_CONVERSATION
);
- find_action.set_enabled(false);
- if (this.current_folder != null && !this.conversation_viewer.is_composer_visible) {
- switch(selection.size) {
- case 0:
- this.application.controller.enable_message_buttons(false);
- this.conversation_viewer.show_none_selected();
- break;
-
- case 1:
- // Cancel existing avatar loads before loading new
- // convo since that will start loading more avatars
+ if (selection != null) {
+ if (selection != current &&
+ !this.conversation_viewer.is_composer_visible) {
this.conversation_viewer.load_conversation.begin(
- Geary.Collection.get_first(selection),
+ selection,
this.current_folder,
this.application.config,
this.application.controller.avatar_session,
@@ -474,13 +456,11 @@ public class MainWindow : Gtk.ApplicationWindow {
}
}
);
- break;
-
- default:
- this.application.controller.enable_multiple_message_buttons();
- this.conversation_viewer.show_multiple_selected();
- break;
}
+ } else {
+ find_action.set_enabled(false);
+ this.application.controller.enable_message_buttons(false);
+ this.conversation_viewer.show_none_selected();
}
}
diff --git a/src/client/conversation-list/conversation-list-item.vala
b/src/client/conversation-list/conversation-list-item.vala
index 6504aa5..29dcb05 100644
--- a/src/client/conversation-list/conversation-list-item.vala
+++ b/src/client/conversation-list/conversation-list-item.vala
@@ -73,6 +73,10 @@ public class ConversationListItem : Gtk.Grid {
}
+ /** The conversation displayed by this item */
+ public Geary.App.Conversation conversation { get; private set; }
+
+
[GtkChild]
private Gtk.Button star_button;
@@ -94,7 +98,6 @@ public class ConversationListItem : Gtk.Grid {
[GtkChild]
private Gtk.Label count;
- private Geary.App.Conversation conversation;
private Gee.List<Geary.RFC822.MailboxAddress> account_addresses;
private bool use_to;
private PreviewLoader previews;
diff --git a/src/client/conversation-list/conversation-list-view.vala
b/src/client/conversation-list/conversation-list-view.vala
index 14b1bce..c636be1 100644
--- a/src/client/conversation-list/conversation-list-view.vala
+++ b/src/client/conversation-list/conversation-list-view.vala
@@ -247,11 +247,11 @@ public class ConversationListView : Gtk.TreeView {
// 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
(GearyApplication.instance.controller.main_window.get_selected_conversations().contains(conversation))
- to_mark = GearyApplication.instance.controller.main_window.get_selected_conversations();
- else
- to_mark = Geary.iterate<Geary.App.Conversation>(conversation).to_array_list();
+ Gee.Collection<Geary.App.Conversation> to_mark = new Gee.ArrayList<Geary.App.Conversation>();
+ // if
(GearyApplication.instance.controller.main_window.get_selected_conversations().contains(conversation))
+ // to_mark = GearyApplication.instance.controller.main_window.get_selected_conversations();
+ // else
+ // to_mark = Geary.iterate<Geary.App.Conversation>(conversation).to_array_list();
if (read_clicked) {
// Read/unread.
diff --git a/src/client/conversation-list/conversation-list.vala
b/src/client/conversation-list/conversation-list.vala
index e55af23..c52ed56 100644
--- a/src/client/conversation-list/conversation-list.vala
+++ b/src/client/conversation-list/conversation-list.vala
@@ -1,6 +1,6 @@
/*
- * Copyright 2017 Michael Gratton <mike vee net>
* Copyright 2016 Software Freedom Conservancy Inc.
+ * Copyright 2017 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
@@ -18,8 +18,16 @@ public class ConversationList : Gtk.ListBox {
/** Underlying model for this list */
public ConversationListModel? model { get; private set; default=null; }
- private Configuration config;
+ /**
+ * The conversation highlighted as selected, if any.
+ *
+ * This is distinct to the conversations chosen via selection
+ * mode, which are checked and might not be highlighted.
+ */
+ public Geary.App.Conversation? selected { get; private set; default = null; }
+
+ private Configuration config;
private Gee.Set<Geary.App.Conversation>? visible_conversations = null;
private Geary.Scheduler.Scheduled? update_visible_scheduled = null;
private bool enable_load_more = true;
@@ -28,7 +36,7 @@ public class ConversationList : Gtk.ListBox {
/** Fired when a user changes the list's selection. */
- public signal void conversation_selection_changed(Gee.Set<Geary.App.Conversation> selection);
+ public signal void conversation_selection_changed(Geary.App.Conversation? selection);
/** Fired when a user activates a row in the list. */
public signal void conversation_activated(Geary.App.Conversation activated);
@@ -51,7 +59,9 @@ public class ConversationList : Gtk.ListBox {
uint activated = row.get_index();
this.conversation_activated(this.model.get_conversation(activated));
});
- this.selected_rows_changed.connect(on_selection_changed);
+ this.selected_rows_changed.connect(() => {
+ selection_changed();
+ });
this.show.connect(on_show);
}
@@ -69,6 +79,8 @@ public class ConversationList : Gtk.ListBox {
this.model = new ConversationListModel(monitor, loader);
this.model.items_changed.connect(on_model_items_changed);
+ // Clear these since they will belong to the old model
+ this.selected = null;
Gee.List<Geary.RFC822.MailboxAddress> account_addresses =
displayed.account.information.get_all_mailboxes();
bool use_to = displayed.special_folder_type.is_outgoing();
base.bind_model(this.model, (convo) => {
@@ -82,21 +94,17 @@ public class ConversationList : Gtk.ListBox {
}
public void select_conversation(Geary.App.Conversation target) {
- // XXX Implement me
- }
-
- public void select_conversations(Gee.Set<Geary.App.Conversation> targets) {
- // XXX Implement me
- }
-
- public Gee.Set<Geary.App.Conversation> get_selected_conversations() {
- Gee.HashSet<Geary.App.Conversation> selection =
- new Gee.HashSet<Geary.App.Conversation>();
- foreach (Gtk.ListBoxRow row in get_selected_rows()) {
- uint selected = row.get_index();
- selection.add(this.model.get_conversation(selected));
+ for (int i = 0; i < this.model.get_n_items(); i++) {
+ Gtk.ListBoxRow? row = get_row_at_index(i);
+ if (row != null) {
+ ConversationListItem item =
+ (ConversationListItem) row.get_child();
+ if (item.conversation == target) {
+ select_row(row);
+ break;
+ }
+ }
}
- return selection;
}
internal Gee.Set<Geary.App.Conversation> get_visible_conversations() {
@@ -105,11 +113,19 @@ public class ConversationList : Gtk.ListBox {
return visible;
}
- internal void set_changing_selection(bool changing) {
- if (changing) {
- this.selected_rows_changed.disconnect(on_selection_changed);
- } else {
- this.selected_rows_changed.connect(on_selection_changed);
+ private void selection_changed() {
+ Geary.App.Conversation? selected = null;
+ Gtk.ListBoxRow? row = get_selected_row();
+ if (row != null) {
+ selected = ((ConversationListItem) row.get_child()).conversation;
+ }
+
+ debug("Selection changed to: %s",
+ selected != null ? selected.to_string() : null
+ );
+ if (this.selected != selected) {
+ this.selected = selected;
+ this.conversation_selection_changed(selected);
}
}
@@ -136,10 +152,6 @@ public class ConversationList : Gtk.ListBox {
get_adjustment().value_changed.connect(on_adjustment_value_changed);
}
- private void on_selection_changed() {
- this.conversation_selection_changed(get_selected_conversations());
- }
-
private void on_adjustment_value_changed() {
Gtk.Adjustment? adjustment = get_adjustment();
if (this.enable_load_more && adjustment != null) {
diff --git a/src/client/conversation-viewer/conversation-viewer.vala
b/src/client/conversation-viewer/conversation-viewer.vala
index e0a4215..8964785 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -1,6 +1,6 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
- * Copyright 2016 Michael Gratton <mike vee net>
+ * Copyright 2016-2017 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
@@ -34,8 +34,6 @@ public class ConversationViewer : Gtk.Stack {
[GtkChild]
private Gtk.Grid conversation_page;
[GtkChild]
- private Gtk.Grid multiple_conversations_page;
- [GtkChild]
private Gtk.Grid empty_folder_page;
[GtkChild]
private Gtk.Grid empty_search_page;
@@ -75,13 +73,6 @@ public class ConversationViewer : Gtk.Stack {
);
this.no_conversations_page.add(no_conversations);
- EmptyPlaceholder multi_conversations = new EmptyPlaceholder();
- multi_conversations.title = _("Multiple conversations selected");
- multi_conversations.subtitle = _(
- "Choosing an action will apply to all selected conversations"
- );
- this.multiple_conversations_page.add(multi_conversations);
-
EmptyPlaceholder empty_folder = new EmptyPlaceholder();
empty_folder.title = _("No conversations found");
empty_folder.subtitle = _(
@@ -113,14 +104,14 @@ public class ConversationViewer : Gtk.Stack {
// GearyController or somewhere more appropriate
ConversationList conversation_list =
((MainWindow) GearyApplication.instance.controller.main_window).conversation_list;
- Gee.Set<Geary.App.Conversation>? prev_selection = conversation_list.get_selected_conversations();
+ Geary.App.Conversation prev_selection = conversation_list.selected;
conversation_list.unselect_all();
box.vanished.connect((box) => {
set_visible_child(this.conversation_page);
- if (prev_selection.is_empty) {
- conversation_list.conversation_selection_changed(prev_selection);
+ if (prev_selection == null) {
+ conversation_list.conversation_selection_changed(null);
} else {
- conversation_list.select_conversations(prev_selection);
+ conversation_list.select_conversation(prev_selection);
}
});
this.composer_page.add(box);
@@ -159,13 +150,6 @@ public class ConversationViewer : Gtk.Stack {
}
/**
- * Shows the UI when multiple conversations have been selected
- */
- public void show_multiple_selected() {
- set_visible_child(this.multiple_conversations_page);
- }
-
- /**
* Shows the empty folder UI.
*/
public void show_empty_folder() {
diff --git a/src/engine/app/app-conversation-monitor.vala b/src/engine/app/app-conversation-monitor.vala
index f607317..907fdc6 100644
--- a/src/engine/app/app-conversation-monitor.vala
+++ b/src/engine/app/app-conversation-monitor.vala
@@ -212,6 +212,10 @@ public class Geary.App.ConversationMonitor : BaseObject {
return conversations.conversations;
}
+ public bool has_conversation(Conversation target) {
+ return conversations.contains(target);
+ }
+
public Geary.App.Conversation? get_conversation_for_email(Geary.EmailIdentifier email_id) {
return conversations.get_by_email_identifier(email_id);
}
diff --git a/ui/conversation-viewer.ui b/ui/conversation-viewer.ui
index b67be0e..d260514 100644
--- a/ui/conversation-viewer.ui
+++ b/ui/conversation-viewer.ui
@@ -129,20 +129,6 @@
</packing>
</child>
<child>
- <object class="GtkGrid" id="multiple_conversations_page">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="name">multiple_conversations_page</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
<object class="GtkGrid" id="empty_folder_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
diff --git a/ui/main-toolbar.ui b/ui/main-toolbar.ui
index 500b189..544c31c 100644
--- a/ui/main-toolbar.ui
+++ b/ui/main-toolbar.ui
@@ -182,6 +182,7 @@
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Mark conversation</property>
<property name="action_name">win.mark-conversation-menu</property>
<property name="always_show_image">True</property>
<child>
@@ -203,6 +204,7 @@
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Add label to conversation</property>
<property name="always_show_image">True</property>
<child>
<object class="GtkImage" id="copy_message_image">
@@ -223,6 +225,7 @@
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Move conversation</property>
<property name="always_show_image">True</property>
<child>
<object class="GtkImage" id="move_message_image">
@@ -252,7 +255,7 @@
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
- <property name="tooltip_text" translatable="yes">Toggle find bar</property>
+ <property name="tooltip_text" translatable="yes">Find in conversation</property>
<property name="always_show_image">True</property>
<child>
<object class="GtkImage" id="find_image">
@@ -297,6 +300,7 @@
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Archive conversation (A)</property>
<property name="action_name">win.archive-conv</property>
<property name="image">archive_image</property>
<property name="use_underline">True</property>
@@ -309,15 +313,17 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="trash_delete_button">
- <property name="visible">True</property>
+ <object class="GtkButton" id="trash_button">
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
+ <property name="no_show_all">True</property>
+ <property name="tooltip_text" translatable="yes">Move conversation to Trash (Delete,
Backspace)</property>
<property name="action_name">win.trash-conv</property>
<property name="always_show_image">True</property>
<child>
- <object class="GtkImage" id="trash_delete_image">
+ <object class="GtkImage">
+ <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">user-trash-symbolic</property>
</object>
@@ -329,6 +335,29 @@
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkButton" id="delete_button">
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="no_show_all">True</property>
+ <property name="tooltip_text" translatable="yes">Delete conversation
(Shift+Delete)</property>
+ <property name="action_name">win.trash-conv</property>
+ <property name="always_show_image">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-delete-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
<style>
<class name="raised"/>
<class name="linked"/>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]