Merge branch 'wip/279-convo-list-context-labels' into 'mainline'

Conversation list context menu fixes

Closes #279

See merge request GNOME/geary!272
This commit is contained in:
Michael Gratton 2019-08-04 03:11:20 +00:00
commit dd1b816958
5 changed files with 76 additions and 31 deletions

View file

@ -279,7 +279,6 @@ public class Application.Controller : Geary.BaseObject {
// Create the main window (must be done after creating actions.)
main_window = new MainWindow(this.application);
main_window.retry_service_problem.connect(on_retry_service_problem);
main_window.on_shift_key.connect(on_shift_key);
main_window.notify["has-toplevel-focus"].connect(on_has_toplevel_focus);
setup_actions();
@ -1049,9 +1048,12 @@ public class Application.Controller : Geary.BaseObject {
// 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.selected_conversations.size;
main_window.main_toolbar.show_trash_button = current_folder_supports_trash() ||
!(current_folder is Geary.FolderSupport.Remove);
this.main_window.main_toolbar.selected_conversations =
this.selected_conversations.size;
this.main_window.main_toolbar.update_trash_button(
!this.main_window.is_shift_down &&
current_folder_supports_trash()
);
}
private void on_folder_selected(Geary.Folder? folder) {
@ -1424,15 +1426,6 @@ public class Application.Controller : Geary.BaseObject {
return sender.cancel_exit();
}
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);
}
}
// this signal does not necessarily indicate that the application previously didn't have
// focus and now it does
private void on_has_toplevel_focus() {

View file

@ -24,8 +24,7 @@ public class MainToolbar : Gtk.Box {
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; }
// Folder header elements
[GtkChild]
@ -52,6 +51,8 @@ public class MainToolbar : Gtk.Box {
[GtkChild]
private Gtk.ToggleButton find_button;
private bool show_trash_button = true;
// 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);
@ -84,7 +85,6 @@ public class MainToolbar : Gtk.Box {
// Setup conversation header elements
this.notify["selected-conversations"].connect(() => update_conversation_buttons());
this.notify["show-trash-button"].connect(() => update_conversation_buttons());
this.mark_message_button.popover = new Gtk.Popover.from_model(null, mark_menu);
this.copy_message_button.popover = copy_folder_menu;
this.move_message_button.popover = move_folder_menu;
@ -116,6 +116,11 @@ public class MainToolbar : Gtk.Box {
conversation_header.show();
}
public void update_trash_button(bool show_trash) {
this.show_trash_button = show_trash;
update_conversation_buttons();
}
private void set_window_buttons() {
string[] buttons = Gtk.Settings.get_default().gtk_decoration_layout.split(":");
this.show_close_button_left = this.show_close_button;
@ -146,8 +151,8 @@ public class MainToolbar : Gtk.Box {
this.selected_conversations
);
this.archive_button.tooltip_text = ngettext(
"Archive conversation (A)",
"Archive conversations (A)",
"Archive conversation",
"Archive conversations",
this.selected_conversations
);
@ -155,16 +160,16 @@ public class MainToolbar : Gtk.Box {
this.trash_delete_button.action_name = "win."+Application.Controller.ACTION_TRASH_CONVERSATION;
this.trash_delete_button.image = trash_image;
this.trash_delete_button.tooltip_text = ngettext(
"Move conversation to Trash (Delete, Backspace)",
"Move conversations to Trash (Delete, Backspace)",
"Move conversation to Trash",
"Move conversations to Trash",
this.selected_conversations
);
} else {
this.trash_delete_button.action_name = "win."+Application.Controller.ACTION_DELETE_CONVERSATION;
this.trash_delete_button.image = delete_image;
this.trash_delete_button.tooltip_text = ngettext(
"Delete conversation (Shift+Delete)",
"Delete conversations (Shift+Delete)",
"Delete conversation",
"Delete conversations",
this.selected_conversations
);
}

View file

@ -28,6 +28,9 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
get; private set; default = null;
}
/** Specifies if the Shift key is currently being held. */
public bool is_shift_down { get; private set; default = false; }
private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
// Used to save/load the window state between sessions.
@ -727,7 +730,12 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
Gtk.Widget? focus = get_focus();
if (focus == null ||
(!(focus is Gtk.Entry) && !(focus is ComposerWebView))) {
on_shift_key(event.type == Gdk.EventType.KEY_PRESS);
this.is_shift_down = (event.type == Gdk.EventType.KEY_PRESS);
this.main_toolbar.update_trash_button(
!this.is_shift_down &&
current_folder_supports_trash()
);
on_shift_key(this.is_shift_down);
}
}
}
@ -736,6 +744,16 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
return (SimpleAction) lookup_action(name);
}
private bool current_folder_supports_trash() {
Geary.Folder? current = this.current_folder;
return (
current != null &&
current.special_folder_type != TRASH &&
!current_folder.properties.is_local_only &&
(current_folder as Geary.FolderSupport.Move) != null
);
}
private void on_scan_completed(Geary.App.ConversationMonitor monitor) {
// Done scanning. Check if we have enough messages to fill
// the conversation list; if not, trigger a load_more();

View file

@ -318,8 +318,28 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
if (event.button == 3 && event.type == Gdk.EventType.BUTTON_PRESS) {
Geary.App.Conversation conversation = get_model().get_conversation_at_path(path);
Menu context_menu_model = new Menu();
context_menu_model.append(_("Delete conversation"), "win."+Application.Controller.ACTION_DELETE_CONVERSATION);
GLib.Menu context_menu_model = new GLib.Menu();
if (!this.main_window.is_shift_down) {
context_menu_model.append(
/// Translators: Context menu item
ngettext(
"Move conversation to _Trash",
"Move conversations to _Trash",
this.selected.size
),
"win." + Application.Controller.ACTION_ARCHIVE_CONVERSATION
);
} else {
context_menu_model.append(
/// Translators: Context menu item
ngettext(
"_Delete conversation",
"_Delete conversations",
this.selected.size
),
"win." + Application.Controller.ACTION_DELETE_CONVERSATION
);
}
if (conversation.is_unread())
context_menu_model.append(_("Mark as _Read"), "win."+Application.Controller.ACTION_MARK_AS_READ);
@ -338,9 +358,18 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
actions_section.append(_("_Forward"), "win."+Application.Controller.ACTION_FORWARD_MESSAGE);
context_menu_model.append_section(null, actions_section);
Gtk.Menu context_menu = new Gtk.Menu.from_model(context_menu_model);
context_menu.insert_action_group("win", this.main_window);
context_menu.popup_at_pointer(event);
// Use a popover rather than a regular context menu since
// the latter grabs the event queue, so the MainWindow
// will not receive events if the user releases Shift,
// making the trash/delete header bar state wrong.
Gtk.Popover context_menu = new Gtk.Popover.from_model(
this, context_menu_model
);
Gdk.Rectangle dest = Gdk.Rectangle();
dest.x = (int) event.x;
dest.y = (int) event.y;
context_menu.set_pointing_to(dest);
context_menu.popup();
// When the conversation under the mouse is selected, stop event propagation
return get_selection().path_is_selected(path);

View file

@ -46,15 +46,15 @@
<section id="email_menu_trash">
<item>
<!-- Translators: Menu item to move a single, specific message
to the trash -->
<attribute name="label" translatable="yes">_Trash</attribute>
to the trash folder -->
<attribute name="label" translatable="yes">Move message to _Trash</attribute>
<attribute name="action">eml.trash_msg</attribute>
</item>
</section>
<section id="email_menu_delete">
<item>
<!-- Translators: Menu item to delete a single, specific message -->
<attribute name="label" translatable="yes">_Delete…</attribute>
<attribute name="label" translatable="yes">_Delete message…</attribute>
<attribute name="action">eml.delete_msg</attribute>
</item>
</section>