[geary/wip/fix-main-window-shortcuts: 2/4] Re-implement single key shortcuts as a preference



commit 259ebe50fdde9b6298e0d3a05a55b3b007686059
Author: Michael Gratton <mike vee net>
Date:   Thu Nov 21 02:36:09 2019 +1100

    Re-implement single key shortcuts as a preference
    
    Add new `single-key-shortcuts` GSetting, Application.Configuration
    property and add UI for it in the Preferences window. When enabled,
    load in new `single-key-shortcuts.css` file that has the appropriate
    bindings. Update bindings to match Google's current set, and update
    shortcut help to match.

 desktop/org.gnome.Geary.gschema.xml                |  8 ++++
 src/client/application/application-client.vala     | 47 +++++++++++++++++-----
 .../application/application-configuration.vala     |  7 +++-
 .../components/components-preferences-window.vala  | 43 ++++++++++++++++++--
 ui/application-main-window.ui                      |  3 ++
 ui/gtk/help-overlay.ui                             | 36 +++++++++++++++--
 ui/org.gnome.Geary.gresource.xml                   |  1 +
 ui/single-key-shortcuts.css                        | 39 ++++++++++++++++++
 8 files changed, 166 insertions(+), 18 deletions(-)
---
diff --git a/desktop/org.gnome.Geary.gschema.xml b/desktop/org.gnome.Geary.gschema.xml
index 9f2467b5..f0068798 100644
--- a/desktop/org.gnome.Geary.gschema.xml
+++ b/desktop/org.gnome.Geary.gschema.xml
@@ -63,6 +63,14 @@
         <description>True if we should display a short preview of each message.</description>
     </key>
 
+    <key name="single-key-shortcuts" type="b">
+        <default>false</default>
+        <summary>Use single key shortcuts</summary>
+        <description>Enables shortcuts for email actions that do not
+        require pressing &lt;Ctrl> to emulate those used by
+        Gmail.</description>
+    </key>
+
     <key name="spell-check-languages" type="mas">
         <default>nothing</default>
         <summary>Languages that shall be used in the spell checker</summary>
