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.
This commit is contained in:
Michael Gratton 2019-11-21 02:36:09 +11:00
parent fb1439264a
commit 259ebe50fd
8 changed files with 166 additions and 18 deletions

View file

@ -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>

View file

@ -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();

View file

@ -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,

View file

@ -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);
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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;
}