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