32 #include <QtCore/QBuffer>
33 #include <QtCore/QFile>
34 #include <QtCore/QFileInfo>
44 #if defined (Q_OS_MAC)
52 : _haveLoadedAll(false)
61 return QString(
"kb-layouts/" + name +
".keytab");
65 QDir dir(
"kb-layouts/");
67 filters <<
"*.keytab";
68 dir.setNameFilters(filters);
69 QStringList list = dir.entryList(filters);
72 list = dir.entryList(filters);
76 QStringListIterator listIter(list);
77 while (listIter.hasNext())
79 QString translatorPath = listIter.next();
81 QString name = QFileInfo(translatorPath).baseName();
104 if ( translator !=
nullptr )
106 else if ( !name.isEmpty() )
107 qWarning() <<
"Unable to load translator" << name;
114 const QString path =
".keytab";
117 qDebug() <<
"Saving translator to" << path;
119 QFile destination(path);
121 if (!destination.open(QIODevice::WriteOnly | QIODevice::Text))
123 qWarning() <<
"Unable to save keyboard translation:"
124 << destination.errorString();
133 QListIterator<KeyboardTranslator::Entry> iter(translator->
entries());
134 while ( iter.hasNext() )
149 if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text))
160 if (!textBuffer.open(QIODevice::ReadOnly))
190 : _destination(destination)
192 Q_ASSERT( destination && destination->isWritable() );
202 *
_writer <<
"keyboard \"" << description <<
'\"' <<
'\n';
263 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
264 Qt::KeyboardModifiers modifierMask = Qt::NoModifier;
266 int keyCode = Qt::Key_unknown;
281 text = tokens[2].text.toLocal8Bit();
287 qWarning() <<
"Command" << tokens[2].text <<
"not understood.";
312 if ( text.compare(
"erase",Qt::CaseInsensitive) == 0 )
314 else if ( text.compare(
"scrollpageup",Qt::CaseInsensitive) == 0 )
316 else if ( text.compare(
"scrollpagedown",Qt::CaseInsensitive) == 0 )
318 else if ( text.compare(
"scrolllineup",Qt::CaseInsensitive) == 0 )
320 else if ( text.compare(
"scrolllinedown",Qt::CaseInsensitive) == 0 )
322 else if ( text.compare(
"scrolllock",Qt::CaseInsensitive) == 0 )
332 Qt::KeyboardModifiers& modifiers,
333 Qt::KeyboardModifiers& modifierMask,
334 KeyboardTranslator::States& flags,
335 KeyboardTranslator::States& flagMask)
337 bool isWanted =
true;
338 bool endOfItem =
false;
341 Qt::KeyboardModifiers tempModifiers = modifiers;
342 Qt::KeyboardModifiers tempModifierMask = modifierMask;
343 KeyboardTranslator::States tempFlags = flags;
344 KeyboardTranslator::States tempFlagMask = flagMask;
346 for (
int i = 0 ; i < text.count() ; i++ )
348 const QChar& ch = text[i];
349 bool isLastLetter = ( i == text.count()-1 );
352 if ( ch.isLetterOrNumber() )
358 if ( (endOfItem || isLastLetter) && !buffer.isEmpty() )
360 Qt::KeyboardModifier itemModifier = Qt::NoModifier;
366 tempModifierMask |= itemModifier;
369 tempModifiers |= itemModifier;
373 tempFlagMask |= itemFlag;
376 tempFlags |= itemFlag;
379 keyCode = itemKeyCode;
381 qDebug() <<
"Unable to parse key binding item:" << buffer;
390 else if ( ch ==
'-' )
394 modifiers = tempModifiers;
395 modifierMask = tempModifierMask;
397 flagMask = tempFlagMask;
404 if ( item ==
"shift" )
405 modifier = Qt::ShiftModifier;
406 else if ( item ==
"ctrl" || item ==
"control" )
407 modifier = Qt::ControlModifier;
408 else if ( item ==
"alt" )
409 modifier = Qt::AltModifier;
410 else if ( item ==
"meta" )
411 modifier = Qt::MetaModifier;
412 else if ( item ==
"keypad" )
413 modifier = Qt::KeypadModifier;
421 if ( item ==
"appcukeys" )
423 else if ( item ==
"ansi" )
425 else if ( item ==
"newline" )
427 else if ( item ==
"appscreen" )
429 else if ( item ==
"anymod" )
438 QKeySequence sequence = QKeySequence::fromString(item);
439 if ( !sequence.isEmpty() )
441 keyCode = sequence[0];
443 if ( sequence.count() > 1 )
445 qDebug() <<
"Unhandled key codes in sequence: " << item;
449 else if ( item ==
"prior" )
450 keyCode = Qt::Key_PageUp;
451 else if ( item ==
"next" )
452 keyCode = Qt::Key_PageDown;
468 const QString& result )
470 QString entryString(
"keyboard \"temporary\"\nkey ");
471 entryString.append(condition);
472 entryString.append(
" : ");
479 entryString.append(result);
481 entryString.append(
'\"' + result +
'\"');
483 QByteArray array = entryString.toUtf8();
487 QBuffer buffer(&array);
488 buffer.open(QIODevice::ReadOnly);
514 QString text = line.simplified();
517 static QRegExp comment(
"\\#.*");
519 static QRegExp title(
"keyboard\\s+\"(.*)\"");
522 static QRegExp key(
"key\\s+([\\w\\+\\s\\-]+)\\s*:\\s*(\"(.*)\"|\\w+)");
526 if ( text.isEmpty() || comment.exactMatch(text) )
531 if ( title.exactMatch(text) )
536 list << titleToken << textToken;
538 else if ( key.exactMatch(text) )
543 list << keyToken << sequenceToken;
545 if ( key.capturedTexts()[3].isEmpty() )
549 list << commandToken;
560 qWarning() <<
"Line in keyboard translator file could not be understood:" << text;
578 , _modifiers(Qt::NoModifier)
579 , _modifierMask(Qt::NoModifier)
581 , _stateMask(NoState)
582 , _command(NoCommand)
598 Qt::KeyboardModifiers modifiers,
601 if ( _keyCode != keyCode )
604 if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) )
608 if ( modifiers != 0 )
611 if ( (
state & _stateMask) != (_state & _stateMask) )
616 bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;
632 QByteArray result(text(expandWildCards,modifiers));
634 for (
int i = 0 ; i < result.count() ; i++ )
637 char replacement = 0;
641 case 27 : replacement =
'E';
break;
642 case 8 : replacement =
'b';
break;
643 case 12 : replacement =
'f';
break;
644 case 9 : replacement =
't';
break;
645 case 13 : replacement =
'r';
break;
646 case 10 : replacement =
'n';
break;
650 if ( !QChar(ch).isPrint() )
654 if ( replacement ==
'x' )
656 result.replace(i,1,
"\\x"+QByteArray::number(QByteArray(1,ch).toInt(
nullptr, 16)));
657 }
else if ( replacement != 0 )
660 result.insert(i,
'\\');
661 result.insert(i+1,replacement);
669 QByteArray result(
input);
671 for (
int i = 0 ; i < result.count()-1 ; i++ )
674 QByteRef ch = result[i];
677 char replacement[2] = {0,0};
678 int charsToRemove = 2;
679 bool escapedChar =
true;
681 switch ( result[i+1] )
683 case 'E' : replacement[0] = 27;
break;
684 case 'b' : replacement[0] = 8 ;
break;
685 case 'f' : replacement[0] = 12;
break;
686 case 't' : replacement[0] = 9 ;
break;
687 case 'r' : replacement[0] = 13;
break;
688 case 'n' : replacement[0] = 10;
break;
694 char hexDigits[3] = {0};
696 if ( (i < result.count()-2) && isxdigit(result[i+2]) )
697 hexDigits[0] = result[i+2];
698 if ( (i < result.count()-3) && isxdigit(result[i+3]) )
699 hexDigits[1] = result[i+3];
702 sscanf(hexDigits,
"%x",&charValue);
704 replacement[0] = (char)charValue;
706 charsToRemove = 2 +
strlen(hexDigits);
714 result.replace(i,charsToRemove,replacement);
723 if ( !(modifier & _modifierMask) )
726 if ( modifier & _modifiers )
731 if ( modifier == Qt::ShiftModifier )
733 else if ( modifier == Qt::ControlModifier )
735 else if ( modifier == Qt::AltModifier )
737 else if ( modifier == Qt::MetaModifier )
739 else if ( modifier == Qt::KeypadModifier )
744 if ( !(
state & _stateMask) )
747 if (
state & _state )
765 if ( !_text.isEmpty() )
766 return escapedText(expandWildCards,modifiers);
770 return "ScrollPageUp";
772 return "ScrollPageDown";
774 return "ScrollLineUp";
776 return "ScrollLineDown";
784 QString result = QKeySequence(_keyCode).toString();
787 insertModifier( result , Qt::ShiftModifier );
788 insertModifier( result , Qt::ControlModifier );
789 insertModifier( result , Qt::AltModifier );
790 insertModifier( result , Qt::MetaModifier );
831 const int keyCode = entry.
keyCode();
850 QListIterator<Entry> iter(entriesForKey);
852 while (iter.hasNext())
855 if (
next.matches(keyCode,modifiers,
state) )
872 qWarning() <<
"Unable to save translator" << translator->
name()
881 if ( QFile::remove(path) )
888 qWarning() <<
"Failed to remove translator - " << path;
895 return theKeyboardTranslatorManager;
#define K_GLOBAL_STATIC(TYPE, NAME)
Manages the keyboard translations available for use by terminal sessions, see KeyboardTranslator.
KeyboardTranslatorManager()
Constructs a new KeyboardTranslatorManager and loads the list of available keyboard translations.
static const char * defaultTranslatorText
const KeyboardTranslator * defaultTranslator()
Returns the default translator for Konsole.
QList< QString > allTranslators()
Returns a list of the names of available keyboard translators.
bool saveTranslator(const KeyboardTranslator *translator)
~KeyboardTranslatorManager()
QString findTranslatorPath(const QString &name)
KeyboardTranslator * loadTranslator(const QString &name)
const KeyboardTranslator * findTranslator(const QString &name)
Returns the keyboard translator with the given name or 0 if no translator with that name exists.
QHash< QString, KeyboardTranslator * > _translators
void addTranslator(KeyboardTranslator *translator)
Adds a new translator.
bool deleteTranslator(const QString &name)
Deletes a translator.
Parses the contents of a Keyboard Translator (.keytab) file and returns the entries found in it.
static KeyboardTranslator::Entry createEntry(const QString &condition, const QString &result)
Parses a condition and result string for a translator entry and produces a keyboard translator entry.
KeyboardTranslatorReader(QIODevice *source)
Constructs a new reader which parses the given source.
static bool parseAsStateFlag(const QString &item, KeyboardTranslator::State &state)
QList< Token > tokenize(const QString &)
static bool parseAsKeyCode(const QString &item, int &keyCode)
bool parseError()
Returns true if an error occurred whilst parsing the input or false if no error occurred.
KeyboardTranslator::Entry _nextEntry
static bool parseAsModifier(const QString &item, Qt::KeyboardModifier &modifier)
static bool parseAsCommand(const QString &text, KeyboardTranslator::Command &command)
bool decodeSequence(const QString &, int &keyCode, Qt::KeyboardModifiers &modifiers, Qt::KeyboardModifiers &modifierMask, KeyboardTranslator::States &state, KeyboardTranslator::States &stateFlags)
bool hasNextEntry()
Returns true if there is another entry in the source stream.
KeyboardTranslator::Entry nextEntry()
Returns the next entry found in the source stream.
QString description() const
Returns the description text.
Writes a keyboard translation to disk.
~KeyboardTranslatorWriter()
void writeHeader(const QString &description)
Writes the header for the keyboard translator.
void writeEntry(const KeyboardTranslator::Entry &entry)
Writes a translator entry.
KeyboardTranslatorWriter(QIODevice *destination)
Constructs a new writer which saves data into destination.
Represents an association between a key sequence pressed by the user and the character sequence and c...
void setModifiers(Qt::KeyboardModifiers modifiers)
See modifiers()
QByteArray unescape(const QByteArray &text) const
void insertState(QString &item, int state) const
QString resultToString(bool expandWildCards=false, Qt::KeyboardModifiers modifiers=Qt::NoModifier) const
Returns this entry's result ( ie.
void setText(const QByteArray &text)
Sets the character sequence associated with this entry.
QString conditionToString() const
Returns the key code and modifiers associated with this entry as a QKeySequence.
void setKeyCode(int keyCode)
Sets the character code associated with this entry.
Qt::KeyboardModifiers _modifiers
Command command() const
Returns the commands associated with this entry.
Qt::KeyboardModifiers _modifierMask
int keyCode() const
Returns the character code ( from the Qt::Key enum ) associated with this entry.
bool isNull() const
Returns true if this entry is null.
bool matches(int keyCode, Qt::KeyboardModifiers modifiers, States flags) const
Returns true if this entry matches the given key sequence, specified as a combination of keyCode ,...
bool operator==(const Entry &rhs) const
void setStateMask(States mask)
See stateMask()
void setCommand(Command command)
Sets the command associated with this entry.
void insertModifier(QString &item, int modifier) const
QByteArray escapedText(bool expandWildCards=false, Qt::KeyboardModifiers modifiers=Qt::NoModifier) const
Returns the character sequence associated with this entry, with any non-printable characters replaced...
void setState(States state)
See state()
void setModifierMask(Qt::KeyboardModifiers modifiers)
See modifierMask() and modifiers()
Entry()
Constructs a new entry for a keyboard translator.
A convertor which maps between key sequences pressed by the user and the character strings which shou...
QString name() const
Returns the name of this keyboard translator.
State
The meaning of a particular key sequence may depend upon the state which the terminal emulation is in...
@ NewLineState
TODO More documentation.
@ NoState
Indicates that no special state is active.
@ AnyModifierState
Indicates that any of the modifier keys is active.
@ AnsiState
Indicates that the terminal is in 'Ansi' mode.
@ AlternateScreenState
Indicates that the alternate screen ( typically used by interactive programs such as screen or vim ) ...
@ CursorKeysState
TODO More documentation.
Entry findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state=NoState) const
Looks for an entry in this keyboard translator which matches the given key code, keyboard modifiers a...
QString description() const
Returns the descriptive name of this keyboard translator.
Command
This enum describes commands which are associated with particular key sequences.
@ ScrollLineUpCommand
Scroll the terminal display up one line.
@ EraseCommand
Echos the operating system specific erase character.
@ ScrollPageUpCommand
Scroll the terminal display up one page.
@ ScrollPageDownCommand
Scroll the terminal display down one page.
@ NoCommand
Indicates that no command is associated with this command sequence.
@ ScrollLockCommand
Toggles scroll lock mode.
@ ScrollLineDownCommand
Scroll the terminal display down one line.
void replaceEntry(const Entry &existing, const Entry &replacement)
Replaces an entry in the translator.
void setName(const QString &name)
Sets the name of this keyboard translator.
QList< Entry > entries() const
Returns a list of all entries in the translator.
KeyboardTranslator(const QString &name)
Constructs a new keyboard translator with the given name.
QMultiHash< int, Entry > _entries
void setDescription(const QString &description)
Sets the descriptive name of this keyboard translator.
void addEntry(const Entry &entry)
Adds an entry to this keyboard translator's table.
void removeEntry(const Entry &entry)
Removes an entry from the table.
T::size_type strlen(const typename T::value_type *str)
static int input(yyscan_t yyscanner)
static uint32_t state[624]