QKeySequence to QKeyEvent

6.1k views Asked by At

I'm in a situation whereby I am trying to read in a JSON config file which dictates what key commands map to given actions. For example:

...
{ 
    "Action": "Quit",
    "Combo" : "CTRL+Q"
},
...

Constructing a QKeySequence from the combo tag is trivial but I need to monitor QKeyEvents in order to trigger actions. Please note I have to monitor QKeyEvents because they are used for other purposes in the application as well. i.e. it would not be acceptable to only monitor key commands for QKeySequences (if that is even possible).

Short of writing a custom parser to construct a QKeyEvent object for each "Combo" tag, is there anyway of comparing a QkeyEvent to a QKeySequence? For example:

QKeyEvent KeyCommandsHandler::toKeyEvent(QKeySequence sequence) {
   //somehow convert to QKeyEvent
}
3

There are 3 answers

0
Jeff On

A simple solution (written in python):

key = QKeySequence(event.modifiers()|event.key()).toString()

Will give you the entire sequence in string form, such as "Ctrl+Q".

The benefits are (at least in python) that you can find in a dict of shortcuts, while a QKeySequence would not have been hashable.

Beware that this expects you use the correct typecase and spacing. "ctrl +Q" will not match. To avoid all issues, you can do the following when first reading the shortcuts:

shortcut = shortcut.lower().remove(' ')

and match/find using

key = QKeySequence(event.modifiers()|event.key()).toString().lower()

or better yet:

shortcut = QKeySequence(shortcut).toString()

and match directly.

0
Ferdinand Beyer On

In general, you cannot compare QKeyEvent and QKeySequence objects. QKeyEvent represents the event of a single key press or release, whereas a QKeySequence can contain a sequence of up to four keys, each with optional modifier information.

You can, however, compare the objects if you are sure that your key sequences will always contain just one key:

bool isEquiv(const QKeyEvent& event, const QKeySequence& seq)
{
    if (seq.count() != 1)
        return false;
    return seq[0] == (event.key() | event.modifiers());
}

You can even write a conversion function for QKeyEvent to QKeySequence:

QKeySequence toKeySequence(const QKeyEvent& event)
{
    return QKeySequence(event.key() | event.modifiers());
}

Note that it does not make sense to convert a QKeySequence to a QKeyEvent, though, since you have to choose a specific event type such as QEvent::KeyPress or QEvent::KeyRelease.

0
bootchk On

A Qt4.7 note with code for converting KeyEvent to KeySequence. (But the code is flawed because it casts an int for the keycode from QKeyEvent.key() to a string. Better to use QKeyEvent.text() ?)

Also, the code in Ferdinand's answer:

QKeySequence(event.key() | event.modifiers())

is not type safe (mixes int and QKeyboardModifiers) and if converted to Python fails in PyQt, but not in PySide?

Also, "QKeyEvent represents the event of a single key press or release" doesn't really explain it. A QKeyEvent can tell you what combination of keys were down, just not the order in which they were pressed. When the user presses keys in sequence, your app might get a sequence of QKeyEvents (depending on whether your app is using default versus overridden handlers for QKeyEvent.) The later QKeyEvents will show you all the keys that were down at the time of the event. They might no longer be down. It is rather complicated.