diff --git a/src/KeyboardTranslator.cpp b/src/KeyboardTranslator.cpp index 0837e07cc..18d8364bb 100644 --- a/src/KeyboardTranslator.cpp +++ b/src/KeyboardTranslator.cpp @@ -155,29 +155,21 @@ void KeyboardTranslatorReader::readNext() if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword ) { KeyboardTranslator::State flags = KeyboardTranslator::NoState; - QKeySequence sequence = decodeSequence(tokens[1].text,flags); + KeyboardTranslator::State flagMask = KeyboardTranslator::NoState; + Qt::KeyboardModifier modifiers = Qt::NoModifier; + Qt::KeyboardModifier modifierMask = Qt::NoModifier; int keyCode = Qt::Key_unknown; - int modifiers = Qt::NoModifier; - QByteArray text; + + decodeSequence(tokens[1].text, + keyCode, + modifiers, + modifierMask, + flags, + flagMask); + KeyboardTranslator::Command command = KeyboardTranslator::NoCommand; - - // get keycode and modifiers - if ( sequence.count() == 1 ) - { - int code = sequence[0]; - - if ( code & Qt::SHIFT ) - modifiers |= Qt::ShiftModifier; - if ( code & Qt::CTRL ) - modifiers |= Qt::ControlModifier; - if ( code & Qt::ALT ) - modifiers |= Qt::AltModifier; - if ( code & Qt::META ) - modifiers |= Qt::MetaModifier; - - keyCode = code & ~Qt::SHIFT & ~Qt::CTRL & ~Qt::ALT & ~Qt::META; - } + QByteArray text; // get text or command if ( tokens[2].type == Token::OutputText ) @@ -202,9 +194,16 @@ void KeyboardTranslatorReader::readNext() } + KeyboardTranslator::Entry newEntry; + newEntry.setKeyCode( keyCode ); + newEntry.setState( flags ); + newEntry.setStateMask( flagMask ); + newEntry.setModifiers( modifiers ); + newEntry.setModifierMask( modifierMask ); + newEntry.setText( text ); + newEntry.setCommand( command ); - _nextEntry = KeyboardTranslator::Entry(keyCode,(Qt::KeyboardModifier)modifiers,flags,text,command); - + _nextEntry = newEntry; _hasNext = true; @@ -214,6 +213,129 @@ void KeyboardTranslatorReader::readNext() _hasNext = false; } + +bool KeyboardTranslatorReader::decodeSequence(const QString& text, + int& keyCode, + Qt::KeyboardModifier& modifiers, + Qt::KeyboardModifier& modifierMask, + KeyboardTranslator::State& flags, + KeyboardTranslator::State& flagMask) +{ + bool isWanted = true; + bool endOfItem = false; + QString buffer; + + int tempModifiers = modifiers; + int tempModifierMask = modifierMask; + int tempFlags = flags; + int tempFlagMask = flagMask; + + for ( int i = 0 ; i < text.count() ; i++ ) + { + const QChar& ch = text[i]; + bool isLastLetter = ( i == text.count()-1 ); + + endOfItem = true; + + if ( ch.isLetterOrNumber() ) + { + endOfItem = false; + + buffer.append(ch); + } + else if ( ch == '+' ) + isWanted = true; + else if ( ch == '-' ) + isWanted = false; + + if ( (endOfItem || isLastLetter) && !buffer.isEmpty() ) + { + qDebug() << "Parsing item: " << buffer; + + int itemModifier = 0; + int itemKeyCode = 0; + int itemFlag = 0; + + if ( parseAsModifier(buffer,itemModifier) ) + { + tempModifierMask |= itemModifier; + + if ( isWanted ) + tempModifiers |= itemModifier; + } + else if ( parseAsStateFlag(buffer,itemFlag) ) + { + tempFlagMask |= itemFlag; + + if ( isWanted ) + tempFlags |= itemFlag; + } + else if ( parseAsKeyCode(buffer,itemKeyCode) ) + keyCode = itemKeyCode; + else + qDebug() << "Unable to parse key binding item:" << buffer; + + buffer.clear(); + } + } + + modifiers = (Qt::KeyboardModifier)tempModifiers; + modifierMask = (Qt::KeyboardModifier)tempModifierMask; + flags = (KeyboardTranslator::State)tempFlags; + flagMask = (KeyboardTranslator::State)tempFlagMask; + + return true; +} + +bool KeyboardTranslatorReader::parseAsModifier(const QString& item , int& modifier) +{ + if ( item == "shift" ) + modifier = Qt::ShiftModifier; + else if ( item == "ctrl" || item == "control" ) + modifier = Qt::ControlModifier; + else if ( item == "alt" ) + modifier = Qt::AltModifier; + else if ( item == "meta" ) + modifier = Qt::MetaModifier; + else + return false; + + return true; +} +bool KeyboardTranslatorReader::parseAsStateFlag(const QString& item , int& flag) +{ + if ( item == "appcukeys" ) + flag = KeyboardTranslator::CursorKeysState; + else if ( item == "ansi" ) + flag = KeyboardTranslator::AnsiState; + else if ( item == "newline" ) + flag = KeyboardTranslator::NewLineState; + else if ( item == "appscreen" ) + flag = KeyboardTranslator::AlternateScreenState; + else + return false; + + return true; +} +bool KeyboardTranslatorReader::parseAsKeyCode(const QString& item , int& keyCode) +{ + QKeySequence sequence = QKeySequence::fromString(item); + if ( !sequence.isEmpty() ) + { + keyCode = sequence[0]; + + if ( sequence.count() > 1 ) + { + qDebug() << "Unhandled key codes in sequence: " << item; + } + } + else + return false; + + return true; +} + +#if 0 QKeySequence KeyboardTranslatorReader::decodeSequence(const QString& text , KeyboardTranslator::State& stateFlags ) { int state = KeyboardTranslator::NoState; @@ -285,6 +407,8 @@ QKeySequence KeyboardTranslatorReader::decodeSequence(const QString& text , Keyb return sequence; } +#endif + QString KeyboardTranslatorReader::description() const { return _description; @@ -375,18 +499,6 @@ QList KeyboardTranslatorManager::allTranslators() return _translators.keys(); } -KeyboardTranslator::Entry::Entry( int keyCode, - Qt::KeyboardModifier modifiers, - State flags, - const QByteArray& text, - Command command ) -: _keyCode(keyCode) -, _modifiers(modifiers) -, _state(flags) -, _command(command) -, _text(text) -{ -} KeyboardTranslator::Entry::Entry() : _keyCode(0) , _modifiers(Qt::NoModifier) @@ -414,7 +526,16 @@ QKeySequence KeyboardTranslator::Entry::keySequence() const bool KeyboardTranslator::Entry::matches(int keyCode , Qt::KeyboardModifier modifiers, State state) const { - return false; + if ( _keyCode != keyCode ) + return false; + + if ( modifiers != ( _modifiers & _modifierMask ) ) + return false; + + if ( state != ( _state & _stateMask ) ) + return false; + + return true; } KeyboardTranslator::KeyboardTranslator(const QString& name) : _name(name) diff --git a/src/KeyboardTranslator.h b/src/KeyboardTranslator.h index 0ffaa913a..7be8c872b 100644 --- a/src/KeyboardTranslator.h +++ b/src/KeyboardTranslator.h @@ -113,34 +113,60 @@ public: public: /** * Constructs a new entry for a keyboard translator. - * - * @param keyCode A key code from the Qt::Key enum - * @param modifiers The combination of keyboard modifiers - * @param flags The state flags associated with this entry - * @param text The character sequence which should be sent to the terminal when - * the key sequence described by the @p keyCode, @p modifiers and @p state is activated. - * @param command The commands which should be executed when the key sequence - * described by the @p keyCode, @p modifiers and @p state is activated. */ - Entry( int keyCode , - Qt::KeyboardModifier modifiers , - State flags, - const QByteArray& text, - Command command ); Entry(); /** Returns the commands associated with this entry */ Command command() const; + /** Sets the command associated with this entry. */ + void setCommand(Command command); + /** Returns the character sequence associated with this entry */ QByteArray text() const; + /** Sets the character sequence associated with this entry */ + void setText(const QByteArray& text); /** Returns the character code ( from the Qt::Key enum ) associated with this entry */ int keyCode() const; - /** Returns the keyboard modifiers associated with this entry */ + /** Sets the character code associated with this entry */ + void setKeyCode(int keyCode); + + /** + * Returns the a bitwise-OR of the enabled keyboard modifiers associated with this entry. + * If a modifier is set in modifierMask() but not in modifiers(), this means that the entry + * only matches when that modifier is NOT pressed. + * + * If a modifier is not set in modifierMask() then the entry matches whether the modifier + * is pressed or not. + */ Qt::KeyboardModifier modifiers() const; - /** Returns the state flags associated with this entry */ + + /** Returns the keyboard modifiers which are valid in this entry. See modifiers() */ + Qt::KeyboardModifier modifierMask() const; + + /** See modifiers() */ + void setModifiers( Qt::KeyboardModifier modifiers ); + /** See modifierMask() and modifiers() */ + void setModifierMask( Qt::KeyboardModifier modifiers ); + + /** + * Returns a bitwise-OR of the enabled state flags associated with this entry. + * If flag is set in stateMask() but not in state(), this means that the entry only + * matches when the terminal is NOT in that state. + * + * If a state is not set in stateMask() then the entry matches whether the terminal + * is in that state or not. + */ State state() const; + /** Returns the state flags which are valid in this entry. See state() */ + State stateMask() const; + + /** See state() */ + void setState( State state ); + /** See stateMask() */ + void setStateMask( State mask ); + /** * Returns the key code and modifiers associated with this entry * as a QKeySequence @@ -157,7 +183,9 @@ public: private: int _keyCode; Qt::KeyboardModifier _modifiers; + Qt::KeyboardModifier _modifierMask; State _state; + State _stateMask; Command _command; QByteArray _text; @@ -278,8 +306,17 @@ private: }; QList tokenize(const QString&); void readNext(); - QKeySequence decodeSequence(const QString& , KeyboardTranslator::State& stateFlags); + bool decodeSequence(const QString& , + int& keyCode, + Qt::KeyboardModifier& modifiers, + Qt::KeyboardModifier& modifiers, + KeyboardTranslator::State& state, + KeyboardTranslator::State& stateFlags); + bool parseAsModifier(const QString& item , int& modifier); + bool parseAsStateFlag(const QString& item , int& modifier); + bool parseAsKeyCode(const QString& item , int& modifier); + QIODevice* _source; QString _description; KeyboardTranslator::Entry _nextEntry; @@ -353,26 +390,44 @@ private: static KeyboardTranslatorManager* _instance; }; -inline int KeyboardTranslator::Entry::keyCode() const -{ - return _keyCode; +inline int KeyboardTranslator::Entry::keyCode() const { return _keyCode; } +inline void KeyboardTranslator::Entry::setKeyCode(int keyCode) { _keyCode = keyCode; } + +inline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifier modifier ) +{ + _modifiers = modifier; } -inline Qt::KeyboardModifier KeyboardTranslator::Entry::modifiers() const -{ - return _modifiers; +inline Qt::KeyboardModifier KeyboardTranslator::Entry::modifiers() const { return _modifiers; } + +inline void KeyboardTranslator::Entry::setModifierMask( Qt::KeyboardModifier mask ) +{ + _modifierMask = mask; } -inline KeyboardTranslator::Command KeyboardTranslator::Entry::command() const -{ - return _command; +inline Qt::KeyboardModifier KeyboardTranslator::Entry::modifierMask() const { return _modifierMask; } + +inline void KeyboardTranslator::Entry::setCommand( Command command ) +{ + _command = command; } -inline QByteArray KeyboardTranslator::Entry::text() const -{ - return _text; +inline KeyboardTranslator::Command KeyboardTranslator::Entry::command() const { return _command; } + +inline void KeyboardTranslator::Entry::setText( const QByteArray& text ) +{ + _text = text; } -inline KeyboardTranslator::State KeyboardTranslator::Entry::state() const -{ - return _state; +inline QByteArray KeyboardTranslator::Entry::text() const { return _text; } + +inline void KeyboardTranslator::Entry::setState( State state ) +{ + _state = state; } +inline KeyboardTranslator::State KeyboardTranslator::Entry::state() const { return _state; } + +inline void KeyboardTranslator::Entry::setStateMask( State stateMask ) +{ + _stateMask = stateMask; +} +inline KeyboardTranslator::State KeyboardTranslator::Entry::stateMask() const { return _stateMask; } }