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