diff --git a/src/client/application/application-client.vala b/src/client/application/application-client.vala
index 88d99c5b..2eef6a7f 100644
--- a/src/client/application/application-client.vala
+++ b/src/client/application/application-client.vala
@@ -243,6 +243,7 @@ public class Application.Client : Gtk.Application {
     private File exec_dir;
     private string binary;
     private bool start_hidden = false;
+    private Gtk.CssProvider single_key_shortcuts = new Gtk.CssProvider();
     private GLib.Cancellable controller_cancellable = new GLib.Cancellable();
     private Components.Inspector? inspector = null;
     private Geary.Nonblocking.Mutex controller_mutex = new Geary.Nonblocking.Mutex();
@@ -427,15 +428,14 @@ public class Application.Client : Gtk.Application {
             provider,
             Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
         );
-        provider.parsing_error.connect(on_css_parse_error);
-        try {
-            var file = GLib.File.new_for_uri(
-                "resource:///org/gnome/Geary/geary.css"
-            );
-            provider.load_from_file(file);
-        } catch (GLib.Error error) {
-            warning("Could not load CSS: %s", error.message);
-        }
+        load_css(provider,
+                 "resource:///org/gnome/Geary/geary.css");
+        load_css(this.single_key_shortcuts,
+                 "resource:///org/gnome/Geary/single-key-shortcuts.css");
+        update_single_key_shortcuts();
+        this.config.notify[Configuration.SINGLE_KEY_SHORTCUTS].connect(
+            on_single_key_shortcuts_toggled
+        );
 
         MainWindow.add_accelerators(this);
         Composer.Widget.add_accelerators(this);
@@ -980,6 +980,21 @@ public class Application.Client : Gtk.Application {
         set_accels_for_action("app." + action, accelerators);
     }
 
+    private void update_single_key_shortcuts() {
+        if (this.config.single_key_shortcuts) {
+            Gtk.StyleContext.add_provider_for_screen(
+                Gdk.Display.get_default().get_default_screen(),
+                this.single_key_shortcuts,
+                Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
+            );
+        } else {
+            Gtk.StyleContext.remove_provider_for_screen(
+                Gdk.Display.get_default().get_default_screen(),
+                this.single_key_shortcuts
+            );
+        }
+    }
+
     private Geary.Folder? get_folder_from_action_target(GLib.Variant target) {
         Geary.Folder? folder = null;
         string id = (string) target.get_child_value(0);
@@ -996,6 +1011,16 @@ public class Application.Client : Gtk.Application {
         return folder;
     }
 
+    private void load_css(Gtk.CssProvider provider, string resource_uri) {
+        provider.parsing_error.connect(on_css_parse_error);
+        try {
+            var file = GLib.File.new_for_uri(resource_uri);
+            provider.load_from_file(file);
+        } catch (GLib.Error error) {
+            warning("Could not load CSS: %s", error.message);
+        }
+    }
+
     private void on_activate_about() {
         this.show_about.begin();
     }
@@ -1146,6 +1171,10 @@ public class Application.Client : Gtk.Application {
         }
     }
 
+    private void on_single_key_shortcuts_toggled() {
+        update_single_key_shortcuts();
+    }
+
     private void on_css_parse_error(Gtk.CssSection section, GLib.Error error) {
         uint start = section.get_start_line();
         uint end = section.get_end_line();
diff --git a/src/client/application/application-configuration.vala 
b/src/client/application/application-configuration.vala
index 051b4d7d..c8e95f83 100644
--- a/src/client/application/application-configuration.vala
+++ b/src/client/application/application-configuration.vala
@@ -9,7 +9,7 @@
 /**
  * Provides properties to access application GSettings values.
  */
-public class Application.Configuration {
+public class Application.Configuration : Geary.BaseObject {
 
 
     public const string ASK_OPEN_ATTACHMENT_KEY = "ask-open-attachment";
@@ -24,6 +24,7 @@ public class Application.Configuration {
     public const string FOLDER_LIST_PANE_POSITION_VERTICAL_KEY = "folder-list-pane-position-vertical";
     public const string MESSAGES_PANE_POSITION_KEY = "messages-pane-position";
     public const string SEARCH_STRATEGY_KEY = "search-strategy";
+    public const string SINGLE_KEY_SHORTCUTS = "single-key-shortcuts";
     public const string SPELL_CHECK_LANGUAGES = "spell-check-languages";
     public const string SPELL_CHECK_VISIBLE_LANGUAGES = "spell-check-visible-languages";
     public const string STARTUP_NOTIFICATIONS_KEY = "startup-notifications";
@@ -116,6 +117,8 @@ public class Application.Configuration {
         get { return settings.get_boolean(DISPLAY_PREVIEW_KEY); }
     }
 
+    public bool single_key_shortcuts { get; set; default = false; }
+
     /**
      * The set of enabled spell checker languages.
      *
@@ -216,6 +219,8 @@ public class Application.Configuration {
         gnome_interface = new Settings("org.gnome.desktop.interface");
 
         Migrate.old_app_config(settings);
+
+        this.bind(SINGLE_KEY_SHORTCUTS, this, SINGLE_KEY_SHORTCUTS);
     }
 
     public void bind(string key, Object object, string property,
diff --git a/src/client/components/components-preferences-window.vala 
b/src/client/components/components-preferences-window.vala
index 198395ad..9b9772fd 100644
--- a/src/client/components/components-preferences-window.vala
+++ b/src/client/components/components-preferences-window.vala
@@ -65,6 +65,19 @@ public class Components.PreferencesWindow : Hdy.PreferencesWindow {
         three_pane_view_row.activatable_widget = three_pane_view;
         three_pane_view_row.add_action(three_pane_view);
 
+        var single_key_shortucts = new Gtk.Switch();
+        single_key_shortucts.valign = CENTER;
+
+        var single_key_shortucts_row = new Hdy.ActionRow();
+        /// Translators: Preferences label
+        single_key_shortucts_row.title = _("Use _single key email shortcuts");
+        single_key_shortucts_row.tooltip_text = _(
+            "Enable keyboard shortcuts for email actions that do not require pressing <Ctrl>"
+        );
+        single_key_shortucts_row.use_underline = true;
+        single_key_shortucts_row.activatable_widget = single_key_shortucts;
+        single_key_shortucts_row.add_action(single_key_shortucts);
+
         var startup_notifications = new Gtk.Switch();
         startup_notifications.valign = CENTER;
 
@@ -87,6 +100,7 @@ public class Components.PreferencesWindow : Hdy.PreferencesWindow {
         group.add(autoselect_row);
         group.add(display_preview_row);
         group.add(three_pane_view_row);
+        group.add(single_key_shortucts_row);
         group.add(startup_notifications_row);
 
         var page = new Hdy.PreferencesPage();
@@ -101,10 +115,31 @@ public class Components.PreferencesWindow : Hdy.PreferencesWindow {
         insert_action_group(Action.Window.GROUP_NAME, window_actions);
 
         Application.Configuration config = this.application.config;
-        config.bind(Application.Configuration.AUTOSELECT_KEY, autoselect, "state");
-        config.bind(Application.Configuration.DISPLAY_PREVIEW_KEY, display_preview, "state");
-        config.bind(Application.Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY, three_pane_view, "state");
-        config.bind(Application.Configuration.STARTUP_NOTIFICATIONS_KEY, startup_notifications, "state");
+        config.bind(
+            Application.Configuration.AUTOSELECT_KEY,
+            autoselect,
+            "state"
+        );
+        config.bind(
+            Application.Configuration.DISPLAY_PREVIEW_KEY,
+            display_preview,
+            "state"
+        );
+        config.bind(
+            Application.Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY,
+            three_pane_view,
+            "state"
+        );
+        config.bind(
+            Application.Configuration.SINGLE_KEY_SHORTCUTS,
+            single_key_shortucts,
+            "state"
+        );
+        config.bind(
+            Application.Configuration.STARTUP_NOTIFICATIONS_KEY,
+            startup_notifications,
+            "state"
+        );
 
         this.delete_event.connect(on_delete);
     }
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
index c2802888..2166b836 100644
--- a/ui/application-main-window.ui
+++ b/ui/application-main-window.ui
@@ -450,5 +450,8 @@ Please check your login name and try again.</property>
         </child>
       </object>
     </child>
+    <style>
+      <class name="geary-main-window"/>
+    </style>
   </template>
 </interface>
diff --git a/ui/gtk/help-overlay.ui b/ui/gtk/help-overlay.ui
index 4fe38dd8..08c29751 100644
--- a/ui/gtk/help-overlay.ui
+++ b/ui/gtk/help-overlay.ui
@@ -280,7 +280,7 @@
                             <object class="GtkShortcutsShortcut">
                                 <property name="visible">True</property>
                                 <property name="title" translatable="yes" context="shortcut window">Reply to 
all</property>
-                                <property name="accelerator">&lt;Shift&gt;R</property>
+                                <property name="accelerator">A</property>
                             </object>
                         </child>
                         <child>
@@ -301,21 +301,21 @@
                             <object class="GtkShortcutsShortcut">
                                 <property name="visible">True</property>
                                 <property name="title" translatable="yes" context="shortcut 
window">Mark/un-mark starred</property>
-                                <property name="accelerator">S D</property>
+                                <property name="accelerator">S</property>
                             </object>
                         </child>
                         <child>
                             <object class="GtkShortcutsShortcut">
                                 <property name="visible">True</property>
                                 <property name="title" translatable="yes" context="shortcut window">Archive 
conversation</property>
-                                <property name="accelerator">A Y</property>
+                                <property name="accelerator">E</property>
                             </object>
                         </child>
                         <child>
                             <object class="GtkShortcutsShortcut">
                                 <property name="visible">True</property>
                                 <property name="title" translatable="yes" context="shortcut window">Move 
conversation</property>
-                                <property name="accelerator">M</property>
+                                <property name="accelerator">V</property>
                             </object>
                         </child>
                         <child>
@@ -332,6 +332,34 @@
                                 <property name="accelerator">exclam</property>
                             </object>
                         </child>
+                        <child>
+                            <object class="GtkShortcutsShortcut">
+                                <property name="visible">True</property>
+                                <property name="title" translatable="yes" context="shortcut window">Delete 
conversation</property>
+                                <property name="accelerator">numbersign</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkShortcutsShortcut">
+                                <property name="visible">True</property>
+                                <property name="title" translatable="yes" context="shortcut window">Find in 
current conversation</property>
+                                <property name="accelerator">slash</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkShortcutsShortcut">
+                                <property name="visible">True</property>
+                                <property name="title" translatable="yes" context="shortcut window">Select 
the conversation down</property>
+                                <property name="accelerator">J</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkShortcutsShortcut">
+                                <property name="visible">True</property>
+                                <property name="title" translatable="yes" context="shortcut window">Select 
the conversation up</property>
+                                <property name="accelerator">K</property>
+                            </object>
+                        </child>
                       </object>
                 </child>
             </object>
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
index 0f1f8881..8ad731f0 100644
--- a/ui/org.gnome.Geary.gresource.xml
+++ b/ui/org.gnome.Geary.gresource.xml
@@ -45,5 +45,6 @@
     <file compressed="true">signature-web-view.js</file>
     <file compressed="true" preprocess="xml-stripblanks">upgrade_dialog.glade</file>
     <file compressed="true">geary.css</file>
+    <file compressed="true">single-key-shortcuts.css</file>
   </gresource>
 </gresources>
diff --git a/ui/single-key-shortcuts.css b/ui/single-key-shortcuts.css
new file mode 100644
index 00000000..7073f754
--- /dev/null
+++ b/ui/single-key-shortcuts.css
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 Michael Gratton <mike vee net>
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+/*
+ * These match Gmail's as of time of commit. Taken from:
+ * https://support.google.com/mail/answer/6594
+ */
+@binding-set SingleKeyShortcuts {
+  bind "r" { "reply-conversation-sender" () };
+  bind "a" { "reply-conversation-all" () };
+  bind "f" { "forward-conversation" () };
+
+  bind "<Shift>i" { "mark-conversations-read" (1) };
+  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" () };
+   /* ! */
+  bind "exclam" { "junk-conversations" () };
+   /* # */
+  bind "numbersign" { "delete-conversations" () };
+
+  /* / */
+  bind "slash" { "find" () };
+
+  bind "k" { "navigate" (step-up) };
+  bind "j" { "navigate" (step-down) };
+}
+
+window.geary-main-window {
+  -gtk-key-bindings: SingleKeyShortcuts;
+}


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