diff --git a/src/client/application/application-folder-context.vala b/src/client/application/application-folder-context.vala index 4ed47cf5..1a16385b 100644 --- a/src/client/application/application-folder-context.vala +++ b/src/client/application/application-folder-context.vala @@ -46,6 +46,17 @@ public class Application.FolderContext : Geary.BaseObject, return this.folder.path.compare_to(other.folder.path); } + private string get_default_icon_name() { + var service_provider = this.folder.account.information.service_provider; + + switch (service_provider) { + case Geary.ServiceProvider.GMAIL: + return "tag-symbolic"; + default: + return "folder-symbolic"; + } + } + private void update() { this.display_name = Util.I18n.to_folder_display_name(this.folder); @@ -88,7 +99,7 @@ public class Application.FolderContext : Geary.BaseObject, break; default: - this.icon_name = "tag-symbolic"; + this.icon_name = get_default_icon_name(); break; } diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala index 681bfe3a..9afffb45 100644 --- a/src/client/application/application-main-window.vala +++ b/src/client/application/application-main-window.vala @@ -1179,11 +1179,23 @@ public class Application.MainWindow : /** Adds a folder to the window. */ private void add_folders(Gee.Collection to_add) { + // Build map between path and display name for + // special directories + var map = new Gee.HashMap(); + foreach (var context in to_add) { + var folder = context.folder; + if (folder.used_as == Geary.Folder.SpecialUse.NONE) + continue; + map.set( + folder.path.to_string().substring(1), + context.display_name + ); + } foreach (var context in to_add) { this.folder_list.add_folder(context); if (context.folder.account == this.selected_account) { foreach (var menu in this.folder_popovers) { - menu.add_folder(context.folder); + menu.add_folder(context, map); } } context.folder.use_changed.connect(on_use_changed); @@ -1588,9 +1600,28 @@ public class Application.MainWindow : this.search_bar.set_account(account); if (account != null) { + var service_provider = account.information.service_provider; + this.conversation_list_actions.service_provider = service_provider; + this.main_toolbar.full_actions.service_provider = service_provider; + this.main_toolbar.compact_actions.service_provider = service_provider; + foreach (var menu in this.folder_popovers) { - foreach (var folder in account.list_folders()) { - menu.add_folder(folder); + var folders = account.list_folders(); + // Build map between path and display name for + // special directories + var map = new Gee.HashMap(); + foreach (var folder in folders) { + var context = new Application.FolderContext(folder); + if (folder.used_as == Geary.Folder.SpecialUse.NONE) + continue; + map.set( + folder.path.to_string().substring(1), + context.display_name + ); + } + foreach (var folder in folders) { + var context = new Application.FolderContext(folder); + menu.add_folder(context, map); } } } diff --git a/src/client/components/components-conversation-actions.vala b/src/client/components/components-conversation-actions.vala index 0876dd27..e5931614 100644 --- a/src/client/components/components-conversation-actions.vala +++ b/src/client/components/components-conversation-actions.vala @@ -24,6 +24,8 @@ public class Components.ConversationActions : Gtk.Box { public int selected_conversations { get; set; } + public Geary.ServiceProvider service_provider { get; set; } + [GtkChild] private unowned Gtk.Box response_buttons { get; } [GtkChild] private unowned Gtk.Box mark_copy_move_buttons { get; } @@ -56,6 +58,7 @@ public class Components.ConversationActions : Gtk.Box { ); this.notify["selected-conversations"].connect(() => update_conversation_buttons()); + this.notify["service-provider"].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; @@ -110,11 +113,7 @@ public class Components.ConversationActions : Gtk.Box { "Mark conversations", this.selected_conversations ); - this.copy_message_button.tooltip_text = ngettext( - "Add label to conversation", - "Add label to conversations", - this.selected_conversations - ); + this.move_message_button.tooltip_text = ngettext( "Move conversation", "Move conversations", @@ -126,6 +125,33 @@ public class Components.ConversationActions : Gtk.Box { this.selected_conversations ); + var copy_icon_name = "edit-copy-symbolic"; + var move_icon_name = "edit-cut-symbolic"; + switch (this.service_provider) { + case Geary.ServiceProvider.GMAIL: + this.copy_message_button.tooltip_text = ngettext( + "Add label to conversation", + "Add label to conversations", + this.selected_conversations + ); + copy_icon_name = "tag-symbolic"; + move_icon_name = "folder-symbolic"; + break; + default: + this.copy_message_button.tooltip_text = ngettext( + "Copy conversation", + "Copy conversations", + this.selected_conversations + ); + break; + } + this.copy_message_button.set_image( + new Gtk.Image.from_icon_name(copy_icon_name, Gtk.IconSize.BUTTON) + ); + this.move_message_button.set_image( + new Gtk.Image.from_icon_name(move_icon_name, Gtk.IconSize.BUTTON) + ); + if (this.show_trash_button) { this.trash_delete_button.action_name = Action.Window.prefix( Application.MainWindow.ACTION_TRASH_CONVERSATION diff --git a/src/client/components/folder-popover-row.vala b/src/client/components/folder-popover-row.vala new file mode 100644 index 00000000..98033bcd --- /dev/null +++ b/src/client/components/folder-popover-row.vala @@ -0,0 +1,32 @@ +/* Copyright 2022 Cédric Bellegarde + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +[GtkTemplate (ui = "/org/gnome/Geary/folder-popover-row.ui")] +public class FolderPopoverRow : Gtk.ListBoxRow { + + [GtkChild] private unowned Gtk.Image image; + [GtkChild] private unowned Gtk.Label label; + + public FolderPopoverRow(Application.FolderContext context, Gee.HashMap map) { + string[] as_array = context.folder.path.as_array(); + + if (map.has_key(as_array[0])) { + as_array[0] = map[as_array[0]]; + } + + var i = 0; + foreach (string name in as_array) { + as_array[i] = GLib.Markup.escape_text(name); + i += 1; + } + + this.set_data("folder", context.folder); + this.image.icon_name = context.icon_name; + + this.label.set_markup(string.joinv(" / ", as_array)); + this.label.query_tooltip.connect(Util.Gtk.query_tooltip_label); + } +} diff --git a/src/client/components/folder-popover.vala b/src/client/components/folder-popover.vala index faba1df2..90dfd81f 100644 --- a/src/client/components/folder-popover.vala +++ b/src/client/components/folder-popover.vala @@ -28,7 +28,8 @@ public class FolderPopover : Gtk.Popover { return get_row_with_folder(folder) != null; } - public void add_folder(Geary.Folder folder) { + public void add_folder(Application.FolderContext context, Gee.HashMap map) { + Geary.Folder folder = context.folder; // don't allow multiples and don't allow folders that can't be opened (that means they // support almost no operations and have no content) if (has_folder(folder) || folder.properties.is_openable.is_impossible()) @@ -39,14 +40,36 @@ public class FolderPopover : Gtk.Popover { if (folder.properties.is_local_only || folder.properties.is_virtual) return; - list_box.add(build_row(folder)); + // Moving mails to Drafts folder not supported + switch (folder.account.information.service_provider) { + case Geary.ServiceProvider.GMAIL: + if (folder.used_as == Geary.Folder.SpecialUse.DRAFTS) + return; + break; + default: + break; + } + + // Ignore special directories already having a dedicated button + switch (folder.used_as) { + case Geary.Folder.SpecialUse.ARCHIVE: + case Geary.Folder.SpecialUse.TRASH: + case Geary.Folder.SpecialUse.JUNK: + return; + default: + break; + } + + var row = new FolderPopoverRow(context, map); + row.show(); + list_box.add(row); list_box.invalidate_sort(); } - public void enable_disable_folder(Geary.Folder folder, bool sensitive) { + public void enable_disable_folder(Geary.Folder folder, bool visible) { Gtk.ListBoxRow row = get_row_with_folder(folder); if (row != null) - row.sensitive = sensitive; + row.visible = visible; } public void remove_folder(Geary.Folder folder) { @@ -68,20 +91,6 @@ public class FolderPopover : Gtk.Popover { list_box.foreach((row) => list_box.remove(row)); } - private Gtk.ListBoxRow build_row(Geary.Folder folder) { - Gtk.ListBoxRow row = new Gtk.ListBoxRow(); - row.get_style_context().add_class("geary-folder-popover-list-row"); - row.set_data("folder", folder); - - Gtk.Label label = new Gtk.Label(folder.path.to_string()); - label.set_halign(Gtk.Align.START); - row.add(label); - - row.show_all(); - - return row; - } - [GtkCallback] private void on_row_activated(Gtk.ListBoxRow? row) { if (row != null) { @@ -118,8 +127,8 @@ public class FolderPopover : Gtk.Popover { } private bool row_filter(Gtk.ListBoxRow row) { - Gtk.Label label = row.get_child() as Gtk.Label; - if (label.label.down().contains(search_entry.text.down())) { + Geary.Folder folder = row.get_data("folder"); + if (folder.path.to_string().down().contains(search_entry.text.down())) { filtered_folder_count++; return true; } @@ -129,6 +138,13 @@ public class FolderPopover : Gtk.Popover { private int row_sort(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) { Geary.Folder folder1 = row1.get_data("folder"); Geary.Folder folder2 = row2.get_data("folder"); - return folder1.path.compare_to(folder2.path); + if (folder1.used_as != Geary.Folder.SpecialUse.NONE && + folder2.used_as == Geary.Folder.SpecialUse.NONE) + return -1; + else if (folder1.used_as == Geary.Folder.SpecialUse.NONE && + folder2.used_as != Geary.Folder.SpecialUse.NONE) + return 1; + else + return folder1.path.compare_to(folder2.path); } } diff --git a/src/client/folder-list/folder-list-account-branch.vala b/src/client/folder-list/folder-list-account-branch.vala index 4e67a194..ffb576a9 100644 --- a/src/client/folder-list/folder-list-account-branch.vala +++ b/src/client/folder-list/folder-list-account-branch.vala @@ -43,7 +43,18 @@ public class FolderList.AccountBranch : Sidebar.Branch { // Translators: The name of the folder group containing // folders created by people (as opposed to special-use // folders) - user_folder_group = new SpecialGrouping(2, _("Labels"), "tag-symbolic"); + string name, icon_name; + switch (account.information.service_provider) { + case Geary.ServiceProvider.GMAIL: + name = _("Labels"); + icon_name = "tag-symbolic"; + break; + default: + name = _("Folders"); + icon_name = "folder-symbolic"; + break; + } + user_folder_group = new SpecialGrouping(2, name, icon_name); folder_entries = new Gee.HashMap(); this.display_name = account.information.display_name; diff --git a/src/client/meson.build b/src/client/meson.build index 18ad1ecb..628201a1 100644 --- a/src/client/meson.build +++ b/src/client/meson.build @@ -66,6 +66,7 @@ client_vala_sources = files( 'components/components-web-view.vala', 'components/count-badge.vala', 'components/folder-popover.vala', + 'components/folder-popover-row.vala', 'components/icon-factory.vala', 'components/monitored-progress-bar.vala', 'components/monitored-spinner.vala', diff --git a/src/client/util/util-gtk.vala b/src/client/util/util-gtk.vala index 09d59e81..63e27e13 100644 --- a/src/client/util/util-gtk.vala +++ b/src/client/util/util-gtk.vala @@ -227,4 +227,13 @@ namespace Util.Gtk { }; } + /* Connect this to Gtk.Widget.query_tooltip signal, will only show tooltip if label ellipsized */ + public bool query_tooltip_label(global::Gtk.Widget widget, int x, int y, bool keyboard, global::Gtk.Tooltip tooltip) { + global::Gtk.Label label = widget as global::Gtk.Label; + if (label.get_layout().is_ellipsized()) { + tooltip.set_markup(label.label); + return true; + } + return false; + } } diff --git a/ui/folder-popover-row.ui b/ui/folder-popover-row.ui new file mode 100644 index 00000000..b7a9309e --- /dev/null +++ b/ui/folder-popover-row.ui @@ -0,0 +1,46 @@ + + + + + + diff --git a/ui/folder-popover.ui b/ui/folder-popover.ui index 473d3dc3..881c8a5f 100644 --- a/ui/folder-popover.ui +++ b/ui/folder-popover.ui @@ -29,14 +29,15 @@ - 200 + 300 320 True - in + none never True + start True