Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt ShortcutOverride default action

Tags:

python

qt

pyside

I understand that QEvent::ShortcutOverride occurs when there is a shortcut registered in the parent and the child wants to "go against the rule". The example given on the Qt Wiki is of a media player which pauses with Space but a QLineEdit might want to use the Space, which makes a lot of sense.

Furthermore, if the event is accepted then a QEvent::KeyPress is generated to the child widget so you can treat your particular case.

Now, my question is, why does it seem that the default action is to actually accept the QEvent::ShortcutOverride when a standard shortcut is used? This seems to me like the opposite of what the name suggest, i.e., it's overriden by default and you have to treat the event to let the shortcut pass.

In the code below, if you don't install the event filter you don't see the message.

from PySide.QtGui import QApplication
from PySide import QtGui, QtCore

app = QApplication([])

class Test(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Test, self).__init__(parent)

        self.setLayout(QtGui.QVBoxLayout())
        self.w_edit = QtGui.QLineEdit(parent=self)
        self.layout().addWidget(self.w_edit)

        # If we install the event filter and ignore() the ShortcutOverride
        # then the shortcut works
        self.w_edit.installEventFilter(self)

        # Ctrl+Left is already in use (jump to previous word)
        shortcut = QtGui.QShortcut(QtGui.QKeySequence('Ctrl+Left'), self)
        shortcut.setContext(QtCore.Qt.ApplicationShortcut)
        shortcut.activated.connect(self.test_slot)

    def test_slot(self):
        print('ctrl+left pressed!')

    def eventFilter(self, obj, event):
        if obj is self.w_edit and event.type() == QtCore.QEvent.ShortcutOverride:
            # Send the event up the hierarchy
            event.ignore()
            # Stop obj from treating the event itself
            return True

        # Events which don't concern us get forwarded
        return super(Test, self).eventFilter(obj, event)

widget = Test()
widget.show()

if __name__ == '__main__':
    app.exec_()

My actual scenario is a tab widget for which I want to use Ctrl+Left/Right to cycle through the tabs, which works unless something like a QLineEdit has focus. I feel that there should be a better way other than calling event->ignore(); return true on all QLineEdits and any other widgets which could use the key combo, am I missing something here?

Thanks!

like image 955
Iosif Spulber Avatar asked Sep 18 '25 16:09

Iosif Spulber


1 Answers

You can set one event filter on the application instance and then filter accordingly:

        QtGui.qApp.installEventFilter(self)
        # self.w_edit.installEventFilter(self)
        ...

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.ShortcutOverride:
            # filter by source object, source.parent(), or whatever...
            if isinstance(source, QtGui.QLineEdit):
                event.ignore()
                return True
        return super(Test, self).eventFilter(source, event)
like image 96
ekhumoro Avatar answered Sep 21 '25 04:09

ekhumoro