• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Konsole

KeyboardTranslator.cpp

Go to the documentation of this file.
00001 /*
00002     This source file is part of Konsole, a terminal emulator.
00003 
00004     Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019     02110-1301  USA.
00020 */
00021 
00022 // Own
00023 #include "KeyboardTranslator.h"
00024 
00025 // System
00026 #include <ctype.h>
00027 #include <stdio.h>
00028 
00029 // Qt
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 // KDE
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     // add the name of each translator to the list and associated
00068     // the name with a null pointer to indicate that the translator
00069     // has not yet been loaded from disk
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 // each line of the keyboard translation file is one of:
00202 //
00203 // - keyboard "name"
00204 // - key KeySequence : "characters"
00205 // - key KeySequence : CommandName
00206 //
00207 // KeySequence begins with the name of the key ( taken from the Qt::Key enum )
00208 // and is followed by the keyboard modifiers and state flags ( with + or - in front
00209 // of each modifier or flag to indicate whether it is required ).  All keyboard modifiers
00210 // and flags are optional, if a particular modifier or state is not specified it is 
00211 // assumed not to be a part of the sequence.  The key sequence may contain whitespace
00212 //
00213 // eg:  "key Up+Shift : scrollLineUp"
00214 //      "key Next-Shift : "\E[6~"
00215 //
00216 // (lines containing only whitespace are ignored, parseLine assumes that comments have
00217 // already been removed)
00218 //
00219 
00220 KeyboardTranslatorReader::KeyboardTranslatorReader( QIODevice* source )
00221     : _source(source)
00222     , _hasNext(false)
00223 {
00224    // read input until we find the description
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     // find next entry
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             // get text or command
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                 // identify command
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         // check if this is a wanted / not-wanted flag and update the 
00371         // state ready for the next item
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     // additional cases implemented for backwards compatibility with KDE 3
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     // if 'result' is the name of a command then the entry result will be that command,
00459     // otherwise the result will be treated as a string to echo when the key sequence
00460     // specified by 'condition' is pressed
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     // comment line: # comment
00501     static QRegExp comment("\\#.*");
00502     // title line: keyboard "title"
00503     static QRegExp title("keyboard\\s+\"(.*)\"");
00504     // key line: key KeySequence : "output"
00505     // key line: key KeySequence : command
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             // capturedTexts()[2] is a command
00532             Token commandToken = { Token::Command , key.capturedTexts()[2] };
00533             list << commandToken;    
00534         }   
00535         else
00536         {
00537             // capturedTexts()[3] is the output string
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     // if modifiers is non-zero, the 'any modifier' state is implicit
00592     if ( modifiers != 0 )
00593         state |= AnyModifierState;
00594 
00595     if ( (state & _stateMask) != (_state & _stateMask) )
00596         return false;
00597 
00598     // special handling for the 'Any Modifier' state, which checks for the presence of 
00599     // any or no modifiers.  In this context, the 'keypad' modifier does not count.
00600     bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;
00601     if ( _stateMask & KeyboardTranslator::AnyModifierState )
00602     {
00603         // test fails if any modifier is required but none are set
00604         if ( (_state & KeyboardTranslator::AnyModifierState) && !anyModifiersSet )
00605            return false;
00606 
00607         // test fails if no modifier is allowed but one or more are set
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                 // any character which is not printable is replaced by an equivalent
00633                 // \xhh escape sequence (where 'hh' are the corresponding hex digits)
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                     // format is \xh or \xhh where 'h' is a hexadecimal
00676                     // digit from 0-9 or A-F which should be replaced
00677                     // with the corresponding character value
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     // add modifiers
00771     insertModifier( result , Qt::ShiftModifier );
00772     insertModifier( result , Qt::ControlModifier );
00773     insertModifier( result , Qt::AltModifier );
00774     insertModifier( result , Qt::MetaModifier ); 
00775 
00776     // add states
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(); // entry not found
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     // locate and delete
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 }

Konsole

Skip menu "Konsole"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • Konsole
  • Libraries
  •   libkonq
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal