[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:
parent
4b6ac1f4c4
commit
a64cdfaf78
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Generated with glade 3.22.1 -->
|
<!-- Generated with glade 3.22.2 -->
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="3.0"/>
|
<requires lib="gtk+" version="3.0"/>
|
||||||
<object class="GtkImage" id="about-image">
|
<object class="GtkImage" id="about-image">
|
||||||
|
@ -7,7 +7,6 @@
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="icon_name">help-about-symbolic</property>
|
<property name="icon_name">help-about-symbolic</property>
|
||||||
</object>
|
</object>
|
||||||
<object class="GtkAccelGroup" id="accelgroup1"/>
|
|
||||||
<object class="GtkImage" id="add-image">
|
<object class="GtkImage" id="add-image">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
@ -67,6 +66,7 @@
|
||||||
<property name="icon_name">zoom-fit-best-symbolic</property>
|
<property name="icon_name">zoom-fit-best-symbolic</property>
|
||||||
<property name="icon_size">1</property>
|
<property name="icon_size">1</property>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="GtkAccelGroup" id="main_accelgroup"/>
|
||||||
<object class="GtkImage" id="new-image">
|
<object class="GtkImage" id="new-image">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
@ -93,9 +93,9 @@
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="title">Deluge</property>
|
<property name="title">Deluge</property>
|
||||||
<accel-groups>
|
<accel-groups>
|
||||||
<group name="accelgroup1"/>
|
<group name="main_accelgroup"/>
|
||||||
</accel-groups>
|
</accel-groups>
|
||||||
<child>
|
<child type="titlebar">
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -114,8 +114,10 @@
|
||||||
<property name="label" translatable="yes">_File</property>
|
<property name="label" translatable="yes">_File</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<child type="submenu">
|
<child type="submenu">
|
||||||
<object class="GtkMenu" id="menuitem1_menu1">
|
<object class="GtkMenu" id="submenu_file">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="accel_group">main_accelgroup</property>
|
||||||
|
<property name="accel_path"><Deluge-MainWindow>/File</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImageMenuItem" id="menuitem_addtorrent">
|
<object class="GtkImageMenuItem" id="menuitem_addtorrent">
|
||||||
<property name="label" translatable="yes">_Add Torrent</property>
|
<property name="label" translatable="yes">_Add Torrent</property>
|
||||||
|
@ -126,7 +128,6 @@
|
||||||
<property name="image">add-image</property>
|
<property name="image">add-image</property>
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_addtorrent_activate" swapped="no"/>
|
<signal name="activate" handler="on_menuitem_addtorrent_activate" swapped="no"/>
|
||||||
<accelerator key="O" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -138,7 +139,6 @@
|
||||||
<property name="image">new-image</property>
|
<property name="image">new-image</property>
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_createtorrent_activate" swapped="no"/>
|
<signal name="activate" handler="on_menuitem_createtorrent_activate" swapped="no"/>
|
||||||
<accelerator key="N" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -155,7 +155,6 @@
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<property name="always_show_image">True</property>
|
<property name="always_show_image">True</property>
|
||||||
<signal name="activate" handler="on_menuitem_quitdaemon_activate" swapped="no"/>
|
<signal name="activate" handler="on_menuitem_quitdaemon_activate" swapped="no"/>
|
||||||
<accelerator key="Q" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -172,9 +171,8 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="image">quit_image</property>
|
<property name="image">quit_image</property>
|
||||||
<property name="use_stock">False</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"/>
|
<signal name="activate" handler="on_menuitem_quit_activate" swapped="no"/>
|
||||||
<accelerator key="Q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@ -188,9 +186,11 @@
|
||||||
<property name="label" translatable="yes">_Edit</property>
|
<property name="label" translatable="yes">_Edit</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<child type="submenu">
|
<child type="submenu">
|
||||||
<object class="GtkMenu" id="menu1">
|
<object class="GtkMenu" id="submenu_edit">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="accel_group">main_accelgroup</property>
|
||||||
|
<property name="accel_path"><Deluge-MainWindow>/Edit</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImageMenuItem" id="menuitem_preferences">
|
<object class="GtkImageMenuItem" id="menuitem_preferences">
|
||||||
<property name="label" translatable="yes">_Preferences</property>
|
<property name="label" translatable="yes">_Preferences</property>
|
||||||
|
@ -199,9 +199,8 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="image">prefs-image</property>
|
<property name="image">prefs-image</property>
|
||||||
<property name="use_stock">False</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"/>
|
<signal name="activate" handler="on_menuitem_preferences_activate" swapped="no"/>
|
||||||
<accelerator key="P" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -213,7 +212,6 @@
|
||||||
<property name="image">connection-image</property>
|
<property name="image">connection-image</property>
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_connectionmanager_activate" swapped="no"/>
|
<signal name="activate" handler="on_menuitem_connectionmanager_activate" swapped="no"/>
|
||||||
<accelerator key="M" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@ -223,6 +221,7 @@
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="menu_torrent">
|
<object class="GtkMenuItem" id="menu_torrent">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="accel_path"><MainWindow>/Torrent</property>
|
||||||
<property name="label" translatable="yes">_Torrent</property>
|
<property name="label" translatable="yes">_Torrent</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
</object>
|
</object>
|
||||||
|
@ -234,9 +233,11 @@
|
||||||
<property name="label" translatable="yes">_View</property>
|
<property name="label" translatable="yes">_View</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<child type="submenu">
|
<child type="submenu">
|
||||||
<object class="GtkMenu" id="menu2">
|
<object class="GtkMenu" id="submenu_view">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="accel_group">main_accelgroup</property>
|
||||||
|
<property name="accel_path"><Deluge-MainWindow>/View</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkCheckMenuItem" id="menuitem_toolbar">
|
<object class="GtkCheckMenuItem" id="menuitem_toolbar">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -297,7 +298,6 @@
|
||||||
<property name="label" translatable="yes">_Find ...</property>
|
<property name="label" translatable="yes">_Find ...</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<signal name="activate" handler="on_search_filter_toggle" swapped="no"/>
|
<signal name="activate" handler="on_search_filter_toggle" swapped="no"/>
|
||||||
<accelerator key="f" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -356,8 +356,10 @@
|
||||||
<property name="label" translatable="yes">_Help</property>
|
<property name="label" translatable="yes">_Help</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<child type="submenu">
|
<child type="submenu">
|
||||||
<object class="GtkMenu" id="menuitem2_menu1">
|
<object class="GtkMenu" id="submenu_help">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="accel_group">main_accelgroup</property>
|
||||||
|
<property name="accel_path"><Deluge-MainWindow>/Help</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImageMenuItem" id="menuitem_homepage">
|
<object class="GtkImageMenuItem" id="menuitem_homepage">
|
||||||
<property name="label" translatable="yes">_Homepage</property>
|
<property name="label" translatable="yes">_Homepage</property>
|
||||||
|
@ -377,7 +379,6 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_faq_activate" swapped="no"/>
|
<signal name="activate" handler="on_menuitem_faq_activate" swapped="no"/>
|
||||||
<accelerator key="F1" signal="activate"/>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -405,7 +406,7 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="image">about-image</property>
|
<property name="image">about-image</property>
|
||||||
<property name="use_stock">False</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"/>
|
<signal name="activate" handler="on_menuitem_about_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</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="label" translatable="yes">Filter</property>
|
||||||
<property name="icon_name">system-search-symbolic</property>
|
<property name="icon_name">system-search-symbolic</property>
|
||||||
<signal name="clicked" handler="on_search_filter_toggle" swapped="no"/>
|
<signal name="clicked" handler="on_search_filter_toggle" swapped="no"/>
|
||||||
<accelerator key="f" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
|
|
@ -23,6 +23,17 @@ from .path_chooser import PathChooser
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
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):
|
class MenuBar(component.Component):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -112,6 +123,11 @@ class MenuBar(component.Component):
|
||||||
# Attach the torrent_menu to the Torrent file menu
|
# Attach the torrent_menu to the Torrent file menu
|
||||||
self.menu_torrent.set_submenu(self.torrentmenu)
|
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
|
# Make sure the view menuitems are showing the correct active state
|
||||||
self.main_builder.get_object('menuitem_toolbar').set_active(
|
self.main_builder.get_object('menuitem_toolbar').set_active(
|
||||||
self.config['show_toolbar']
|
self.config['show_toolbar']
|
||||||
|
|
|
@ -5,48 +5,36 @@
|
||||||
# the additional special exception to link portions of this program with the OpenSSL library.
|
# the additional special exception to link portions of this program with the OpenSSL library.
|
||||||
# See LICENSE for more details.
|
# See LICENSE for more details.
|
||||||
#
|
#
|
||||||
|
from gi.repository import Gtk
|
||||||
from gi.repository.Gdk import ModifierType
|
|
||||||
from gi.repository.Gtk import SeparatorMenuItem, accel_groups_from_object
|
|
||||||
from gi.repository.Gtk.AccelFlags import VISIBLE
|
|
||||||
|
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
|
|
||||||
|
macos_main_window_accelmap = {
|
||||||
def accel_swap(item, group, skey, smod, dkey, dmod):
|
'<Deluge-MainWindow>/File/Add Torrent': '<Meta>o',
|
||||||
# Accel map hack broken, see ticket #3078
|
'<Deluge-MainWindow>/File/Create Torrent': '<Meta>n',
|
||||||
# item.remove_accelerator(group, ord(skey), smod)
|
'<Deluge-MainWindow>/File/Quit & Shutdown Daemon': '<Meta><Shift>q',
|
||||||
item.add_accelerator('activate', group, ord(dkey), dmod, VISIBLE)
|
'<Deluge-MainWindow>/File/Quit': '<Meta>q',
|
||||||
|
'<Deluge-MainWindow>/Edit/Preferences': '<Meta>comma',
|
||||||
|
'<Deluge-MainWindow>/Edit/Connection Manager': '<Meta>m',
|
||||||
def accel_meta(item, group, key):
|
'<Deluge-MainWindow>/View/Find ...': '<Meta>f',
|
||||||
accel_swap(item, group, key, ModifierType.CONTROL_MASK, key, ModifierType.META_MASK)
|
'<Deluge-MainWindow>/Help/FAQ': '<Meta>question',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def menubar_osx(gtkui, osxapp):
|
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()
|
main_builder = gtkui.mainwindow.get_builder()
|
||||||
menubar = main_builder.get_object('menubar')
|
menubar = main_builder.get_object('menubar')
|
||||||
group = accel_groups_from_object(gtkui.mainwindow.window)[0]
|
|
||||||
|
|
||||||
config = ConfigManager('gtk3ui.conf')
|
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_menu = main_builder.get_object('menu_file').get_submenu()
|
||||||
file_items = file_menu.get_children()
|
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]
|
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
|
for item in range(2, len(file_items)): # remove quits
|
||||||
file_menu.remove(file_items[item])
|
file_menu.remove(file_items[item])
|
||||||
|
|
||||||
|
@ -54,13 +42,9 @@ def menubar_osx(gtkui, osxapp):
|
||||||
edit_menu = menu_widget.get_submenu()
|
edit_menu = menu_widget.get_submenu()
|
||||||
edit_items = edit_menu.get_children()
|
edit_items = edit_menu.get_children()
|
||||||
pref_item = edit_items[0]
|
pref_item = edit_items[0]
|
||||||
accel_swap(
|
|
||||||
pref_item, group, 'p', ModifierType.CONTROL_MASK, ',', ModifierType.META_MASK
|
|
||||||
)
|
|
||||||
edit_menu.remove(pref_item)
|
edit_menu.remove(pref_item)
|
||||||
|
|
||||||
conn_item = edit_items[1]
|
conn_item = edit_items[1]
|
||||||
accel_meta(conn_item, group, 'm')
|
|
||||||
edit_menu.remove(conn_item)
|
edit_menu.remove(conn_item)
|
||||||
|
|
||||||
menubar.remove(menu_widget)
|
menubar.remove(menu_widget)
|
||||||
|
@ -75,10 +59,10 @@ def menubar_osx(gtkui, osxapp):
|
||||||
osxapp.set_menu_bar(menubar)
|
osxapp.set_menu_bar(menubar)
|
||||||
# populate app menu
|
# populate app menu
|
||||||
osxapp.insert_app_menu_item(about_item, 0)
|
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)
|
osxapp.insert_app_menu_item(pref_item, 2)
|
||||||
if not config['standalone']:
|
if not config['standalone']:
|
||||||
osxapp.insert_app_menu_item(conn_item, 3)
|
osxapp.insert_app_menu_item(conn_item, 3)
|
||||||
if quit_all_item.get_visible():
|
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)
|
osxapp.insert_app_menu_item(quit_all_item, 5)
|
||||||
|
|
Loading…
Reference in New Issue