[geary/gnumdk/rework-move-button] components: Rework Folder Popover
- From: Cédric Bellegarde <cbellegarde src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/gnumdk/rework-move-button] components: Rework Folder Popover
- Date: Tue, 19 Jul 2022 13:18:36 +0000 (UTC)
commit 54aee2508d0ead1b520aa2e88d46a6fcbc498d2a
Author: Cédric Bellegarde <cedric bellegarde adishatz org>
Date: Mon Jul 18 13:54:39 2022 +0200
components: Rework Folder Popover
- Tag button was just a copy mail to folder button, it is confusing so just remove it. We need a pure tag
feature like in others email clients.
- Enhanced 'move mail to folder' feature:
- Do not show folders with a dedicated button: Trash, Archive, ...
- Do not show folders as an IMAP path but as a human readable path (>INBOX>Folder vs Boîte de
reception/Folder)
.../application/application-folder-context.vala | 2 +-
.../application/application-main-window.vala | 67 ++++++++++------------
.../components-conversation-actions.vala | 21 +------
src/client/components/folder-popover-row.vala | 35 +++++++++++
src/client/components/folder-popover.vala | 47 ++++++++-------
.../folder-list/folder-list-account-branch.vala | 2 +-
src/client/meson.build | 1 +
src/client/util/util-gtk.vala | 9 +++
ui/components-conversation-actions.ui | 23 +-------
ui/folder-popover-row.ui | 46 +++++++++++++++
ui/folder-popover.ui | 4 +-
ui/geary.css | 7 +--
ui/org.gnome.Geary.gresource.xml | 1 +
ui/single-key-shortcuts.css | 1 -
14 files changed, 158 insertions(+), 108 deletions(-)
---
diff --git a/src/client/application/application-folder-context.vala
b/src/client/application/application-folder-context.vala
index 4ed47cf56..65b67eeac 100644
--- a/src/client/application/application-folder-context.vala
+++ b/src/client/application/application-folder-context.vala
@@ -88,7 +88,7 @@ public class Application.FolderContext : Geary.BaseObject,
break;
default:
- this.icon_name = "tag-symbolic";
+ this.icon_name = "folder-symbolic";
break;
}
diff --git a/src/client/application/application-main-window.vala
b/src/client/application/application-main-window.vala
index 8e969d108..6076c02d6 100644
--- a/src/client/application/application-main-window.vala
+++ b/src/client/application/application-main-window.vala
@@ -26,7 +26,6 @@ public class Application.MainWindow :
public const string ACTION_REPLY_CONVERSATION = "reply-conversation";
public const string ACTION_SEARCH = "search";
public const string ACTION_SELECT_INBOX = "select-inbox";
- public const string ACTION_SHOW_COPY_MENU = "show-copy-menu";
public const string ACTION_SHOW_MARK_MENU = "show-mark-menu";
public const string ACTION_SHOW_MOVE_MENU = "show-move-menu";
public const string ACTION_TOGGLE_JUNK = "toggle-conversation-junk";
@@ -56,7 +55,6 @@ public class Application.MainWindow :
{ ACTION_ARCHIVE_CONVERSATION, on_archive_conversation },
{ ACTION_TRASH_CONVERSATION, on_trash_conversation },
{ ACTION_DELETE_CONVERSATION, on_delete_conversation },
- { ACTION_SHOW_COPY_MENU, on_show_copy_menu },
{ ACTION_SHOW_MOVE_MENU, on_show_move_menu },
{ ACTION_CONVERSATION_UP, on_conversation_up },
{ ACTION_CONVERSATION_DOWN, on_conversation_down },
@@ -476,12 +474,6 @@ public class Application.MainWindow :
);
}
- /** Keybinding signal for showing the copy/label menu. */
- [Signal (action=true)]
- public virtual signal void show_copy_menu() {
- activate_action(get_window_action(ACTION_SHOW_COPY_MENU));
- }
-
/** Keybinding signal for showing the move menu. */
[Signal (action=true)]
public virtual signal void show_move_menu() {
@@ -1177,11 +1169,23 @@ public class Application.MainWindow :
/** Adds a folder to the window. */
private void add_folders(Gee.Collection<FolderContext> to_add) {
+ // Build map between path and display name for
+ // special directories
+ var map = new Gee.HashMap<string,string>();
+ 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);
@@ -1406,10 +1410,6 @@ public class Application.MainWindow :
var move = actions.move_folder_menu;
this.folder_popovers += move;
move.folder_selected.connect(on_move_conversation);
-
- var copy = actions.copy_folder_menu;
- this.folder_popovers += copy;
- copy.folder_selected.connect(on_copy_conversation);
}
}
@@ -1588,8 +1588,22 @@ public class Application.MainWindow :
if (account != null) {
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<string,string>();
+ 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);
}
}
}
@@ -1834,14 +1848,6 @@ public class Application.MainWindow :
actions.set_move_sensitive(move_enabled);
}
- bool copy_enabled = (
- sensitive && (selected_folder is Geary.FolderSupport.Copy)
- );
- get_window_action(ACTION_SHOW_COPY_MENU).set_enabled(move_enabled);
- foreach (var actions in this.folder_conversation_actions) {
- actions.set_copy_sensitive(copy_enabled);
- }
-
get_window_action(ACTION_ARCHIVE_CONVERSATION).set_enabled(
sensitive && (selected_folder is Geary.FolderSupport.Archive)
);
@@ -1919,10 +1925,6 @@ public class Application.MainWindow :
sensitive &&
(typeof(Geary.FolderSupport.Mark) in supported_operations)
);
- get_window_action(ACTION_SHOW_COPY_MENU).set_enabled(
- sensitive &&
- (supported_operations.contains(typeof(Geary.FolderSupport.Copy)))
- );
get_window_action(ACTION_SHOW_MOVE_MENU).set_enabled(
sensitive &&
(supported_operations.contains(typeof(Geary.FolderSupport.Move)))
@@ -2415,17 +2417,6 @@ public class Application.MainWindow :
overlay.show();
}
- private void on_show_copy_menu() {
- if (this.is_conversation_list_shown &&
- this.conversation_list_actions_revealer.child_revealed) {
- this.conversation_list_actions.show_copy_menu();
- } else if (this.is_conversation_viewer_shown) {
- this.main_toolbar.shown_actions.show_copy_menu();
- } else {
- error_bell();
- }
- }
-
private void on_show_move_menu() {
if (this.is_conversation_list_shown &&
this.conversation_list_actions_revealer.child_revealed) {
diff --git a/src/client/components/components-conversation-actions.vala
b/src/client/components/components-conversation-actions.vala
index f7df39fb9..1efefa7cd 100644
--- a/src/client/components/components-conversation-actions.vala
+++ b/src/client/components/components-conversation-actions.vala
@@ -18,17 +18,14 @@ public class Components.ConversationActions : Gtk.Box {
public bool pack_justified { get; construct; }
- public FolderPopover copy_folder_menu { get; private set; default = new FolderPopover(); }
-
public FolderPopover move_folder_menu { get; private set; default = new FolderPopover(); }
public int selected_conversations { get; set; }
[GtkChild] private unowned Gtk.Box response_buttons { get; }
- [GtkChild] private unowned Gtk.Box mark_copy_move_buttons { get; }
+ [GtkChild] private unowned Gtk.Box mark_move_buttons { get; }
[GtkChild] private unowned Gtk.MenuButton mark_message_button { get; }
- [GtkChild] private unowned Gtk.MenuButton copy_message_button { get; }
[GtkChild] private unowned Gtk.MenuButton move_message_button { get; }
[GtkChild] private unowned Gtk.Box archive_trash_delete_buttons { get; }
@@ -57,11 +54,10 @@ public class Components.ConversationActions : Gtk.Box {
this.notify["selected-conversations"].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;
this.response_buttons.set_visible(this.show_response_actions);
- this.mark_copy_move_buttons.set_visible(this.show_conversation_actions);
+ this.mark_move_buttons.set_visible(this.show_conversation_actions);
this.archive_trash_delete_buttons.set_visible(this.show_conversation_actions);
if (this.pack_justified) {
@@ -78,14 +74,6 @@ public class Components.ConversationActions : Gtk.Box {
this.move_message_button.clicked();
}
- public void set_copy_sensitive(bool is_sensitive) {
- this.copy_message_button.sensitive = is_sensitive;
- }
-
- public void show_copy_menu() {
- this.copy_message_button.clicked();
- }
-
public void update_trash_button(bool show_trash) {
this.show_trash_button = show_trash;
update_conversation_buttons();
@@ -98,11 +86,6 @@ 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",
diff --git a/src/client/components/folder-popover-row.vala b/src/client/components/folder-popover-row.vala
new file mode 100644
index 000000000..9fd5bc0a1
--- /dev/null
+++ b/src/client/components/folder-popover-row.vala
@@ -0,0 +1,35 @@
+/* Copyright 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ *
+ * 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<string,string> map) {
+ Geary.Folder folder = context.folder;
+ string path = folder.path.to_string().substring(1);
+ string[] split_path = path.split(">");
+
+ if (split_path.length > 0) {
+ if (map.has_key(split_path[0])) {
+ split_path[0] = map[split_path[0]];
+ }
+ path = string.joinv(">", split_path);
+ }
+
+ this.set_data("folder", folder);
+ this.image.icon_name = context.icon_name;
+ this.label.set_markup(
+ path.replace(
+ ">",
+ "<span alpha='30%'> / </span>"
+ )
+ );
+ 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 faba1df2b..9904ec9db 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<string,string> 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,25 @@ public class FolderPopover : Gtk.Popover {
if (folder.properties.is_local_only || folder.properties.is_virtual)
return;
- list_box.add(build_row(folder));
+ // Ignore special directories already having a dedicated button:
+ switch (folder.used_as) {
+ case Geary.Folder.SpecialUse.ARCHIVE:
+ case Geary.Folder.SpecialUse.TRASH:
+ 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 +80,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 +116,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<Geary.Folder>("folder");
+ if (folder.path.to_string().down().contains(search_entry.text.down())) {
filtered_folder_count++;
return true;
}
@@ -129,6 +127,13 @@ public class FolderPopover : Gtk.Popover {
private int row_sort(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
Geary.Folder folder1 = row1.get_data<Geary.Folder>("folder");
Geary.Folder folder2 = row2.get_data<Geary.Folder>("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 4e67a1948..1ef26d138 100644
--- a/src/client/folder-list/folder-list-account-branch.vala
+++ b/src/client/folder-list/folder-list-account-branch.vala
@@ -43,7 +43,7 @@ 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");
+ user_folder_group = new SpecialGrouping(2, _("Folders"), "folder-symbolic");
folder_entries = new Gee.HashMap<Geary.FolderPath, FolderEntry>();
this.display_name = account.information.display_name;
diff --git a/src/client/meson.build b/src/client/meson.build
index 715358320..982590c54 100644
--- a/src/client/meson.build
+++ b/src/client/meson.build
@@ -65,6 +65,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 09d59e816..63e27e136 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/components-conversation-actions.ui b/ui/components-conversation-actions.ui
index 5471d2847..8a980ea1a 100644
--- a/ui/components-conversation-actions.ui
+++ b/ui/components-conversation-actions.ui
@@ -79,7 +79,7 @@
</object>
</child>
<child>
- <object class="GtkBox" id="mark_copy_move_buttons">
+ <object class="GtkBox" id="mark_move_buttons">
<property name="visible">True</property>
<child>
<object class="GtkMenuButton" id="mark_message_button">
@@ -100,25 +100,6 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkMenuButton" id="copy_message_button">
- <property name="visible">True</property>
- <property name="focus_on_click">False</property>
- <property name="receives_default">False</property>
- <property name="always_show_image">True</property>
- <child>
- <object class="GtkImage" id="copy_message_image">
- <property name="visible">True</property>
- <property name="icon_name">tag-symbolic</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
<child>
<object class="GtkMenuButton" id="move_message_button">
<property name="visible">True</property>
@@ -135,7 +116,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
<style>
diff --git a/ui/folder-popover-row.ui b/ui/folder-popover-row.ui
new file mode 100644
index 000000000..b7a9309e0
--- /dev/null
+++ b/ui/folder-popover-row.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.14"/>
+ <template class="FolderPopoverRow" parent="GtkListBoxRow">
+ <child>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="geary-folder-popover-list-row"/>
+ </style>
+ </template>
+</interface>
diff --git a/ui/folder-popover.ui b/ui/folder-popover.ui
index 473d3dc34..894924d8a 100644
--- a/ui/folder-popover.ui
+++ b/ui/folder-popover.ui
@@ -29,10 +29,10 @@
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled">
- <property name="min_content_width">200</property>
+ <property name="width-request">300</property>
<property name="min_content_height">320</property>
<property name="visible">True</property>
- <property name="shadow_type">in</property>
+ <property name="shadow_type">none</property>
<property name="hscrollbar_policy">never</property>
<child>
<object class="GtkListBox" id="list_box">
diff --git a/ui/geary.css b/ui/geary.css
index 84533f5ff..0f639308c 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -69,10 +69,9 @@ revealer components-conversation-actions {
/* FolderPopover */
row.geary-folder-popover-list-row {
- padding: 6px;
- border-color: @borders;
- border-style: groove;
- border-bottom-width: 1px;
+ padding: 5px;
+ margin: 3px;
+ border: 1px solid @borders;
}
row.geary-folder-popover-list-row > label {
color: @theme_text_color;
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
index 57b977a35..3af61ca76 100644
--- a/ui/org.gnome.Geary.gresource.xml
+++ b/ui/org.gnome.Geary.gresource.xml
@@ -40,6 +40,7 @@
<file compressed="true">conversation-web-view.js</file>
<file compressed="true" preprocess="xml-stripblanks">find_bar.glade</file>
<file compressed="true" preprocess="xml-stripblanks">folder-popover.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks">folder-popover-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
<file compressed="true" preprocess="xml-stripblanks">password-dialog.glade</file>
<file compressed="true" preprocess="xml-stripblanks">problem-details-dialog.ui</file>
diff --git a/ui/single-key-shortcuts.css b/ui/single-key-shortcuts.css
index 7073f7545..3a969c052 100644
--- a/ui/single-key-shortcuts.css
+++ b/ui/single-key-shortcuts.css
@@ -18,7 +18,6 @@
bind "<Shift>u" { "mark-conversations-read" (0) };
bind "s" { "mark-conversations-starred" (1) };
- bind "l" { "show-copy-menu" () };
bind "v" { "show-move-menu" () };
bind "e" { "archive-conversations" () };
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]