📄 kaccel.cpp
字号:
/* Copyright (C) 1998 Mark Donohoe <donohoe@kde.org> Copyright (C) 1997 Nicolas Hadacek <hadacek@via.ecp.fr> Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include <qkeycode.h>#include <qlayout.h>#include <qpainter.h>#include <qapplication.h>#include <qdrawutil.h>#include <qmessagebox.h>#include <kapp.h>#include <kdebug.h>#include "kaccel.h"KAccel::KAccel( QWidget * parent, const char * name ): aKeyDict(100){ aAvailableId = 1; bEnabled = true; aGroup = "Keys"; bGlobal = false; pAccel = new QAccel( parent, name );}KAccel::~KAccel(){ delete pAccel;}void KAccel::clear(){ pAccel->clear(); aKeyDict.clear();}void KAccel::connectItem( const char * action, const QObject* receiver, const char* member, bool activate ){ if (!action) return; KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) { QString str; str.sprintf( "KAccel : Cannot connect action %s ", action ); str.append( "which is not in the object dictionary" ); warning(str); return; } pEntry->receiver = receiver; pEntry->member = member; pEntry->aAccelId = aAvailableId; aAvailableId++; pAccel->insertItem( pEntry->aCurrentKeyCode, pEntry->aAccelId ); pAccel->connectItem( pEntry->aAccelId, receiver, member ); if ( !activate ) setItemEnabled( action, FALSE );}void KAccel::connectItem( StdAccel accel, const QObject* receiver, const char* member, bool activate ){ if (stdAction(accel) && !aKeyDict[ stdAction(accel) ]){ insertStdItem(accel); } connectItem(stdAction(accel), receiver, member, activate);}uint KAccel::count() const{ return aKeyDict.count();}uint KAccel::currentKey( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return 0; else return pEntry->aCurrentKeyCode;}const char* KAccel::description( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return 0; else return pEntry->descr;}uint KAccel::defaultKey( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return 0; else return pEntry->aDefaultKeyCode;}void KAccel::disconnectItem( const char * action, const QObject* receiver, const char* member ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return; pAccel->disconnectItem( pEntry->aAccelId, receiver, member );}const char * KAccel::findKey( int key ) const{ QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst();#define pE aKeyIt.current() while ( pE ) { if ( (unsigned int)key == pE->aCurrentKeyCode ) return aKeyIt.currentKey(); ++aKeyIt; }#undef pE return 0; }bool KAccel::insertItem( const char* descr, const char * action, uint keyCode, bool configurable ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( pEntry ) removeItem( action ); pEntry = new KKeyEntry; aKeyDict.insert( action, pEntry ); pEntry->aDefaultKeyCode = keyCode; pEntry->aCurrentKeyCode = keyCode; pEntry->aConfigKeyCode = keyCode; pEntry->bConfigurable = configurable; pEntry->aAccelId = 0; pEntry->receiver = 0; pEntry->member = 0; pEntry->descr = descr; return TRUE;}bool KAccel::insertItem( const char* descr, const char * action, const char * keyCode, bool configurable ){ uint iKeyCode = stringToKey( keyCode ); return insertItem( descr, action, iKeyCode, configurable );}bool KAccel::insertItem( const char * action, uint keyCode, bool configurable ){ return insertItem(action, action, keyCode, configurable);}void KAccel::changeMenuAccel ( QPopupMenu *menu, int id, const char *action ){ QString s = menu->text( id ); if ( !s ) return; if (!action) return; int i = s.find('\t'); QString k = keyToString( currentKey( action), true ); if( !k ) return; if ( i >= 0 ) s.replace( i+1, s.length()-i, k ); else { s += '\t'; s += k; } QPixmap *pp = menu->pixmap(id); if(pp && !pp->isNull()) menu->changeItem( *pp, s, id ); else menu->changeItem( s, id );}void KAccel::changeMenuAccel ( QPopupMenu *menu, int id, StdAccel accel ){ changeMenuAccel(menu, id, stdAction(accel));}bool KAccel::insertStdItem( StdAccel id, const char* descr ){ const char *key=0, *name = 0; switch( id ) { case Open: name=i18n("Open") ; key = "CTRL+O"; break; case New: name=i18n("New") ; key = "CTRL+N"; break; case Close: name=i18n("Close") ; key = "CTRL+W"; break; case Save: name=i18n("Save") ; key = "CTRL+S"; break; case Print: name=i18n("Print") ; key = "CTRL+P"; break; case Quit: name=i18n("Quit") ; key = "CTRL+Q"; break; case Cut: name=i18n("Cut") ; key = "CTRL+X"; break; case Copy: name=i18n("Copy") ; key = "CTRL+C"; break; case Paste: name=i18n("Paste") ; key = "CTRL+V"; break; case Undo: name=i18n("Undo") ; key = "CTRL+Z"; break; case Find: name=i18n("Find") ; key = "CTRL+F"; break; case Replace: name=i18n("Replace") ; key = "CTRL+R"; break; case Insert: name=i18n("Insert") ; key = "CTRL+Insert"; break; case Home: name=i18n("Home") ; key = "CTRL+Home"; break; case End: name=i18n("End") ; key = "CTRL+End"; break; case Prior: name=i18n("Prior") ; key = "Prior"; break; case Next: name=i18n("Next") ; key = "Next"; break; case Help: name=i18n("Help") ; key = "F1"; break; default: return false; break; } return insertItem( descr?descr:name, stdAction(id), key, false );}bool KAccel::isEnabled(){ return bEnabled;}bool KAccel::isItemEnabled( const char *action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return false; else return pEntry->bEnabled;}QDict<KKeyEntry> KAccel::keyDict(){ return aKeyDict;}void KAccel::readSettings(KConfig* config){ QString s; KConfig *pConfig = config?config:kapp->getConfig(); pConfig->setGroup( aGroup.data() ); QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst();#define pE aKeyIt.current() while ( pE ) { s = pConfig->readEntry( aKeyIt.currentKey() ); if ( s.isNull() ) pE->aConfigKeyCode = pE->aDefaultKeyCode; else pE->aConfigKeyCode = stringToKey( s.data() ); pE->aCurrentKeyCode = pE->aConfigKeyCode; if ( pE->aAccelId && pE->aCurrentKeyCode ) { pAccel->disconnectItem( pE->aAccelId, pE->receiver, pE->member ); pAccel->removeItem( pE->aAccelId ); pAccel->insertItem( pE->aCurrentKeyCode, pE->aAccelId ); pAccel->connectItem( pE->aAccelId, pE->receiver, pE->member); } ++aKeyIt; }#undef pE}void KAccel::removeItem( const char * action ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) return; if ( pEntry->aAccelId ) { pAccel->disconnectItem( pEntry->aAccelId, pEntry->receiver, pEntry->member); pAccel->removeItem( pEntry->aAccelId ); } aKeyDict.remove( action );}void KAccel::setEnabled( bool activate ){ QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst();#define pE aKeyIt.current() while ( pE ) { setItemEnabled( aKeyIt.currentKey(), activate ); ++aKeyIt; }#undef pE bEnabled = activate;}void KAccel::setItemEnabled( const char * action, bool activate ){ KKeyEntry *pEntry = aKeyDict[ action ]; if ( !pEntry ) { QString str; str.sprintf( "KAccel : cannont enable action %s"\ "which is not in the object dictionary", action ); warning( str ); return; } pAccel->setItemEnabled( pEntry->aAccelId, activate );}bool KAccel::setKeyDict( QDict<KKeyEntry> nKeyDict ){ kdebug(KDEBUG_INFO, 125, "Disconenct and remove"); // Disconnect and remove all items in pAccel QDictIterator<KKeyEntry> *aKeyIt = new QDictIterator<KKeyEntry>( aKeyDict ); aKeyIt->toFirst();#define pE aKeyIt->current() while( pE ) { QString s; if ( pE->aAccelId && pE->aCurrentKeyCode ) { pAccel->disconnectItem( pE->aAccelId, pE->receiver, pE->member ); pAccel->removeItem( pE->aAccelId ); } ++*aKeyIt; }#undef pE kdebug(KDEBUG_INFO, 125, "Clear the dictionary"); // Clear the dictionary aKeyDict.clear(); kdebug(KDEBUG_INFO, 125, "Insert new items"); // Insert the new items into the dictionary and reconnect if neccessary // Note also swap config and current key codes !!!!!! delete aKeyIt; // tanghus aKeyIt = new QDictIterator<KKeyEntry>( nKeyDict ); aKeyIt->toFirst();#define pE aKeyIt->current() KKeyEntry *pEntry; while( pE ) { pEntry = new KKeyEntry; aKeyDict.insert( aKeyIt->currentKey(), pEntry ); pEntry->aDefaultKeyCode = pE->aDefaultKeyCode; // Note we write config key code to current key code !! pEntry->aCurrentKeyCode = pE->aConfigKeyCode; pEntry->aConfigKeyCode = pE->aConfigKeyCode; pEntry->bConfigurable = pE->bConfigurable; pEntry->aAccelId = pE->aAccelId; pEntry->receiver = pE->receiver; pEntry->member = pE->member; pEntry->descr = pE->descr; // tanghus if ( pEntry->aAccelId && pEntry->aCurrentKeyCode ) { pAccel->insertItem( pEntry->aCurrentKeyCode, pEntry->aAccelId ); pAccel->connectItem( pEntry->aAccelId, pEntry->receiver, pEntry->member); } ++*aKeyIt; }#undef pE delete aKeyIt; // tanghus return true;}const char * KAccel::stdAction( StdAccel id ) { const char* action = 0; switch( id ) { case Open: action = "Open"; break; case New: action = "New"; break; case Close: action = "Close"; break; case Save: action = "Save"; break; case Print: action = "Print"; break; case Quit: action = "Quit"; break; case Cut: action = "Cut"; break; case Copy: action = "Copy"; break; case Paste: action = "Paste"; break; case Undo: action = "Undo"; break; case Find: action = "Find"; break; case Replace: action = "Replace"; break; case Insert: action = "Insert"; break; case Home: action = "Home"; break; case End: action = "End"; break; case Prior: action = "Prior"; break; case Next: action = "Next"; break; case Help: action = "Help"; break; default: return 0; break; } return action;}void KAccel::setConfigGroup( const char *group ){ aGroup = group;}void KAccel::setConfigGlobal( bool global ){ bGlobal = global;}const char *KAccel::configGroup(){ return aGroup.data();}bool KAccel::configGlobal(){ return bGlobal;}void KAccel::writeSettings(KConfig* config){ KConfig *pConfig = config?config:kapp->getConfig(); pConfig->setGroup( aGroup.data() ); QDictIterator<KKeyEntry> aKeyIt( aKeyDict ); aKeyIt.toFirst(); while ( aKeyIt.current() ) { if ( aKeyIt.current()->bConfigurable ) { if ( bGlobal ) pConfig->writeEntry( aKeyIt.currentKey(), keyToString( aKeyIt.current()->aCurrentKeyCode), true, true ); else pConfig->writeEntry( aKeyIt.currentKey(), keyToString( aKeyIt.current()->aCurrentKeyCode )); } ++aKeyIt; } pConfig->sync();}/*****************************************************************************/const QString keyToString( uint keyCode, bool i18_n ){ QString res; if ( keyCode == 0 ) { res = ""; return res; } if (!i18_n){ if ( keyCode & SHIFT ){ res += ("SHIFT"); res += "+"; } if ( keyCode & CTRL ){ res +=("CTRL"); res += "+"; } if ( keyCode & ALT ){ res +=("ALT"); res += "+"; } } else { if ( keyCode & SHIFT ){ res = i18n("SHIFT"); res += "+"; } if ( keyCode & CTRL ){ res += i18n("CTRL"); res += "+"; } if ( keyCode & ALT ){ res += i18n("ALT"); res += "+"; } } uint kCode = keyCode & ~(SHIFT | CTRL | ALT); for (int i=0; i<NB_KEYS; i++) { if ( kCode == (uint)KKeys[i].code ) { res += KKeys[i].name; return res; } } return 0;}uint stringToKey(const char * key ){ char *toks[4], *next_tok; uint keyCode = 0; int j, nb_toks = 0; char sKey[200]; //printf("string to key %s\n", key); if ( key == 0 ) { kdebug(KDEBUG_WARN, 125, "stringToKey::Null key");return 0; } if( strcmp( key, "" ) == -1 ) { kdebug(KDEBUG_WARN, 125, "stringToKey::Empty key");return 0; } strncpy(sKey, (const char *)key, 200); next_tok = strtok(sKey,"+"); if ( next_tok== 0L ) return 0; do { toks[nb_toks] = next_tok; nb_toks++; if ( nb_toks==5 ) return 0; next_tok = strtok(0L, "+"); } while ( next_tok!=0L ); /* we test if there is one and only one key (the others tokens are accelerators) ; we also fill the keycode with infos */ bool keyFound = FALSE; for (int i=0; i<nb_toks; i++) { if ( strcmp(toks[i], "SHIFT")==0 ) keyCode |= SHIFT; else if ( strcmp(toks[i], "CTRL")==0 ) keyCode |= CTRL; else if ( strcmp(toks[i], "ALT")==0 ) keyCode |= ALT; else if ( strcmp(toks[i], "Umschalt")==0 ) keyCode |= SHIFT; else if ( strcmp(toks[i], "Strg")==0 ) keyCode |= CTRL; else if ( strcmp(toks[i], "Alt")==0 ) keyCode |= ALT; else if ( strcmp(toks[i], i18n("SHIFT"))==0 ) keyCode |= SHIFT; else if ( strcmp(toks[i], i18n("CTRL"))==0 ) keyCode |= CTRL; else if ( strcmp(toks[i], i18n("ALT"))==0 ) keyCode |= ALT; else { /* key already found ? */ if ( keyFound ) return 0; keyFound = TRUE; /* search key */ for(j=0; j<NB_KEYS; j++) { if ( strcmp(toks[i], KKeys[j].name)==0 ) { keyCode |= KKeys[j].code; break; } } /* key name ot found ? */ if ( j==NB_KEYS ) return 0; } } return keyCode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -