Browse Source

re-implement the qt-broken hover shortcuts by using our own event filter

master
Nils 4 years ago
parent
commit
19a7a05169
  1. 44
      template/qtgui/mainwindow.py
  2. 9
      template/qtgui/menu.py

44
template/qtgui/mainwindow.py

@ -129,6 +129,8 @@ class MainWindow(QtWidgets.QMainWindow):
self.ui.menubar.setNativeMenuBar(False) #Force a real menu bar. Qt on wayland will not display it otherwise.
self.menu = Menu(mainWindow=self) #needs the about dialog, save file and the api.session ready.
self.installEventFilter(self) #Bottom of the file. Works around the hover numpad bug that is in Qt for years.
self.initiGuiSharedDataToSave()
def start(self):
@ -148,6 +150,7 @@ class MainWindow(QtWidgets.QMainWindow):
self._zoom() #enable zoom factor loaded from save file
#def event(self, event):
# print (event.type())
# return super().event(event)
@ -333,5 +336,46 @@ class MainWindow(QtWidgets.QMainWindow):
self.show()
self.nsmClient.announceGuiVisibility(True)
def eventFilter(self, obj, event):
"""Qt has a known but unresolved bug (for many years now)
that shortcuts with the numpad don't trigger. This has little
chance of ever getting fixed, despite getting reported multiple
times.
Try to uninstall this filter (self.__init__) after a new qt release
and check if it works without. It should (it did already in the past)
but so far no luck...
What do we do?
We intercept every key and see if it was with a numpad modifier.
If yes we trigger the menu action ourselves and discard the event
We also need to separate the action of assigning a hover shortcut
to a menu and actually triggering it. Since we are in the template
part of the program we can't assume there is a main widget,
as in Patroneo and Laborejos case.
The obj is always MainWindow, so we can't detect if the menu was open or not.
self.qtApp.focusWidget() is also NOT the menu.
The menu is only triggered AFTER the filter. But we need to
detect if a menu is open while we are running the filter.
self.menu.ui.menubar.activeAction()
For each key press/release we receive 3 keypress events, not
counting autoRepeats. event.type() which is different from type(event)
returns 51 (press), 6(release), 7(accept) for the three. This is key press, release and event accept(?).
This event filter somehow does not differentiate between numpad
on or numpad off. There maybe is another qt check for that.
"""
if (not self.menu.ui.menubar.activeAction()) and event.type() == 51 and type(event) is QtGui.QKeyEvent and event.modifiers() == QtCore.Qt.KeypadModifier and event.text() and event.text() in "0123456789":
action = self.menu.hoverShortcutDict[event.text()]
if action:
action.trigger()
event.accept() #despite what Qt docs say it is not enough to return True to "eat" the event.
return True
else:
#No keypad shortcut. Just use the normal handling.
return super().eventFilter(obj, event)

9
template/qtgui/menu.py

@ -46,7 +46,7 @@ class Menu(object):
#Hover Shortcuts
self.hoverShortcutDict = HoverActionDictionary(self.mainWindow) #for temporary hover shortcuts. key=actual key, value=QAction
self.lastHoverAction = None #the last time the mouse hovered over a menu it was this QAction
self.lastHoverAction = None #the last time the mouse hovered over a menu it was this QAction. This gets never empty again, but works because we only check it during menu KeyPressEvent
def _rememberHover(action): self.lastHoverAction = action
self.ui.menubar.hovered.connect(_rememberHover)
self._originalMenuKeyPressEvent = self.ui.menubar.keyPressEvent
@ -121,12 +121,14 @@ class Menu(object):
self.ui.menuDebug.menuAction().setVisible(state) #...therefore we hide manually.
def menuKeyPressInterceptor(self, event):
"""Menu Entries without their own shortcut can be temporarily assigned one of the ten
"""
Triggered when a menu is open and mouse hovers over a menu.
Menu Entries without their own shortcut can be temporarily assigned one of the ten
number keypad keys as shortcuts.
If the numpad key is already in use it will be rerouted (freed first).
"""
strings = set(("Num+1", "Num+2", "Num+3", "Num+4", "Num+5", "Num+6", "Num+7", "Num+8", "Num+9", "Num+0"))
if self.lastHoverAction and (not self.lastHoverAction.menu()) and event.modifiers() == QtCore.Qt.KeypadModifier and ((not self.lastHoverAction.shortcut().toString()) or self.lastHoverAction.shortcut().toString() in strings):
key = event.text() #just number 0-9 #event.key() is 49, 50...
@ -135,6 +137,7 @@ class Menu(object):
else:
self._originalMenuKeyPressEvent(event)
def addSubmenu(self, submenuActionAsString, text):
"""
Returns the submenu.

Loading…
Cancel
Save