GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
KeyboardTranslator.cpp
Go to the documentation of this file.
1 /*
2  This source file was part of Konsole, a terminal emulator.
3 
4  Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>
5 
6  Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301 USA.
22 */
23 
24 // Own
26 
27 // System
28 #include <ctype.h>
29 #include <stdio.h>
30 
31 // Qt
32 #include <QtCore/QBuffer>
33 #include <QtCore/QFile>
34 #include <QtCore/QFileInfo>
35 #include <QtCore>
36 #include <QtGui>
37 
38 // FIXME: We should not have a special case for Mac here. Instead, we
39 // should be loading .keytab files at run time, and ideally, allowing
40 // individual keys to be redefined from some preferences menu.
41 
42 //and this is default now translator - default.keytab from original Konsole
44 #if defined (Q_OS_MAC)
46 #else
48 #endif
49 ;
50 
52  : _haveLoadedAll(false)
53 {
54 }
56 {
57  qDeleteAll(_translators.values());
58 }
60 {
61  return QString("kb-layouts/" + name + ".keytab");
62 }
64 {
65  QDir dir("kb-layouts/");
66  QStringList filters;
67  filters << "*.keytab";
68  dir.setNameFilters(filters);
69  QStringList list = dir.entryList(filters); //(".keytab"); // = KGlobal::dirs()->findAllResources("data",
70  // "konsole/*.keytab",
71  // KStandardDirs::NoDuplicates);
72  list = dir.entryList(filters);
73  // add the name of each translator to the list and associated
74  // the name with a null pointer to indicate that the translator
75  // has not yet been loaded from disk
76  QStringListIterator listIter(list);
77  while (listIter.hasNext())
78  {
79  QString translatorPath = listIter.next();
80 
81  QString name = QFileInfo(translatorPath).baseName();
82 
83  if ( !_translators.contains(name) ) {
84  _translators.insert(name,0);
85  }
86  }
87  _haveLoadedAll = true;
88 }
89 
91 {
92  if ( name.isEmpty() )
93  return defaultTranslator();
94 
95  //here was smth wrong in original Konsole source
97 
98  if ( _translators.contains(name) && _translators[name] != 0 ) {
99  return _translators[name];
100  }
101 
102  KeyboardTranslator* translator = loadTranslator(name);
103 
104  if ( translator != 0 )
105  _translators[name] = translator;
106  else if ( !name.isEmpty() )
107  qWarning() << "Unable to load translator" << name;
108 
109  return translator;
110 }
111 
113 {
114  const QString path = ".keytab";// = KGlobal::dirs()->saveLocation("data","konsole/")+translator->name()
115  // +".keytab";
116 
117  qDebug() << "Saving translator to" << path;
118 
119  QFile destination(path);
120 
121  if (!destination.open(QIODevice::WriteOnly | QIODevice::Text))
122  {
123  qWarning() << "Unable to save keyboard translation:"
124  << destination.errorString();
125 
126  return false;
127  }
128 
129  {
130  KeyboardTranslatorWriter writer(&destination);
131  writer.writeHeader(translator->description());
132 
133  QListIterator<KeyboardTranslator::Entry> iter(translator->entries());
134  while ( iter.hasNext() )
135  writer.writeEntry(iter.next());
136  }
137 
138  destination.close();
139 
140  return true;
141 }
142 
144 {
145  const QString& path = findTranslatorPath(name);
146 
147  QFile source(path);
148 
149  if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text))
150  return 0;
151 
152  return loadTranslator(&source,name);
153 }
154 
156 {
157  QBuffer textBuffer;
158  textBuffer.setData(defaultTranslatorText,strlen(defaultTranslatorText));
159 
160  if (!textBuffer.open(QIODevice::ReadOnly))
161  return 0;
162 
163  return loadTranslator(&textBuffer,"fallback");
164 }
165 
166 KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(QIODevice* source,const QString& name)
167 {
168  KeyboardTranslator* translator = new KeyboardTranslator(name);
169  KeyboardTranslatorReader reader(source);
170  translator->setDescription( reader.description() );
171 
172  while ( reader.hasNextEntry() ) {
173  translator->addEntry(reader.nextEntry());
174  }
175 
176  source->close();
177 
178  if ( !reader.parseError() )
179  {
180  return translator;
181  }
182  else
183  {
184  delete translator;
185  return 0;
186  }
187 }
188 
190  : _destination(destination)
191 {
192  Q_ASSERT( destination && destination->isWritable() );
193 
194  _writer = new QTextStream(_destination);
195 }
197 {
198  delete _writer;
199 }
200 void KeyboardTranslatorWriter::writeHeader( const QString& description )
201 {
202  *_writer << "keyboard \"" << description << '\"' << '\n';
203 }
205 {
206  QString result;
207 
208  if ( entry.command() != KeyboardTranslator::NoCommand )
209  result = entry.resultToString();
210  else
211  result = '\"' + entry.resultToString() + '\"';
212 
213  *_writer << "key " << entry.conditionToString() << " : " << result << '\n';
214 }
215 
216 
217 // each line of the keyboard translation file is one of:
218 //
219 // - keyboard "name"
220 // - key KeySequence : "characters"
221 // - key KeySequence : CommandName
222 //
223 // KeySequence begins with the name of the key ( taken from the Qt::Key enum )
224 // and is followed by the keyboard modifiers and state flags ( with + or - in front
225 // of each modifier or flag to indicate whether it is required ). All keyboard modifiers
226 // and flags are optional, if a particular modifier or state is not specified it is
227 // assumed not to be a part of the sequence. The key sequence may contain whitespace
228 //
229 // eg: "key Up+Shift : scrollLineUp"
230 // "key Next-Shift : "\E[6~"
231 //
232 // (lines containing only whitespace are ignored, parseLine assumes that comments have
233 // already been removed)
234 //
235 
237  : _source(source)
238  , _hasNext(false)
239 {
240  // read input until we find the description
241  while ( _description.isEmpty() && !source->atEnd() )
242  {
243  const QList<Token>& tokens = tokenize( QString(source->readLine()) );
244 
245  if ( !tokens.isEmpty() && tokens.first().type == Token::TitleKeyword )
246  {
247  _description = (tokens[1].text.toUtf8());
248  }
249  }
250 
251  readNext();
252 }
254 {
255  // find next entry
256  while ( !_source->atEnd() )
257  {
258  const QList<Token>& tokens = tokenize( QString(_source->readLine()) );
259  if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword )
260  {
261  KeyboardTranslator::States flags = KeyboardTranslator::NoState;
262  KeyboardTranslator::States flagMask = KeyboardTranslator::NoState;
263  Qt::KeyboardModifiers modifiers = Qt::NoModifier;
264  Qt::KeyboardModifiers modifierMask = Qt::NoModifier;
265 
266  int keyCode = Qt::Key_unknown;
267 
268  decodeSequence(tokens[1].text.toLower(),
269  keyCode,
270  modifiers,
271  modifierMask,
272  flags,
273  flagMask);
274 
276  QByteArray text;
277 
278  // get text or command
279  if ( tokens[2].type == Token::OutputText )
280  {
281  text = tokens[2].text.toLocal8Bit();
282  }
283  else if ( tokens[2].type == Token::Command )
284  {
285  // identify command
286  if (!parseAsCommand(tokens[2].text,command))
287  qWarning() << "Command" << tokens[2].text << "not understood.";
288  }
289 
290  KeyboardTranslator::Entry newEntry;
291  newEntry.setKeyCode( keyCode );
292  newEntry.setState( flags );
293  newEntry.setStateMask( flagMask );
294  newEntry.setModifiers( modifiers );
295  newEntry.setModifierMask( modifierMask );
296  newEntry.setText( text );
297  newEntry.setCommand( command );
298 
299  _nextEntry = newEntry;
300 
301  _hasNext = true;
302 
303  return;
304  }
305  }
306 
307  _hasNext = false;
308 }
309 
311 {
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 )
324  else
325  return false;
326 
327  return true;
328 }
329 
331  int& keyCode,
332  Qt::KeyboardModifiers& modifiers,
333  Qt::KeyboardModifiers& modifierMask,
334  KeyboardTranslator::States& flags,
335  KeyboardTranslator::States& flagMask)
336 {
337  bool isWanted = true;
338  bool endOfItem = false;
339  QString buffer;
340 
341  Qt::KeyboardModifiers tempModifiers = modifiers;
342  Qt::KeyboardModifiers tempModifierMask = modifierMask;
343  KeyboardTranslator::States tempFlags = flags;
344  KeyboardTranslator::States tempFlagMask = flagMask;
345 
346  for ( int i = 0 ; i < text.count() ; i++ )
347  {
348  const QChar& ch = text[i];
349  bool isLastLetter = ( i == text.count()-1 );
350 
351  endOfItem = true;
352  if ( ch.isLetterOrNumber() )
353  {
354  endOfItem = false;
355  buffer.append(ch);
356  }
357 
358  if ( (endOfItem || isLastLetter) && !buffer.isEmpty() )
359  {
360  Qt::KeyboardModifier itemModifier = Qt::NoModifier;
361  int itemKeyCode = 0;
363 
364  if ( parseAsModifier(buffer,itemModifier) )
365  {
366  tempModifierMask |= itemModifier;
367 
368  if ( isWanted )
369  tempModifiers |= itemModifier;
370  }
371  else if ( parseAsStateFlag(buffer,itemFlag) )
372  {
373  tempFlagMask |= itemFlag;
374 
375  if ( isWanted )
376  tempFlags |= itemFlag;
377  }
378  else if ( parseAsKeyCode(buffer,itemKeyCode) )
379  keyCode = itemKeyCode;
380  else
381  qDebug() << "Unable to parse key binding item:" << buffer;
382 
383  buffer.clear();
384  }
385 
386  // check if this is a wanted / not-wanted flag and update the
387  // state ready for the next item
388  if ( ch == '+' )
389  isWanted = true;
390  else if ( ch == '-' )
391  isWanted = false;
392  }
393 
394  modifiers = tempModifiers;
395  modifierMask = tempModifierMask;
396  flags = tempFlags;
397  flagMask = tempFlagMask;
398 
399  return true;
400 }
401 
402 bool KeyboardTranslatorReader::parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier)
403 {
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;
414  else
415  return false;
416 
417  return true;
418 }
420 {
421  if ( item == "appcukeys" )
423  else if ( item == "ansi" )
425  else if ( item == "newline" )
427  else if ( item == "appscreen" )
429  else if ( item == "anymod" )
431  else
432  return false;
433 
434  return true;
435 }
436 bool KeyboardTranslatorReader::parseAsKeyCode(const QString& item , int& keyCode)
437 {
438  QKeySequence sequence = QKeySequence::fromString(item);
439  if ( !sequence.isEmpty() )
440  {
441  keyCode = sequence[0];
442 
443  if ( sequence.count() > 1 )
444  {
445  qDebug() << "Unhandled key codes in sequence: " << item;
446  }
447  }
448  // additional cases implemented for backwards compatibility with KDE 3
449  else if ( item == "prior" )
450  keyCode = Qt::Key_PageUp;
451  else if ( item == "next" )
452  keyCode = Qt::Key_PageDown;
453  else
454  return false;
455 
456  return true;
457 }
458 
460 {
461  return _description;
462 }
464 {
465  return _hasNext;
466 }
468  const QString& result )
469 {
470  QString entryString("keyboard \"temporary\"\nkey ");
471  entryString.append(condition);
472  entryString.append(" : ");
473 
474  // if 'result' is the name of a command then the entry result will be that command,
475  // otherwise the result will be treated as a string to echo when the key sequence
476  // specified by 'condition' is pressed
478  if (parseAsCommand(result,command))
479  entryString.append(result);
480  else
481  entryString.append('\"' + result + '\"');
482 
483  QByteArray array = entryString.toUtf8();
484 
486 
487  QBuffer buffer(&array);
488  buffer.open(QIODevice::ReadOnly);
489  KeyboardTranslatorReader reader(&buffer);
490 
491  if ( reader.hasNextEntry() )
492  entry = reader.nextEntry();
493 
494  return entry;
495 }
496 
498 {
499  Q_ASSERT( _hasNext );
500 
501 
503 
504  readNext();
505 
506  return entry;
507 }
509 {
510  return false;
511 }
513 {
514  QString text = line.simplified();
515 
516  // comment line: # comment
517  static QRegExp comment("\\#.*");
518  // title line: keyboard "title"
519  static QRegExp title("keyboard\\s+\"(.*)\"");
520  // key line: key KeySequence : "output"
521  // key line: key KeySequence : command
522  static QRegExp key("key\\s+([\\w\\+\\s\\-]+)\\s*:\\s*(\"(.*)\"|\\w+)");
523 
524  QList<Token> list;
525 
526  if ( text.isEmpty() || comment.exactMatch(text) )
527  {
528  return list;
529  }
530 
531  if ( title.exactMatch(text) )
532  {
533  Token titleToken = { Token::TitleKeyword , QString() };
534  Token textToken = { Token::TitleText , title.capturedTexts()[1] };
535 
536  list << titleToken << textToken;
537  }
538  else if ( key.exactMatch(text) )
539  {
540  Token keyToken = { Token::KeyKeyword , QString() };
541  Token sequenceToken = { Token::KeySequence , key.capturedTexts()[1].remove(' ') };
542 
543  list << keyToken << sequenceToken;
544 
545  if ( key.capturedTexts()[3].isEmpty() )
546  {
547  // capturedTexts()[2] is a command
548  Token commandToken = { Token::Command , key.capturedTexts()[2] };
549  list << commandToken;
550  }
551  else
552  {
553  // capturedTexts()[3] is the output string
554  Token outputToken = { Token::OutputText , key.capturedTexts()[3] };
555  list << outputToken;
556  }
557  }
558  else
559  {
560  qWarning() << "Line in keyboard translator file could not be understood:" << text;
561  }
562 
563  return list;
564 }
565 
567 {
568  if ( !_haveLoadedAll )
569  {
570  findTranslators();
571  }
572 
573  return _translators.keys();
574 }
575 
577  : _keyCode(0)
578  , _modifiers(Qt::NoModifier)
579  , _modifierMask(Qt::NoModifier)
580  , _state(NoState)
581  , _stateMask(NoState)
582  , _command(NoCommand)
583 {
584 }
585 
587 {
588  return _keyCode == rhs._keyCode &&
589  _modifiers == rhs._modifiers &&
590  _modifierMask == rhs._modifierMask &&
591  _state == rhs._state &&
592  _stateMask == rhs._stateMask &&
593  _command == rhs._command &&
594  _text == rhs._text;
595 }
596 
598  Qt::KeyboardModifiers modifiers,
599  States state) const
600 {
601  if ( _keyCode != keyCode )
602  return false;
603 
604  if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) )
605  return false;
606 
607  // if modifiers is non-zero, the 'any modifier' state is implicit
608  if ( modifiers != 0 )
609  state |= AnyModifierState;
610 
611  if ( (state & _stateMask) != (_state & _stateMask) )
612  return false;
613 
614  // special handling for the 'Any Modifier' state, which checks for the presence of
615  // any or no modifiers. In this context, the 'keypad' modifier does not count.
616  bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;
617  if ( _stateMask & KeyboardTranslator::AnyModifierState )
618  {
619  // test fails if any modifier is required but none are set
620  if ( (_state & KeyboardTranslator::AnyModifierState) && !anyModifiersSet )
621  return false;
622 
623  // test fails if no modifier is allowed but one or more are set
624  if ( !(_state & KeyboardTranslator::AnyModifierState) && anyModifiersSet )
625  return false;
626  }
627 
628  return true;
629 }
630 QByteArray KeyboardTranslator::Entry::escapedText(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
631 {
632  QByteArray result(text(expandWildCards,modifiers));
633 
634  for ( int i = 0 ; i < result.count() ; i++ )
635  {
636  char ch = result[i];
637  char replacement = 0;
638 
639  switch ( ch )
640  {
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;
647  default:
648  // any character which is not printable is replaced by an equivalent
649  // \xhh escape sequence (where 'hh' are the corresponding hex digits)
650  if ( !QChar(ch).isPrint() )
651  replacement = 'x';
652  }
653 
654  if ( replacement == 'x' )
655  {
656  result.replace(i,1,"\\x"+QByteArray(1,ch).toInt(0, 16));
657  } else if ( replacement != 0 )
658  {
659  result.remove(i,1);
660  result.insert(i,'\\');
661  result.insert(i+1,replacement);
662  }
663  }
664 
665  return result;
666 }
667 QByteArray KeyboardTranslator::Entry::unescape(const QByteArray& input) const
668 {
669  QByteArray result(input);
670 
671  for ( int i = 0 ; i < result.count()-1 ; i++ )
672  {
673 
674  QByteRef ch = result[i];
675  if ( ch == '\\' )
676  {
677  char replacement[2] = {0,0};
678  int charsToRemove = 2;
679  bool escapedChar = true;
680 
681  switch ( result[i+1] )
682  {
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;
689  case 'x' :
690  {
691  // format is \xh or \xhh where 'h' is a hexadecimal
692  // digit from 0-9 or A-F which should be replaced
693  // with the corresponding character value
694  char hexDigits[3] = {0};
695 
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];
700 
701  int charValue = 0;
702  sscanf(hexDigits,"%x",&charValue);
703 
704  replacement[0] = (char)charValue;
705 
706  charsToRemove = 2 + strlen(hexDigits);
707  }
708  break;
709  default:
710  escapedChar = false;
711  }
712 
713  if ( escapedChar )
714  result.replace(i,charsToRemove,replacement);
715  }
716  }
717 
718  return result;
719 }
720 
721 void KeyboardTranslator::Entry::insertModifier( QString& item , int modifier ) const
722 {
723  if ( !(modifier & _modifierMask) )
724  return;
725 
726  if ( modifier & _modifiers )
727  item += '+';
728  else
729  item += '-';
730 
731  if ( modifier == Qt::ShiftModifier )
732  item += "Shift";
733  else if ( modifier == Qt::ControlModifier )
734  item += "Ctrl";
735  else if ( modifier == Qt::AltModifier )
736  item += "Alt";
737  else if ( modifier == Qt::MetaModifier )
738  item += "Meta";
739  else if ( modifier == Qt::KeypadModifier )
740  item += "KeyPad";
741 }
742 void KeyboardTranslator::Entry::insertState( QString& item , int state ) const
743 {
744  if ( !(state & _stateMask) )
745  return;
746 
747  if ( state & _state )
748  item += '+' ;
749  else
750  item += '-' ;
751 
753  item += "AppScreen";
754  else if ( state == KeyboardTranslator::NewLineState )
755  item += "NewLine";
756  else if ( state == KeyboardTranslator::AnsiState )
757  item += "Ansi";
758  else if ( state == KeyboardTranslator::CursorKeysState )
759  item += "AppCuKeys";
760  else if ( state == KeyboardTranslator::AnyModifierState )
761  item += "AnyMod";
762 }
763 QString KeyboardTranslator::Entry::resultToString(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
764 {
765  if ( !_text.isEmpty() )
766  return escapedText(expandWildCards,modifiers);
767  else if ( _command == EraseCommand )
768  return "Erase";
769  else if ( _command == ScrollPageUpCommand )
770  return "ScrollPageUp";
771  else if ( _command == ScrollPageDownCommand )
772  return "ScrollPageDown";
773  else if ( _command == ScrollLineUpCommand )
774  return "ScrollLineUp";
775  else if ( _command == ScrollLineDownCommand )
776  return "ScrollLineDown";
777  else if ( _command == ScrollLockCommand )
778  return "ScrollLock";
779 
780  return QString();
781 }
783 {
784  QString result = QKeySequence(_keyCode).toString();
785 
786  // add modifiers
787  insertModifier( result , Qt::ShiftModifier );
788  insertModifier( result , Qt::ControlModifier );
789  insertModifier( result , Qt::AltModifier );
790  insertModifier( result , Qt::MetaModifier );
791 
792  // add states
793  insertState( result , KeyboardTranslator::AlternateScreenState );
794  insertState( result , KeyboardTranslator::NewLineState );
795  insertState( result , KeyboardTranslator::AnsiState );
796  insertState( result , KeyboardTranslator::CursorKeysState );
797  insertState( result , KeyboardTranslator::AnyModifierState );
798 
799  return result;
800 }
801 
803  : _name(name)
804 {
805 }
806 
807 void KeyboardTranslator::setDescription(const QString& description)
808 {
810 }
812 {
813  return _description;
814 }
815 void KeyboardTranslator::setName(const QString& name)
816 {
817  _name = name;
818 }
820 {
821  return _name;
822 }
823 
825 {
826  return _entries.values();
827 }
828 
830 {
831  const int keyCode = entry.keyCode();
832  _entries.insertMulti(keyCode,entry);
833 }
834 void KeyboardTranslator::replaceEntry(const Entry& existing , const Entry& replacement)
835 {
836  if ( !existing.isNull() )
837  _entries.remove(existing.keyCode());
838  _entries.insertMulti(replacement.keyCode(),replacement);
839 }
841 {
842  _entries.remove(entry.keyCode());
843 }
844 KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const
845 {
846  if ( _entries.contains(keyCode) )
847  {
848  QList<Entry> entriesForKey = _entries.values(keyCode);
849 
850  QListIterator<Entry> iter(entriesForKey);
851 
852  while (iter.hasNext())
853  {
854  const Entry& next = iter.next();
855  if ( next.matches(keyCode,modifiers,state) )
856  return next;
857  }
858 
859  return Entry(); // entry not found
860  }
861  else
862  {
863  return Entry();
864  }
865 
866 }
868 {
869  _translators.insert(translator->name(),translator);
870 
871  if ( !saveTranslator(translator) )
872  qWarning() << "Unable to save translator" << translator->name()
873  << "to disk.";
874 }
876 {
877  Q_ASSERT( _translators.contains(name) );
878 
879  // locate and delete
880  QString path = findTranslatorPath(name);
881  if ( QFile::remove(path) )
882  {
883  _translators.remove(name);
884  return true;
885  }
886  else
887  {
888  qWarning() << "Failed to remove translator - " << path;
889  return false;
890  }
891 }
892 K_GLOBAL_STATIC( KeyboardTranslatorManager , theKeyboardTranslatorManager )
894 {
895  return theKeyboardTranslatorManager;
896 }
void setKeyCode(int keyCode)
Sets the character code associated with this entry.
QHash< int, Entry > _entries
Scroll the terminal display up one page.
static const char * defaultTranslatorText
bool parseError()
Returns true if an error occurred whilst parsing the input or false if no error occurred.
Command
This enum describes commands which are associated with particular key sequences.
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...
Echos the operating system specific erase character.
Qt::KeyboardModifiers _modifierMask
QString resultToString(bool expandWildCards=false, Qt::KeyboardModifiers modifiers=Qt::NoModifier) const
Returns this entry's result ( ie.
Command command() const
Returns the commands associated with this entry.
static uint32_t state[624]
Definition: randmtzig.c:188
void writeHeader(const QString &description)
Writes the header for the keyboard translator.
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...
void insertModifier(QString &item, int modifier) const
void addTranslator(KeyboardTranslator *translator)
Adds a new translator.
bool isNull() const
Returns true if this entry is null.
QString findTranslatorPath(const QString &name)
Entry()
Constructs a new entry for a keyboard translator.
void setModifiers(Qt::KeyboardModifiers modifiers)
See modifiers()
Indicates that no special state is active.
bool deleteTranslator(const QString &name)
Deletes a translator.
bool operator==(const Entry &rhs) const
State
The meaning of a particular key sequence may depend upon the state which the terminal emulation is in...
KeyboardTranslator::Entry nextEntry()
Returns the next entry found in the source stream.
QString description() const
Returns the descriptive name of this keyboard translator.
const KeyboardTranslator * findTranslator(const QString &name)
Returns the keyboard translator with the given name or 0 if no translator with that name exists...
#define K_GLOBAL_STATIC(TYPE, NAME)
void writeEntry(const KeyboardTranslator::Entry &entry)
Writes a translator entry.
static bool parseAsStateFlag(const QString &item, KeyboardTranslator::State &state)
static bool parseAsModifier(const QString &item, Qt::KeyboardModifier &modifier)
void setText(const QByteArray &text)
Sets the character sequence associated with this entry.
KeyboardTranslatorWriter(QIODevice *destination)
Constructs a new writer which saves data into destination.
KeyboardTranslator(const QString &name)
Constructs a new keyboard translator with the given name.
static uint32_t * next
Definition: randmtzig.c:187
QList< QString > allTranslators()
Returns a list of the names of available keyboard translators.
QList< Entry > entries() const
Returns a list of all entries in the translator.
Manages the keyboard translations available for use by terminal sessions, see KeyboardTranslator.
QString description() const
Returns the description text.
Indicates that the alternate screen ( typically used by interactive programs such as screen or vim ) ...
Indicates that the terminal is in 'Ansi' mode.
bool saveTranslator(const KeyboardTranslator *translator)
void setStateMask(States mask)
See stateMask()
void setDescription(const QString &description)
Sets the descriptive name of this keyboard translator.
QList< Token > tokenize(const QString &)
Indicates that no command is associated with this command sequence.
Scroll the terminal display up one line.
void setCommand(Command command)
Sets the command associated with this entry.
void setName(const QString &name)
Sets the name of this keyboard translator.
const KeyboardTranslator * defaultTranslator()
Returns the default translator for Konsole.
A convertor which maps between key sequences pressed by the user and the character strings which shou...
void setModifierMask(Qt::KeyboardModifiers modifiers)
See modifierMask() and modifiers()
QString conditionToString() const
Returns the key code and modifiers associated with this entry as a QKeySequence.
KeyboardTranslator * loadTranslator(const QString &name)
Scroll the terminal display down one line.
Parses the contents of a Keyboard Translator (.keytab) file and returns the entries found in it...
bool hasNextEntry()
Returns true if there is another entry in the source stream.
QString name() const
Returns the name of this keyboard translator.
void setState(States state)
See state()
KeyboardTranslator::Entry _nextEntry
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)
void replaceEntry(const Entry &existing, const Entry &replacement)
Replaces an entry in the translator.
Represents an association between a key sequence pressed by the user and the character sequence and c...
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 ...
Writes a keyboard translation to disk.
KeyboardTranslatorManager()
Constructs a new KeyboardTranslatorManager and loads the list of available keyboard translations...
Indicates that any of the modifier keys is active.
static int input(yyscan_t yyscanner)
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...
static bool parseAsKeyCode(const QString &item, int &keyCode)
QByteArray unescape(const QByteArray &text) const
Scroll the terminal display down one page.
QHash< QString, KeyboardTranslator * > _translators
int keyCode() const
Returns the character code ( from the Qt::Key enum ) associated with this entry.
void removeEntry(const Entry &entry)
Removes an entry from the table.
KeyboardTranslatorReader(QIODevice *source)
Constructs a new reader which parses the given source.
Qt::KeyboardModifiers _modifiers
void insertState(QString &item, int state) const
void addEntry(const Entry &entry)
Adds an entry to this keyboard translator's table.