[geary/gnumdk/rework-move-button] components: Rework Folder Popover




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]