[GtkUI] Enable remapping of keyboard shortcuts

With key shortcuts set in the glade files it is not easy to change
the shortcuts on macOS.

Add AccelPaths to each MenuItem to allow adding or modifying accelerator
in codes. Uses the recommended format `<Deluge-MainWindow>/MenuName`

Update menubar code to use new functionality, taking advantage of
accelerator_parse to specify accelerators as strings instead of Gdk
flags.

A future idea would be to use `Gtk.AccelMap.load` to have shortcuts
loaded from user config.

Co-authored-by: Gregorio Litenstein <g.litenstein@gmail.com>
This commit is contained in:
Calum Lind 2021-12-08 18:28:46 +00:00
parent 4b6ac1f4c4
commit a64cdfaf78
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
3 changed files with 55 additions and 55 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkImage" id="about-image">
@ -7,7 +7,6 @@
<property name="can_focus">False</property>
<property name="icon_name">help-about-symbolic</property>
</object>
<object class="GtkAccelGroup" id="accelgroup1"/>
<object class="GtkImage" id="add-image">
<property name="visible">True</property>
<property name="can_focus">False</property>
@ -67,6 +66,7 @@
<property name="icon_name">zoom-fit-best-symbolic</property>
<property name="icon_size">1</property>
</object>
<object class="GtkAccelGroup" id="main_accelgroup"/>
<object class="GtkImage" id="new-image">
<property name="visible">True</property>
<property name="can_focus">False</property>
@ -93,9 +93,9 @@
<property name="can_focus">False</property>
<property name="title">Deluge</property>
<accel-groups>
<group name="accelgroup1"/>
<group name="main_accelgroup"/>
</accel-groups>
<child>
<child type="titlebar">
<placeholder/>
</child>
<child>
@ -114,8 +114,10 @@
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menuitem1_menu1">
<object class="GtkMenu" id="submenu_file">
<property name="can_focus">False</property>
<property name="accel_group">main_accelgroup</property>
<property name="accel_path">&lt;Deluge-MainWindow&gt;/File</property>
<child>
<object class="GtkImageMenuItem" id="menuitem_addtorrent">
<property name="label" translatable="yes">_Add Torrent</property>
@ -126,7 +128,6 @@
<property name="image">add-image</property>
<property name="use_stock">False</property>
<signal name="activate" handler="on_menuitem_addtorrent_activate" swapped="no"/>
<accelerator key="O" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
@ -138,7 +139,6 @@
<property name="image">new-image</property>
<property name="use_stock">False</property>
<signal name="activate" handler="on_menuitem_createtorrent_activate" swapped="no"/>
<accelerator key="N" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
@ -155,7 +155,6 @@
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
<signal name="activate" handler="on_menuitem_quitdaemon_activate" swapped="no"/>
<accelerator key="Q" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</object>
</child>
<child>
@ -172,9 +171,8 @@
<property name="use_underline">True</property>
<property name="image">quit_image</property>
<property name="use_stock">False</property>
<property name="accel_group">accelgroup1</property>
<property name="accel_group">main_accelgroup</property>
<signal name="activate" handler="on_menuitem_quit_activate" swapped="no"/>
<accelerator key="Q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
</object>
@ -188,9 +186,11 @@
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<object class="GtkMenu" id="submenu_edit">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="accel_group">main_accelgroup</property>
<property name="accel_path">&lt;Deluge-MainWindow&gt;/Edit</property>
<child>
<object class="GtkImageMenuItem" id="menuitem_preferences">
<property name="label" translatable="yes">_Preferences</property>
@ -199,9 +199,8 @@
<property name="use_underline">True</property>
<property name="image">prefs-image</property>
<property name="use_stock">False</property>
<property name="accel_group">accelgroup1</property>
<property name="accel_group">main_accelgroup</property>
<signal name="activate" handler="on_menuitem_preferences_activate" swapped="no"/>
<accelerator key="P" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
@ -213,7 +212,6 @@
<property name="image">connection-image</property>
<property name="use_stock">False</property>
<signal name="activate" handler="on_menuitem_connectionmanager_activate" swapped="no"/>
<accelerator key="M" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
</object>
@ -223,6 +221,7 @@
<child>
<object class="GtkMenuItem" id="menu_torrent">
<property name="can_focus">False</property>
<property name="accel_path">&lt;MainWindow&gt;/Torrent</property>
<property name="label" translatable="yes">_Torrent</property>
<property name="use_underline">True</property>
</object>
@ -234,9 +233,11 @@
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu2">
<object class="GtkMenu" id="submenu_view">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="accel_group">main_accelgroup</property>
<property name="accel_path">&lt;Deluge-MainWindow&gt;/View</property>
<child>
<object class="GtkCheckMenuItem" id="menuitem_toolbar">
<property name="visible">True</property>
@ -297,7 +298,6 @@
<property name="label" translatable="yes">_Find ...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_search_filter_toggle" swapped="no"/>
<accelerator key="f" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
@ -356,8 +356,10 @@
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menuitem2_menu1">
<object class="GtkMenu" id="submenu_help">
<property name="can_focus">False</property>
<property name="accel_group">main_accelgroup</property>
<property name="accel_path">&lt;Deluge-MainWindow&gt;/Help</property>
<child>
<object class="GtkImageMenuItem" id="menuitem_homepage">
<property name="label" translatable="yes">_Homepage</property>
@ -377,7 +379,6 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="on_menuitem_faq_activate" swapped="no"/>
<accelerator key="F1" signal="activate"/>
</object>
</child>
<child>
@ -405,7 +406,7 @@
<property name="use_underline">True</property>
<property name="image">about-image</property>
<property name="use_stock">False</property>
<property name="accel_group">accelgroup1</property>
<property name="accel_group">main_accelgroup</property>
<signal name="activate" handler="on_menuitem_about_activate" swapped="no"/>
</object>
</child>
@ -467,7 +468,6 @@ This will filter torrents for the current selection on the sidebar.</property>
<property name="label" translatable="yes">Filter</property>
<property name="icon_name">system-search-symbolic</property>
<signal name="clicked" handler="on_search_filter_toggle" swapped="no"/>
<accelerator key="f" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
</object>
<packing>
<property name="expand">False</property>

