00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KeyboardTranslator.h"
00024
00025
00026 #include <ctype.h>
00027 #include <stdio.h>
00028
00029
00030 #include <QtCore/QBuffer>
00031 #include <QtCore/QFile>
00032 #include <QtCore/QFileInfo>
00033 #include <QtCore/QTextStream>
00034 #include <QtGui/QKeySequence>
00035
00036
00037 #include <KDebug>
00038 #include <KLocale>
00039 #include <KStandardDirs>
00040
00041 using namespace Konsole;
00042
00043
00044 const char* KeyboardTranslatorManager::defaultTranslatorText =
00045 #include <DefaultTranslatorText.h>
00046 ;
00047
00048 KeyboardTranslatorManager::KeyboardTranslatorManager()
00049 : _haveLoadedAll(false)
00050 {
00051 }
00052 KeyboardTranslatorManager::~KeyboardTranslatorManager()
00053 {
00054 qDeleteAll(_translators);
00055 }
00056 QString KeyboardTranslatorManager::findTranslatorPath(const QString& name)
00057 {
00058 return KGlobal::dirs()->findResource("data","konsole/"+name+".keytab");
00059 }
00060 void KeyboardTranslatorManager::findTranslators()
00061 {
00062 QStringList list = KGlobal::dirs()->findAllResources("data",
00063 "konsole/*.keytab",
00064 KStandardDirs::NoDuplicates);
00065
00066
00067
00068
00069 QStringListIterator listIter(list);
00070 while (listIter.hasNext())
00071 {
00072 QString translatorPath = listIter.next();
00073
00074 QString name = QFileInfo(translatorPath).baseName();
00075
00076 if ( !_translators.contains(name) )
00077 _translators.insert(name,0);
00078 }
00079
00080 _haveLoadedAll = true;
00081 }
00082
00083 const KeyboardTranslator* KeyboardTranslatorManager::findTranslator(const QString& name)
00084 {
00085 if ( name.isEmpty() )
00086 return defaultTranslator();
00087
00088 if ( _translators.contains(name) && _translators[name] != 0 )
00089 return _translators[name];
00090
00091 KeyboardTranslator* translator = loadTranslator(name);
00092
00093 if ( translator != 0 )
00094 _translators[name] = translator;
00095 else if ( !name.isEmpty() )
00096 kWarning() << "Unable to load translator" << name;
00097
00098 return translator;
00099 }
00100
00101 bool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* translator)
00102 {
00103 const QString path = KGlobal::dirs()->saveLocation("data","konsole/")+translator->name()
00104 +".keytab";
00105
00106 kDebug() << "Saving translator to" << path;
00107
00108 QFile destination(path);
00109 if (!destination.open(QIODevice::WriteOnly | QIODevice::Text))
00110 {
00111 kWarning() << "Unable to save keyboard translation:"
00112 << destination.errorString();
00113 return false;
00114 }
00115
00116 {
00117 KeyboardTranslatorWriter writer(&destination);
00118 writer.writeHeader(translator->description());
00119
00120 QListIterator<KeyboardTranslator::Entry> iter(translator->entries());
00121 while ( iter.hasNext() )
00122 writer.writeEntry(iter.next());
00123 }
00124
00125 destination.close();
00126
00127 return true;
00128 }
00129
00130 KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& name)
00131 {
00132 const QString& path = findTranslatorPath(name);
00133
00134 QFile source(path);
00135 if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text))
00136 return 0;
00137
00138 return loadTranslator(&source,name);
00139 }
00140
00141 const KeyboardTranslator* KeyboardTranslatorManager::defaultTranslator()
00142 {
00143 kDebug() << "Loading default translator from text" << defaultTranslatorText;
00144 QBuffer textBuffer;
00145 textBuffer.setData(defaultTranslatorText,strlen(defaultTranslatorText));
00146 return loadTranslator(&textBuffer,"fallback");
00147 }
00148
00149 KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(QIODevice* source,const QString& name)
00150 {
00151 KeyboardTranslator* translator = new KeyboardTranslator(name);
00152 KeyboardTranslatorReader reader(source);
00153 translator->setDescription( reader.description() );
00154 while ( reader.hasNextEntry() )
00155 translator->addEntry(reader.nextEntry());
00156
00157 source->close();
00158
00159 if ( !reader.parseError() )
00160 {
00161 return translator;
00162 }
00163 else
00164 {
00165 delete translator;
00166 return 0;
00167 }
00168 }
00169
00170 KeyboardTranslatorWriter::KeyboardTranslatorWriter(QIODevice* destination)
00171 : _destination(destination)
00172 {
00173 Q_ASSERT( destination && destination->isWritable() );
00174
00175 _writer = new QTextStream(_destination);
00176 }
00177 KeyboardTranslatorWriter::~KeyboardTranslatorWriter()
00178 {
00179 delete _writer;
00180 }
00181 void KeyboardTranslatorWriter::writeHeader( const QString& description )
00182 {
00183 *_writer << "keyboard \"" << description << '\"' << '\n';
00184 }
00185 void KeyboardTranslatorWriter::writeEntry( const KeyboardTranslator::Entry& entry )
00186 {
00187 QString result;
00188 if ( entry.command() != KeyboardTranslator::NoCommand )
00189 result = entry.resultToString();
00190 else
00191 result = '\"' + entry.resultToString() + '\"';
00192
00193 *_writer << "key " << entry.conditionToString() << " : " << result << '\n';
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 KeyboardTranslatorReader::KeyboardTranslatorReader( QIODevice* source )
00217 : _source(source)
00218 , _hasNext(false)
00219 {
00220
00221 while ( _description.isEmpty() && !source->atEnd() )
00222 {
00223 QList<Token> tokens = tokenize( QString(source->readLine()) );
00224 if ( !tokens.isEmpty() && tokens.first().type == Token::TitleKeyword )
00225 _description = i18n(tokens[1].text.toUtf8());
00226 }
00227
00228 readNext();
00229 }
00230 void KeyboardTranslatorReader::readNext()
00231 {
00232
00233 while ( !_source->atEnd() )
00234 {
00235 const QList<Token>& tokens = tokenize( QString(_source->readLine()) );
00236 if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword )
00237 {
00238 KeyboardTranslator::States flags = KeyboardTranslator::NoState;
00239 KeyboardTranslator::States flagMask = KeyboardTranslator::NoState;
00240 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
00241 Qt::KeyboardModifiers modifierMask = Qt::NoModifier;
00242
00243 int keyCode = Qt::Key_unknown;
00244
00245 decodeSequence(tokens[1].text.toLower(),
00246 keyCode,
00247 modifiers,
00248 modifierMask,
00249 flags,
00250 flagMask);
00251
00252 KeyboardTranslator::Command command = KeyboardTranslator::NoCommand;
00253 QByteArray text;
00254
00255
00256 if ( tokens[2].type == Token::OutputText )
00257 {
00258 text = tokens[2].text.toLocal8Bit();
00259 }
00260 else if ( tokens[2].type == Token::Command )
00261 {
00262
00263 if (!parseAsCommand(tokens[2].text,command))
00264 kWarning() << "Command" << tokens[2].text << "not understood.";
00265 }
00266
00267 KeyboardTranslator::Entry newEntry;
00268 newEntry.setKeyCode( keyCode );
00269 newEntry.setState( flags );
00270 newEntry.setStateMask( flagMask );
00271 newEntry.setModifiers( modifiers );
00272 newEntry.setModifierMask( modifierMask );
00273 newEntry.setText( text );
00274 newEntry.setCommand( command );
00275
00276 _nextEntry = newEntry;
00277
00278 _hasNext = true;
00279
00280 return;
00281 }
00282 }
00283
00284 _hasNext = false;
00285 }
00286
00287 bool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTranslator::Command& command)
00288 {
00289 if ( text.compare("erase",Qt::CaseInsensitive) == 0 )
00290 command = KeyboardTranslator::EraseCommand;
00291 else if ( text.compare("scrollpageup",Qt::CaseInsensitive) == 0 )
00292 command = KeyboardTranslator::ScrollPageUpCommand;
00293 else if ( text.compare("scrollpagedown",Qt::CaseInsensitive) == 0 )
00294 command = KeyboardTranslator::ScrollPageDownCommand;
00295 else if ( text.compare("scrolllineup",Qt::CaseInsensitive) == 0 )
00296 command = KeyboardTranslator::ScrollLineUpCommand;
00297 else if ( text.compare("scrolllinedown",Qt::CaseInsensitive) == 0 )
00298 command = KeyboardTranslator::ScrollLineDownCommand;
00299 else if ( text.compare("scrolllock",Qt::CaseInsensitive) == 0 )
00300 command = KeyboardTranslator::ScrollLockCommand;
00301 else
00302 return false;
00303
00304 return true;
00305 }
00306
00307 bool KeyboardTranslatorReader::decodeSequence(const QString& text,
00308 int& keyCode,
00309 Qt::KeyboardModifiers& modifiers,
00310 Qt::KeyboardModifiers& modifierMask,
00311 KeyboardTranslator::States& flags,
00312 KeyboardTranslator::States& flagMask)
00313 {
00314 bool isWanted = true;
00315 bool endOfItem = false;
00316 QString buffer;
00317
00318 Qt::KeyboardModifiers tempModifiers = modifiers;
00319 Qt::KeyboardModifiers tempModifierMask = modifierMask;
00320 KeyboardTranslator::States tempFlags = flags;
00321 KeyboardTranslator::States tempFlagMask = flagMask;
00322
00323 for ( int i = 0 ; i < text.count() ; i++ )
00324 {
00325 const QChar& ch = text[i];
00326 bool isFirstLetter = i == 0;
00327 bool isLastLetter = ( i == text.count()-1 );
00328 endOfItem = true;
00329 if ( ch.isLetterOrNumber() )
00330 {
00331 endOfItem = false;
00332 buffer.append(ch);
00333 } else if ( isFirstLetter )
00334 {
00335 buffer.append(ch);
00336 }
00337
00338 if ( (endOfItem || isLastLetter) && !buffer.isEmpty() )
00339 {
00340 Qt::KeyboardModifier itemModifier = Qt::NoModifier;
00341 int itemKeyCode = 0;
00342 KeyboardTranslator::State itemFlag = KeyboardTranslator::NoState;
00343
00344 if ( parseAsModifier(buffer,itemModifier) )
00345 {
00346 tempModifierMask |= itemModifier;
00347
00348 if ( isWanted )
00349 tempModifiers |= itemModifier;
00350 }
00351 else if ( parseAsStateFlag(buffer,itemFlag) )
00352 {
00353 tempFlagMask |= itemFlag;
00354
00355 if ( isWanted )
00356 tempFlags |= itemFlag;
00357 }
00358 else if ( parseAsKeyCode(buffer,itemKeyCode) )
00359 keyCode = itemKeyCode;
00360 else
00361 kDebug() << "Unable to parse key binding item:" << buffer;
00362
00363 buffer.clear();
00364 }
00365
00366
00367
00368 if ( ch == '+' )
00369 isWanted = true;
00370 else if ( ch == '-' )
00371 isWanted = false;
00372 }
00373
00374 modifiers = tempModifiers;
00375 modifierMask = tempModifierMask;
00376 flags = tempFlags;
00377 flagMask = tempFlagMask;
00378
00379 return true;
00380 }
00381
00382 bool KeyboardTranslatorReader::parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier)
00383 {
00384 if ( item == "shift" )
00385 modifier = Qt::ShiftModifier;
00386 else if ( item == "ctrl" || item == "control" )
00387 modifier = Qt::ControlModifier;
00388 else if ( item == "alt" )
00389 modifier = Qt::AltModifier;
00390 else if ( item == "meta" )
00391 modifier = Qt::MetaModifier;
00392 else if ( item == "keypad" )
00393 modifier = Qt::KeypadModifier;
00394 else
00395 return false;
00396
00397 return true;
00398 }
00399 bool KeyboardTranslatorReader::parseAsStateFlag(const QString& item , KeyboardTranslator::State& flag)
00400 {
00401 if ( item == "appcukeys" || item == "appcursorkeys" )
00402 flag = KeyboardTranslator::CursorKeysState;
00403 else if ( item == "ansi" )
00404 flag = KeyboardTranslator::AnsiState;
00405 else if ( item == "newline" )
00406 flag = KeyboardTranslator::NewLineState;
00407 else if ( item == "appscreen" )
00408 flag = KeyboardTranslator::AlternateScreenState;
00409 else if ( item == "anymod" || item == "anymodifier" )
00410 flag = KeyboardTranslator::AnyModifierState;
00411 else if ( item == "appkeypad" )
00412 flag = KeyboardTranslator::ApplicationKeypadState;
00413 else
00414 return false;
00415
00416 return true;
00417 }
00418 bool KeyboardTranslatorReader::parseAsKeyCode(const QString& item , int& keyCode)
00419 {
00420 QKeySequence sequence = QKeySequence::fromString(item);
00421 if ( !sequence.isEmpty() )
00422 {
00423 keyCode = sequence[0];
00424
00425 if ( sequence.count() > 1 )
00426 {
00427 kDebug() << "Unhandled key codes in sequence: " << item;
00428 }
00429 }
00430
00431 else if ( item == "prior" )
00432 keyCode = Qt::Key_PageUp;
00433 else if ( item == "next" )
00434 keyCode = Qt::Key_PageDown;
00435 else
00436 return false;
00437
00438 return true;
00439 }
00440
00441 QString KeyboardTranslatorReader::description() const
00442 {
00443 return _description;
00444 }
00445 bool KeyboardTranslatorReader::hasNextEntry()
00446 {
00447 return _hasNext;
00448 }
00449 KeyboardTranslator::Entry KeyboardTranslatorReader::createEntry( const QString& condition ,
00450 const QString& result )
00451 {
00452 QString entryString("keyboard \"temporary\"\nkey ");
00453 entryString.append(condition);
00454 entryString.append(" : ");
00455
00456
00457
00458
00459 KeyboardTranslator::Command command;
00460 if (parseAsCommand(result,command))
00461 entryString.append(result);
00462 else
00463 entryString.append('\"' + result + '\"');
00464
00465 QByteArray array = entryString.toUtf8();
00466 QBuffer buffer(&array);
00467 buffer.open(QIODevice::ReadOnly);
00468 KeyboardTranslatorReader reader(&buffer);
00469
00470 KeyboardTranslator::Entry entry;
00471 if ( reader.hasNextEntry() )
00472 entry = reader.nextEntry();
00473
00474 return entry;
00475 }
00476
00477 KeyboardTranslator::Entry KeyboardTranslatorReader::nextEntry()
00478 {
00479 Q_ASSERT( _hasNext );
00480 KeyboardTranslator::Entry entry = _nextEntry;
00481 readNext();
00482 return entry;
00483 }
00484 bool KeyboardTranslatorReader::parseError()
00485 {
00486 return false;
00487 }
00488 QList<KeyboardTranslatorReader::Token> KeyboardTranslatorReader::tokenize(const QString& line)
00489 {
00490 QString text = line;
00491
00492
00493 bool inQuotes = false;
00494 int commentPos = -1;
00495 for (int i=text.length()-1;i>=0;i--)
00496 {
00497 QChar ch = text[i];
00498 if (ch == '\"')
00499 inQuotes = !inQuotes;
00500 else if (ch == '#' && !inQuotes)
00501 commentPos = i;
00502 }
00503 if (commentPos != -1)
00504 text.remove(commentPos,text.length());
00505
00506 text = text.simplified();
00507
00508
00509 static QRegExp title("keyboard\\s+\"(.*)\"");
00510
00511
00512 static QRegExp key("key\\s+([\\w\\+\\s\\-\\*\\.]+)\\s*:\\s*(\"(.*)\"|\\w+)");
00513
00514 QList<Token> list;
00515 if ( text.isEmpty() )
00516 {
00517 return list;
00518 }
00519
00520 if ( title.exactMatch(text) )
00521 {
00522 Token titleToken = { Token::TitleKeyword , QString() };
00523 Token textToken = { Token::TitleText , title.capturedTexts()[1] };
00524
00525 list << titleToken << textToken;
00526 }
00527 else if ( key.exactMatch(text) )
00528 {
00529 Token keyToken = { Token::KeyKeyword , QString() };
00530 Token sequenceToken = { Token::KeySequence , key.capturedTexts()[1].remove(' ') };
00531
00532 list << keyToken << sequenceToken;
00533
00534 if ( key.capturedTexts()[3].isEmpty() )
00535 {
00536
00537 Token commandToken = { Token::Command , key.capturedTexts()[2] };
00538 list << commandToken;
00539 }
00540 else
00541 {
00542
00543 Token outputToken = { Token::OutputText , key.capturedTexts()[3] };
00544 list << outputToken;
00545 }
00546 }
00547 else
00548 {
00549 kWarning() << "Line in keyboard translator file could not be understood:" << text;
00550 }
00551
00552 return list;
00553 }
00554
00555 QList<QString> KeyboardTranslatorManager::allTranslators()
00556 {
00557 if ( !_haveLoadedAll )
00558 {
00559 findTranslators();
00560 }
00561
00562 return _translators.keys();
00563 }
00564
00565 KeyboardTranslator::Entry::Entry()
00566 : _keyCode(0)
00567 , _modifiers(Qt::NoModifier)
00568 , _modifierMask(Qt::NoModifier)
00569 , _state(NoState)
00570 , _stateMask(NoState)
00571 , _command(NoCommand)
00572 {
00573 }
00574
00575 bool KeyboardTranslator::Entry::operator==(const Entry& rhs) const
00576 {
00577 return _keyCode == rhs._keyCode &&
00578 _modifiers == rhs._modifiers &&
00579 _modifierMask == rhs._modifierMask &&
00580 _state == rhs._state &&
00581 _stateMask == rhs._stateMask &&
00582 _command == rhs._command &&
00583 _text == rhs._text;
00584 }
00585
00586 bool KeyboardTranslator::Entry::matches(int keyCode ,
00587 Qt::KeyboardModifiers modifiers,
00588 States testState) const
00589 {
00590 if ( _keyCode != keyCode )
00591 return false;
00592
00593 if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) )
00594 return false;
00595
00596
00597 if ( modifiers != 0 )
00598 testState |= AnyModifierState;
00599
00600 if ( (testState & _stateMask) != (_state & _stateMask) )
00601 return false;
00602
00603
00604
00605 bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;
00606 bool wantAnyModifier = _state & KeyboardTranslator::AnyModifierState;
00607 if ( _stateMask & KeyboardTranslator::AnyModifierState )
00608 {
00609 if ( wantAnyModifier != anyModifiersSet )
00610 return false;
00611 }
00612
00613 return true;
00614 }
00615 QByteArray KeyboardTranslator::Entry::escapedText(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
00616 {
00617 QByteArray result(text(expandWildCards,modifiers));
00618
00619 for ( int i = 0 ; i < result.count() ; i++ )
00620 {
00621 char ch = result[i];
00622 char replacement = 0;
00623
00624 switch ( ch )
00625 {
00626 case 27 : replacement = 'E'; break;
00627 case 8 : replacement = 'b'; break;
00628 case 12 : replacement = 'f'; break;
00629 case 9 : replacement = 't'; break;
00630 case 13 : replacement = 'r'; break;
00631 case 10 : replacement = 'n'; break;
00632 default:
00633
00634
00635 if ( !QChar(ch).isPrint() )
00636 replacement = 'x';
00637 }
00638
00639 if ( replacement == 'x' )
00640 {
00641 result.replace(i,1,"\\x"+QByteArray(1,ch).toHex());
00642 } else if ( replacement != 0 )
00643 {
00644 result.remove(i,1);
00645 result.insert(i,'\\');
00646 result.insert(i+1,replacement);
00647 }
00648 }
00649
00650 return result;
00651 }
00652 QByteArray KeyboardTranslator::Entry::unescape(const QByteArray& input) const
00653 {
00654 QByteArray result(input);
00655
00656 for ( int i = 0 ; i < result.count()-1 ; i++ )
00657 {
00658
00659 QByteRef ch = result[i];
00660 if ( ch == '\\' )
00661 {
00662 char replacement[2] = {0,0};
00663 int charsToRemove = 2;
00664 bool escapedChar = true;
00665
00666 switch ( result[i+1] )
00667 {
00668 case 'E' : replacement[0] = 27; break;
00669 case 'b' : replacement[0] = 8 ; break;
00670 case 'f' : replacement[0] = 12; break;
00671 case 't' : replacement[0] = 9 ; break;
00672 case 'r' : replacement[0] = 13; break;
00673 case 'n' : replacement[0] = 10; break;
00674 case 'x' :
00675 {
00676
00677
00678
00679 char hexDigits[3] = {0};
00680
00681 if ( (i < result.count()-2) && isxdigit(result[i+2]) )
00682 hexDigits[0] = result[i+2];
00683 if ( (i < result.count()-3) && isxdigit(result[i+3]) )
00684 hexDigits[1] = result[i+3];
00685
00686 unsigned charValue = 0;
00687 sscanf(hexDigits,"%x",&charValue);
00688
00689 replacement[0] = (char)charValue;
00690 charsToRemove = 2 + strlen(hexDigits);
00691 }
00692 break;
00693 default:
00694 escapedChar = false;
00695 }
00696
00697 if ( escapedChar )
00698 result.replace(i,charsToRemove,replacement);
00699 }
00700 }
00701
00702 return result;
00703 }
00704
00705 void KeyboardTranslator::Entry::insertModifier( QString& item , int modifier ) const
00706 {
00707 if ( !(modifier & _modifierMask) )
00708 return;
00709
00710 if ( modifier & _modifiers )
00711 item += '+';
00712 else
00713 item += '-';
00714
00715 if ( modifier == Qt::ShiftModifier )
00716 item += "Shift";
00717 else if ( modifier == Qt::ControlModifier )
00718 item += "Ctrl";
00719 else if ( modifier == Qt::AltModifier )
00720 item += "Alt";
00721 else if ( modifier == Qt::MetaModifier )
00722 item += "Meta";
00723 else if ( modifier == Qt::KeypadModifier )
00724 item += "KeyPad";
00725 }
00726 void KeyboardTranslator::Entry::insertState( QString& item , int state ) const
00727 {
00728 if ( !(state & _stateMask) )
00729 return;
00730
00731 if ( state & _state )
00732 item += '+' ;
00733 else
00734 item += '-' ;
00735
00736 if ( state == KeyboardTranslator::AlternateScreenState )
00737 item += "AppScreen";
00738 else if ( state == KeyboardTranslator::NewLineState )
00739 item += "NewLine";
00740 else if ( state == KeyboardTranslator::AnsiState )
00741 item += "Ansi";
00742 else if ( state == KeyboardTranslator::CursorKeysState )
00743 item += "AppCursorKeys";
00744 else if ( state == KeyboardTranslator::AnyModifierState )
00745 item += "AnyModifier";
00746 else if ( state == KeyboardTranslator::ApplicationKeypadState )
00747 item += "AppKeypad";
00748 }
00749 QString KeyboardTranslator::Entry::resultToString(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
00750 {
00751 if ( !_text.isEmpty() )
00752 return escapedText(expandWildCards,modifiers);
00753 else if ( _command == EraseCommand )
00754 return "Erase";
00755 else if ( _command == ScrollPageUpCommand )
00756 return "ScrollPageUp";
00757 else if ( _command == ScrollPageDownCommand )
00758 return "ScrollPageDown";
00759 else if ( _command == ScrollLineUpCommand )
00760 return "ScrollLineUp";
00761 else if ( _command == ScrollLineDownCommand )
00762 return "ScrollLineDown";
00763 else if ( _command == ScrollLockCommand )
00764 return "ScrollLock";
00765
00766 return QString();
00767 }
00768 QString KeyboardTranslator::Entry::conditionToString() const
00769 {
00770 QString result = QKeySequence(_keyCode).toString();
00771
00772 insertModifier( result , Qt::ShiftModifier );
00773 insertModifier( result , Qt::ControlModifier );
00774 insertModifier( result , Qt::AltModifier );
00775 insertModifier( result , Qt::MetaModifier );
00776 insertModifier( result , Qt::KeypadModifier );
00777
00778 insertState( result , KeyboardTranslator::AlternateScreenState );
00779 insertState( result , KeyboardTranslator::NewLineState );
00780 insertState( result , KeyboardTranslator::AnsiState );
00781 insertState( result , KeyboardTranslator::CursorKeysState );
00782 insertState( result , KeyboardTranslator::AnyModifierState );
00783 insertState( result , KeyboardTranslator::ApplicationKeypadState );
00784
00785 return result;
00786 }
00787
00788 KeyboardTranslator::KeyboardTranslator(const QString& name)
00789 : _name(name)
00790 {
00791 }
00792
00793 void KeyboardTranslator::setDescription(const QString& description)
00794 {
00795 _description = description;
00796 }
00797 QString KeyboardTranslator::description() const
00798 {
00799 return _description;
00800 }
00801 void KeyboardTranslator::setName(const QString& name)
00802 {
00803 _name = name;
00804 }
00805 QString KeyboardTranslator::name() const
00806 {
00807 return _name;
00808 }
00809
00810 QList<KeyboardTranslator::Entry> KeyboardTranslator::entries() const
00811 {
00812 return _entries.values();
00813 }
00814
00815 void KeyboardTranslator::addEntry(const Entry& entry)
00816 {
00817 const int keyCode = entry.keyCode();
00818 _entries.insert(keyCode,entry);
00819 }
00820 void KeyboardTranslator::replaceEntry(const Entry& existing , const Entry& replacement)
00821 {
00822 if ( !existing.isNull() )
00823 _entries.remove(existing.keyCode(),existing);
00824 _entries.insert(replacement.keyCode(),replacement);
00825 }
00826 void KeyboardTranslator::removeEntry(const Entry& entry)
00827 {
00828 _entries.remove(entry.keyCode(),entry);
00829 }
00830 KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const
00831 {
00832 foreach(const Entry& entry, _entries.values(keyCode))
00833 {
00834 if ( entry.matches(keyCode,modifiers,state) )
00835 return entry;
00836 }
00837 return Entry();
00838 }
00839 void KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator)
00840 {
00841 _translators.insert(translator->name(),translator);
00842
00843 if ( !saveTranslator(translator) )
00844 kWarning() << "Unable to save translator" << translator->name()
00845 << "to disk.";
00846 }
00847 bool KeyboardTranslatorManager::deleteTranslator(const QString& name)
00848 {
00849 Q_ASSERT( _translators.contains(name) );
00850
00851
00852 QString path = findTranslatorPath(name);
00853 if ( QFile::remove(path) )
00854 {
00855 _translators.remove(name);
00856 return true;
00857 }
00858 else
00859 {
00860 kWarning() << "Failed to remove translator - " << path;
00861 return false;
00862 }
00863 }
00864 K_GLOBAL_STATIC( KeyboardTranslatorManager , theKeyboardTranslatorManager )
00865 KeyboardTranslatorManager* KeyboardTranslatorManager::instance()
00866 {
00867 return theKeyboardTranslatorManager;
00868 }