8

I would like to convert a string representing a key on the keyboard to a keycode enum like Qt::Key (or anything else). Example conversions would be:

  • "Ctrl" to Qt::Key_Control
  • "Up" to Qt::Key_Up
  • "a" to Qt::Key_A
  • "5" to Qt::Key_5

As you see the above includes not just alpha numeric keys but modifiers and special keys. I'm not attached to the Qt keycode enum, but it seems that Qt has this parsing functionality in QKeySequence's fromString static function (see this direct link):

QKeySequence fromString(const QString & str, SequenceFormat format);

You might as why I need this conversion. Well, I have a data file generated by GhostMouse. It's a log of what I type. Here's an example of me typing " It ":

{SPACE down}
{Delay 0.08}
{SPACE up}
{Delay 2.25}
{SHIFT down}
{Delay 0.11}
{i down}
{Delay 0.02}
{SHIFT up}
{Delay 0.03}
{i up}
{Delay 0.05}
{t down}
{Delay 0.08}
{t up}
{Delay 0.05}
{SPACE down}
{Delay 0.12}
{SPACE up}

So I need a way to convert the string "SPACE" and all the other strings representing keys in this data file to a unique int.

Alan Turing
  • 12,223
  • 16
  • 74
  • 116

3 Answers3

11

You were already on the right track looking at QKeySequence, as this can be used to convert between string and key codes:

QKeySequence seq = QKeySequence("SPACE");
qDebug() << seq.count(); // 1

// If the sequence contained more than one key, you
// could loop over them. But there is only one here.
uint keyCode = seq[0]; 
bool isSpace = keyCode==Qt::Key_Space;
qDebug() << keyCode << isSpace;  // 32 true

QString keyStr = seq.toString().toUpper();
qDebug() << keyStr;  // "SPACE"

added by OP

The above does not support modifier keys such as Ctrl, Alt, Shift, etc. Unfortunately, QKeySequence does not acknowledge a Ctrl key by itself as a key. So, to support modifier keys, you must split the string representation using "+" sign and then process separately each substring. The following is the complete function:

QVector<int> EmoKey::splitKeys(const QString &comb)
{
    QVector<int> keys;
    const auto keyList = comb.split('+');
    for (const auto &key: keyList) {
        if (0 == key.compare("Alt", Qt::CaseInsensitive)) {
            keys << Qt::Key_Alt;
        } else if (0 == key.compare("Ctrl", Qt::CaseInsensitive)) {
            keys << Qt::Key_Control;
        } else if (0 == key.compare("Shift", Qt::CaseInsensitive)) {
            keys << Qt::Key_Shift;
        } else if (0 == key.compare("Meta", Qt::CaseInsensitive)) {
            keys << Qt::Key_Meta;
        } else {
            const QKeySequence keySeq(key);
            if (1 == keySeq.count()) {
                keys << keySeq[0];
            }
        }
    }
    return keys;
}
Cristea Bogdan
  • 116
  • 1
  • 11
jdi
  • 90,542
  • 19
  • 167
  • 203
  • Excellent code. I had to extend it to support modifier keys. I put the result in an answer. If you want to extend your answer with that, I'll mark it as THE answer. – Alan Turing Dec 26 '12 at 00:14
  • Well I don't want to just steal your work since you came up with the extended functionality. I am fine if you need to mark yours as the real solution :-) What you can do if you want is move your answer to just an **update** to your question, and then mark mine as the answer. – jdi Dec 26 '12 at 02:35
  • Ooops I thought you meant move it to your answer. I hope that works for you. I guess the edit needs to be "approved". – Alan Turing Dec 26 '12 at 02:55
  • No problem. I added a small header for it. You can just mark this answered if its all good – jdi Dec 26 '12 at 03:35
  • This is not the correct answer: QKeySequence of a combination of keys has a count of 1 – Cristea Bogdan May 19 '20 at 19:52
  • @Cristea Bogdan, do you mean the extra part added by the OP to my answer? Because count() wasn't even part of the solution. It was just a debug output. – jdi May 21 '20 at 06:08
  • @jdi Yes, the part added by OP – Cristea Bogdan May 21 '20 at 19:47
  • @Cristea Bogdan thanks for clarifying. Maybe you could submit an edit to remove or correct the Ops faulty addition to my original accepted answer? – jdi May 22 '20 at 23:54
1

You can restore most of key codes, for example, QKeySequence::fromString("SPACE")[0] returns 32. It doesn't work for Shift, Ctrl, etc, so you should process some strings on your own.

Oleg Shparber
  • 2,732
  • 1
  • 18
  • 19
1

In one line, try it:

qDebug() << QKeySequence(event->modifiers()+event->key()).toString() << '\n';

First I call the QKeySequence contructor and then convert it to string using toString().

Output (the last one is the windows key):

"Alt+??"

"Alt+A"

"Alt+A"

"Alt+A"

"A"

"S"

"F1"

"F2"

"Home"

"Ins"

"Num+8"

"Num+5"

"Num+4"

"Num+."

"Num++"

"Num+-"

"Num+/"

"Num+*"

"??"