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

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.7
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