View File

@ -23,6 +23,17 @@ from .path_chooser import PathChooser
log = logging.getLogger(__name__)
default_main_window_accelmap = {
'<Deluge-MainWindow>/File/Add Torrent': '<Primary>o',
'<Deluge-MainWindow>/File/Create Torrent': '<Primary>n',
'<Deluge-MainWindow>/File/Quit & Shutdown Daemon': '<Primary><Shift>q',
'<Deluge-MainWindow>/File/Quit': '<Primary>q',
'<Deluge-MainWindow>/Edit/Preferences': '<Primary>p',
'<Deluge-MainWindow>/Edit/Connection Manager': '<Primary>m',
'<Deluge-MainWindow>/View/Find ...': '<Primary>f',
'<Deluge-MainWindow>/Help/FAQ': 'F1',
}
class MenuBar(component.Component):
def __init__(self):
@ -112,6 +123,11 @@ class MenuBar(component.Component):
# Attach the torrent_menu to the Torrent file menu
self.menu_torrent.set_submenu(self.torrentmenu)
# Set keyboard shortcuts
for accel_path, accelerator in default_main_window_accelmap.items():
accel_key, accel_mods = Gtk.accelerator_parse(accelerator)
Gtk.AccelMap.change_entry(accel_path, accel_key, accel_mods, True)
# Make sure the view menuitems are showing the correct active state
self.main_builder.get_object('menuitem_toolbar').set_active(
self.config['show_toolbar']

View File

@ -5,48 +5,36 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
from gi.repository.Gdk import ModifierType
from gi.repository.Gtk import SeparatorMenuItem, accel_groups_from_object
from gi.repository.Gtk.AccelFlags import VISIBLE
from gi.repository import Gtk
from deluge.configmanager import ConfigManager
def accel_swap(item, group, skey, smod, dkey, dmod):
# Accel map hack broken, see ticket #3078
# item.remove_accelerator(group, ord(skey), smod)
item.add_accelerator('activate', group, ord(dkey), dmod, VISIBLE)
def accel_meta(item, group, key):
accel_swap(item, group, key, ModifierType.CONTROL_MASK, key, ModifierType.META_MASK)
macos_main_window_accelmap = {
'<Deluge-MainWindow>/File/Add Torrent': '<Meta>o',
'<Deluge-MainWindow>/File/Create Torrent': '<Meta>n',
'<Deluge-MainWindow>/File/Quit & Shutdown Daemon': '<Meta><Shift>q',
'<Deluge-MainWindow>/File/Quit': '<Meta>q',
'<Deluge-MainWindow>/Edit/Preferences': '<Meta>comma',
'<Deluge-MainWindow>/Edit/Connection Manager': '<Meta>m',
'<Deluge-MainWindow>/View/Find ...': '<Meta>f',
'<Deluge-MainWindow>/Help/FAQ': '<Meta>question',
}
def menubar_osx(gtkui, osxapp):
# Change key shortcuts
for accel_path, accelerator in macos_main_window_accelmap.items():
accel_key, accel_mods = Gtk.accelerator_parse(accelerator)
Gtk.AccelMap.change_entry(accel_path, accel_key, accel_mods, True)
main_builder = gtkui.mainwindow.get_builder()
menubar = main_builder.get_object('menubar')
group = accel_groups_from_object(gtkui.mainwindow.window)[0]
config = ConfigManager('gtk3ui.conf')
# NOTE: accel maps doesn't work with glade file format
# because of libglade not setting MenuItem accel groups
# That's why we remove / set accelerators by hand... (dirty)
# Clean solution: migrate glades files to gtkbuilder format
file_menu = main_builder.get_object('menu_file').get_submenu()
file_items = file_menu.get_children()
accel_meta(file_items[0], group, 'o')
accel_meta(file_items[1], group, 'n')
quit_all_item = file_items[3]
accel_swap(
quit_all_item,
group,
'q',
ModifierType.SHIFT_MASK | ModifierType.CONTROL_MASK,
'q',
ModifierType.SHIFT_MASK | ModifierType.META_MASK,
)
for item in range(2, len(file_items)): # remove quits
file_menu.remove(file_items[item])
@ -54,13 +42,9 @@ def menubar_osx(gtkui, osxapp):
edit_menu = menu_widget.get_submenu()
edit_items = edit_menu.get_children()
pref_item = edit_items[0]
accel_swap(
pref_item, group, 'p', ModifierType.CONTROL_MASK, ',', ModifierType.META_MASK
)
edit_menu.remove(pref_item)
conn_item = edit_items[1]
accel_meta(conn_item, group, 'm')
edit_menu.remove(conn_item)
menubar.remove(menu_widget)
@ -75,10 +59,10 @@ def menubar_osx(gtkui, osxapp):
osxapp.set_menu_bar(menubar)
# populate app menu
osxapp.insert_app_menu_item(about_item, 0)
osxapp.insert_app_menu_item(SeparatorMenuItem(), 1)
osxapp.insert_app_menu_item(Gtk.SeparatorMenuItem(), 1)
osxapp.insert_app_menu_item(pref_item, 2)
if not config['standalone']:
osxapp.insert_app_menu_item(conn_item, 3)
if quit_all_item.get_visible():
osxapp.insert_app_menu_item(SeparatorMenuItem(), 4)
osxapp.insert_app_menu_item(Gtk.SeparatorMenuItem(), 4)
osxapp.insert_app_menu_item(quit_all_item, 5)