• Skip to content
  • Skip to link menu
KDE 4.1 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 2007-2008 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 <QtCore/QFile>
00032 #include <QtCore/QFileInfo>
00033 #include <QtCore/QTextStream>
00034 #include <QtGui/QKeySequence>
00035 
00036 // KDE
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     // add the name of each translator to the list and associated
00067     // the name with a null pointer to indicate that the translator
00068     // has not yet been loaded from disk
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 // each line of the keyboard translation file is one of:
00201 //
00202 // - keyboard "name"
00203 // - key KeySequence : "characters"
00204 // - key KeySequence : CommandName
00205 //
00206 // KeySequence begins with the name of the key ( taken from the Qt::Key enum )
00207 // and is followed by the keyboard modifiers and state flags ( with + or - in front
00208 // of each modifier or flag to indicate whether it is required ).  All keyboard modifiers
00209 // and flags are optional, if a particular modifier or state is not specified it is 
00210 // assumed not to be a part of the sequence.  The key sequence may contain whitespace
00211 //
00212 // eg:  "key Up+Shift : scrollLineUp"
00213 //      "key Next-Shift : "\E[6~"
00214 //
00215 // (lines containing only whitespace are ignored, parseLine assumes that comments have
00216 // already been removed)
00217 //
00218 
00219 KeyboardTranslatorReader::KeyboardTranslatorReader( QIODevice* source )
00220     : _source(source)
00221     , _hasNext(false)
00222 {
00223    // read input until we find the description
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     // find next entry
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             // get text or command
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                 // identify command
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         // check if this is a wanted / not-wanted flag and update the 
00370         // state ready for the next item
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     // additional cases implemented for backwards compatibility with KDE 3
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     // if 'result' is the name of a command then the entry result will be that command,
00458     // otherwise the result will be treated as a string to echo when the key sequence
00459     // specified by 'condition' is pressed
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     // remove comments 
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     // title line: keyboard "title"
00516     static QRegExp title("keyboard\\s+\"(.*)\"");
00517     // key line: key KeySequence : "output"
00518     // key line: key KeySequence : command
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             // capturedTexts()[2] is a command
00544             Token commandToken = { Token::Command , key.capturedTexts()[2] };
00545             list << commandToken;    
00546         }   
00547         else
00548         {
00549             // capturedTexts()[3] is the output string
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     // if modifiers is non-zero, the 'any modifier' state is implicit
00604     if ( modifiers != 0 )
00605         state |= AnyModifierState;
00606 
00607     if ( (state & _stateMask) != (_state & _stateMask) )
00608         return false;
00609 
00610     // special handling for the 'Any Modifier' state, which checks for the presence of 
00611     // any or no modifiers.  In this context, the 'keypad' modifier does not count.
00612     bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;
00613     if ( _stateMask & KeyboardTranslator::AnyModifierState )
00614     {
00615         // test fails if any modifier is required but none are set
00616         if ( (_state & KeyboardTranslator::AnyModifierState) && !anyModifiersSet )
00617            return false;
00618 
00619         // test fails if no modifier is allowed but one or more are set
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                 // any character which is not printable is replaced by an equivalent
00645                 // \xhh escape sequence (where 'hh' are the corresponding hex digits)
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                     // format is \xh or \xhh where 'h' is a hexadecimal
00688                     // digit from 0-9 or A-F which should be replaced
00689                     // with the corresponding character value
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     // add modifiers
00782     insertModifier( result , Qt::ShiftModifier );
00783     insertModifier( result , Qt::ControlModifier );
00784     insertModifier( result , Qt::AltModifier );
00785     insertModifier( result , Qt::MetaModifier ); 
00786 
00787     // add states
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(); // entry not found
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     // locate and delete
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 }

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