[geary] Fix for the context menu. Bug 770356.



commit 56c10aca945178dafae9cae9e6f7a209008db6e3
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Sep 21 03:37:21 2016 +0200

    Fix for the context menu. Bug 770356.
    
    Signed-off-by: Niels De Graef <nielsdegraef gmail com>

 src/client/components/stock.vala         |    1 -
 src/client/composer/composer-widget.vala |   61 +++++++++++++--------------
 src/client/util/util-gtk.vala            |   68 ++++++++++++++++++++++++++++++
 ui/composer-menus.ui                     |   22 ++++++----
 4 files changed, 111 insertions(+), 41 deletions(-)
---
diff --git a/src/client/components/stock.vala b/src/client/components/stock.vala
index 4eb5d86..cddc62e 100644
--- a/src/client/components/stock.vala
+++ b/src/client/components/stock.vala
@@ -29,7 +29,6 @@ public const string _PRINT_MENU = _("_Print...");
 public const string _QUIT = _("_Quit");
 public const string _REMOVE = _("_Remove");
 public const string _SAVE = _("_Save");
-public const string SELECT__ALL = _("Select _All");
 public const string _KEEP = _("_Keep");
 
 }
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index 58b0dc2..270e431 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -46,6 +46,7 @@ public class ComposerWidget : Gtk.EventBox {
     private const string ACTION_COPY_LINK = "copy-link";
     private const string ACTION_PASTE = "paste";
     private const string ACTION_PASTE_WITH_FORMATTING = "paste-with-formatting";
+    private const string ACTION_SELECT_ALL = "select-all";
     private const string ACTION_BOLD = "bold";
     private const string ACTION_ITALIC = "italic";
     private const string ACTION_UNDERLINE = "underline";
@@ -71,7 +72,8 @@ public class ComposerWidget : Gtk.EventBox {
 
     private const string[] html_actions = {
         ACTION_BOLD, ACTION_ITALIC, ACTION_UNDERLINE, ACTION_STRIKETHROUGH, ACTION_FONT_SIZE,
-        ACTION_FONT_FAMILY, ACTION_REMOVE_FORMAT, ACTION_COLOR, ACTION_JUSTIFY, ACTION_INSERT_LINK
+        ACTION_FONT_FAMILY, ACTION_REMOVE_FORMAT, ACTION_COLOR, ACTION_JUSTIFY, ACTION_INSERT_LINK,
+        ACTION_COPY_LINK, ACTION_PASTE_WITH_FORMATTING
     };
 
     private const ActionEntry[] action_entries = {
@@ -83,6 +85,7 @@ public class ComposerWidget : Gtk.EventBox {
         {ACTION_COPY_LINK,                on_copy_link                                  },
         {ACTION_PASTE,                    on_paste                                      },
         {ACTION_PASTE_WITH_FORMATTING,    on_paste_with_formatting                      },
+        {ACTION_SELECT_ALL,               on_select_all                                 },
         {ACTION_BOLD,                     on_action,                null,      "false"  },
         {ACTION_ITALIC,                   on_action,                null,      "false"  },
         {ACTION_UNDERLINE,                on_action,                null,      "false"  },
@@ -1741,7 +1744,7 @@ public class ComposerWidget : Gtk.EventBox {
             this.editor.paste_clipboard();
     }
 
-    private void on_select_all() {
+    private void on_select_all(SimpleAction action, Variant? param) {
         this.editor.select_all();
     }
 
@@ -2011,42 +2014,36 @@ public class ComposerWidget : Gtk.EventBox {
     private bool on_context_menu(Gtk.Widget default_menu, WebKit.HitTestResult hit_test_result,
         bool keyboard_triggered) {
         Gtk.Menu context_menu = (Gtk.Menu) default_menu;
-        Gtk.MenuItem? ignore_spelling = null, learn_spelling = null;
-        bool suggestions = false;
 
-        GLib.List<weak Gtk.Widget> children = context_menu.get_children();
-        foreach (weak Gtk.Widget child in children) {
+        // Keep the spelling menu items
+        foreach (weak Gtk.Widget child in context_menu.get_children()) {
             Gtk.MenuItem item = (Gtk.MenuItem) child;
-            if (item.is_sensitive()) {
-                WebKit.ContextMenuAction action = WebKit.context_menu_item_get_action(item);
-                if (action == WebKit.ContextMenuAction.SPELLING_GUESS) {
-                    suggestions = true;
-                    continue;
-                }
+            WebKit.ContextMenuAction action = WebKit.context_menu_item_get_action(item);
 
-                if (action == WebKit.ContextMenuAction.IGNORE_SPELLING)
-                    ignore_spelling = item;
-                else if (action == WebKit.ContextMenuAction.LEARN_SPELLING)
-                    learn_spelling = item;
-            }
+            const WebKit.ContextMenuAction[] spelling_actions = {
+                WebKit.ContextMenuAction.SPELLING_GUESS,
+                WebKit.ContextMenuAction.IGNORE_SPELLING,
+                WebKit.ContextMenuAction.LEARN_SPELLING
+            };
+
+            if (!(action in spelling_actions))
+                context_menu.remove(item);
         }
 
+        // Add our own Menu (but don't add formatting actions if they are disabled).
         context_menu.insert_action_group("cme", this.actions);
-        context_menu.bind_model(this.context_menu_model, "cme", true);
-
-        if (suggestions)
-            context_menu.append(new Gtk.SeparatorMenuItem());
-        if (ignore_spelling != null)
-            context_menu.append(ignore_spelling);
-        if (learn_spelling != null)
-            context_menu.append(learn_spelling);
-        if (ignore_spelling != null || learn_spelling != null)
-            context_menu.append(new Gtk.SeparatorMenuItem());
-
-        // Select all.
-        Gtk.MenuItem select_all_item = new Gtk.MenuItem.with_mnemonic(Stock.SELECT__ALL);
-        select_all_item.activate.connect(on_select_all);
-        context_menu.append(select_all_item);
+        GtkUtil.add_g_menu_to_gtk_menu(context_menu, context_menu_model, (label, detailed_action_name) => {
+            string action_name;
+            Variant? target;
+            try {
+                Action.parse_detailed_name(detailed_action_name, out action_name, out target);
+                if ("." in action_name) // Remove possible prefixes
+                    action_name = action_name.split(".")[1];
+            } catch (GLib.Error e) {
+                debug("Couldn't parse action \"%s\" in context menu".printf(detailed_action_name));
+            }
+            return !(action_name in html_actions) || (this.actions.get_action_enabled(action_name));
+        });
 
         context_menu.show_all();
         update_actions();
diff --git a/src/client/util/util-gtk.vala b/src/client/util/util-gtk.vala
index 16ca6aa..dd83a8f 100644
--- a/src/client/util/util-gtk.vala
+++ b/src/client/util/util-gtk.vala
@@ -153,4 +153,72 @@ bool close_button_at_end() {
     return at_end;
 }
 
+/**
+ * Allows iterating over a GMenu, without having to handle MenuItems
+ * @param menu - The menu to iterate over
+ * @param foreach_func - The function which will be called on the attributes of menu's children
+ */
+void menu_foreach(Menu menu, MenuForeachFunc foreach_func) {
+    for (int i = 0; i < menu.get_n_items(); i++) {
+        // Get the attributes we're interested in
+        Variant? label = menu.get_item_attribute_value(i, Menu.ATTRIBUTE_LABEL, VariantType.STRING);
+        Variant? action_name = menu.get_item_attribute_value(i, Menu.ATTRIBUTE_ACTION, VariantType.STRING);
+        Variant? action_target = menu.get_item_attribute_value(i, Menu.ATTRIBUTE_TARGET, VariantType.STRING);
+        string detailed_action_name = null;
+        if (action_name != null)
+            detailed_action_name = Action.print_detailed_name(action_name.get_string(), action_target);
+
+        // Check if the child is a section
+        Menu? section = (Menu) menu.get_item_link(i, Menu.LINK_SECTION);
+
+        // Callback
+        foreach_func((label != null) ? label.get_string() : null
+                     , detailed_action_name
+                     , section);
+    }
+}
+
+/*
+ * Used for menu_foreach()
+ * @param label - The label if one was set
+ * @param detailed_action_name - The action if it was set
+ * @param section - If the item represents a section, this will return that section (or null otherwise)
+ */
+delegate void MenuForeachFunc(string? label, string? detailed_action_name, Menu? section);
+
+/**
+ * Adds the entries of a GLib.Menu to a Gtk.Menu
+ * @param gtk_menu - The Gtk.Menu to add entries to.
+ * @param g_menu - The Menu whose entries should be added
+ * @param filter - If this function returns false for a menu item, it will not be added to the menu
+ */
+void add_g_menu_to_gtk_menu(Gtk.Menu gtk_menu, Menu g_menu, MenuItemFilterFunc filter) {
+    menu_foreach(g_menu, (label, action_name, section) => {
+        List<weak Gtk.Widget> children = gtk_menu.get_children();
+        weak Gtk.Widget? last_child = (children.length() > 0) ? children.last().data : null;
+
+        if (section != null) {
+            // Section. Set separators (without getting double separators)
+            if ((children.length() > 0) && ((last_child as Gtk.SeparatorMenuItem) == null))
+                gtk_menu.add(new Gtk.SeparatorMenuItem());
+
+            add_g_menu_to_gtk_menu(gtk_menu, section, filter);
+
+            if ((children.length() > 0) && ((last_child as Gtk.SeparatorMenuItem) == null))
+                gtk_menu.add(new Gtk.SeparatorMenuItem());
+        } else {
+            // Regular menu-item
+            if (filter(label, action_name) && label != null) {
+                Gtk.MenuItem item = new Gtk.MenuItem.with_mnemonic(label);
+                if (action_name != null)
+                    item.set_detailed_action_name(action_name);
+                gtk_menu.add(item);
+            }
+        }
+    });
+}
+
+// Used for add_g_menu_to_gtk_menu()
+delegate bool MenuItemFilterFunc(string? label, string? detailed_action_name);
+
 }
diff --git a/ui/composer-menus.ui b/ui/composer-menus.ui
index cf939e6..56f0a00 100644
--- a/ui/composer-menus.ui
+++ b/ui/composer-menus.ui
@@ -75,33 +75,39 @@
     <section>
       <item>
         <attribute name="label" translatable="yes">_Undo</attribute>
-        <attribute name="action">undo</attribute>
+        <attribute name="action">cme.undo</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">_Redo</attribute>
-        <attribute name="action">redo</attribute>
+        <attribute name="action">cme.redo</attribute>
       </item>
     </section>
     <section>
       <item>
         <attribute name="label" translatable="yes">Cu_t</attribute>
-        <attribute name="action">cut</attribute>
+        <attribute name="action">cme.cut</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">_Copy</attribute>
-        <attribute name="action">copy</attribute>
+        <attribute name="action">cme.copy</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">Copy _Link</attribute>
-        <attribute name="action">copy-link</attribute>
+        <attribute name="action">cme.copy-link</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">_Paste</attribute>
-        <attribute name="action">paste</attribute>
+        <attribute name="action">cme.paste</attribute>
       </item>
       <item>
-        <attribute name="label" translatable="yes">Paste _With Formatting</attribute>
-        <attribute name="action">paste-with-formatting</attribute>
+        <attribute name="label" translatable="yes" context="Clipboard paste with rich text">Paste _With 
Formatting</attribute>
+        <attribute name="action">cme.paste-with-formatting</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">Select _All</attribute>
+        <attribute name="action">cme.select-all</attribute>
       </item>
     </section>
   </menu>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]