KDECore
kshortcut.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kshortcut.h"
00021 #include "kkeynative.h"
00022 #include "kkeyserver.h"
00023
00024 #include <qevent.h>
00025 #include <qstringlist.h>
00026
00027 #include <kdebug.h>
00028 #include <kglobal.h>
00029 #include <klocale.h>
00030 #include <ksimpleconfig.h>
00031
00032
00033
00034 static KKey* g_pspec = 0;
00035 static KKeySequence* g_pseq = 0;
00036 static KShortcut* g_pcut = 0;
00037
00038
00039
00040
00041
00042 KKey::KKey() { clear(); }
00043 KKey::KKey( uint key, uint modFlags ) { init( key, modFlags ); }
00044 KKey::KKey( int keyQt ) { init( keyQt ); }
00045 KKey::KKey( const QKeySequence& seq ) { init( seq ); }
00046 KKey::KKey( const QKeyEvent* pEvent ) { init( pEvent ); }
00047 KKey::KKey( const KKey& key ) { init( key ); }
00048 KKey::KKey( const QString& sKey ) { init( sKey ); }
00049
00050 KKey::~KKey()
00051 {
00052 }
00053
00054 void KKey::clear()
00055 {
00056 m_sym = 0;
00057 m_mod = 0;
00058 }
00059
00060 bool KKey::init( uint key, uint modFlags )
00061 {
00062 m_sym = key;
00063 m_mod = modFlags;
00064 return true;
00065 }
00066
00067 bool KKey::init( int keyQt )
00068 {
00069
00070
00071
00072 if( KKeyServer::keyQtToSym( keyQt, m_sym )
00073 && KKeyServer::keyQtToMod( keyQt, m_mod ) )
00074 return true;
00075 else {
00076 m_sym = 0;
00077 m_mod = 0;
00078 return false;
00079 }
00080 }
00081
00082 bool KKey::init( const QKeySequence& key )
00083 {
00084
00085 return init( (int) key );
00086 }
00087
00088 bool KKey::init( const QKeyEvent* pEvent )
00089 {
00090 int keyQt = pEvent->key();
00091 if( pEvent->state() & Qt::ShiftButton ) keyQt |= Qt::SHIFT;
00092 if( pEvent->state() & Qt::ControlButton ) keyQt |= Qt::CTRL;
00093 if( pEvent->state() & Qt::AltButton ) keyQt |= Qt::ALT;
00094 if( pEvent->state() & Qt::MetaButton ) keyQt |= Qt::META;
00095 return init( keyQt );
00096 }
00097
00098 bool KKey::init( const KKey& key )
00099 {
00100 m_sym = key.m_sym;
00101 m_mod = key.m_mod;
00102 return true;
00103 }
00104
00105 bool KKey::init( const QString& sSpec )
00106 {
00107 clear();
00108
00109 QString sKey = sSpec.stripWhiteSpace();
00110 if( sKey.startsWith( "default(" ) && sKey.endsWith( ")" ) )
00111 sKey = sKey.mid( 8, sKey.length() - 9 );
00112
00113 if( sKey.endsWith( "++" ) )
00114 sKey = sKey.left( sKey.length() - 1 ) + "plus";
00115 QStringList rgs = QStringList::split( '+', sKey, true );
00116
00117 uint i;
00118
00119 for( i = 0; i < rgs.size(); i++ ) {
00120 QString s = rgs[i].lower();
00121 if( s == "shift" ) m_mod |= KKey::SHIFT;
00122 else if( s == "ctrl" ) m_mod |= KKey::CTRL;
00123 else if( s == "alt" ) m_mod |= KKey::ALT;
00124 else if( s == "win" ) m_mod |= KKey::WIN;
00125 else if( s == "meta" ) m_mod |= KKey::WIN;
00126 else {
00127 uint m = KKeyServer::stringUserToMod( s );
00128 if( m != 0 ) m_mod |= m;
00129 else break;
00130 }
00131 }
00132
00133 if( (i == rgs.size() - 1 && !rgs[i].isEmpty()) ) {
00134 KKeyServer::Sym sym( rgs[i] );
00135 m_sym = sym.m_sym;
00136 }
00137
00138 if( m_sym == 0 )
00139 m_mod = 0;
00140
00141 kdDebug(125) << "KKey::init( \"" << sSpec << "\" ):"
00142 << " m_sym = " << QString::number(m_sym, 16)
00143 << ", m_mod = " << QString::number(m_mod, 16) << endl;
00144
00145 return m_sym != 0;
00146 }
00147
00148 bool KKey::isNull() const { return m_sym == 0; }
00149 uint KKey::sym() const { return m_sym; }
00150 uint KKey::modFlags() const { return m_mod; }
00151
00152 int KKey::compare( const KKey& spec ) const
00153 {
00154 if( m_sym != spec.m_sym )
00155 return m_sym - spec.m_sym;
00156 if( m_mod != spec.m_mod )
00157 return m_mod - spec.m_mod;
00158 return 0;
00159 }
00160
00161 int KKey::keyCodeQt() const
00162 {
00163 return KKeyNative( *this ).keyCodeQt();
00164 }
00165
00166 QString KKey::toString() const
00167 {
00168 QString s;
00169
00170 s = KKeyServer::modToStringUser( m_mod );
00171 if( !s.isEmpty() )
00172 s += '+';
00173 s += KKeyServer::Sym(m_sym).toString();
00174
00175 return s;
00176 }
00177
00178 QString KKey::toStringInternal() const
00179 {
00180
00181
00182
00183 QString s;
00184
00185 s = KKeyServer::modToStringInternal( m_mod );
00186 if( !s.isEmpty() )
00187 s += '+';
00188 s += KKeyServer::Sym(m_sym).toStringInternal();
00189 return s;
00190 }
00191
00192 KKey& KKey::null()
00193 {
00194 if( !g_pspec )
00195 g_pspec = new KKey;
00196 if( !g_pspec->isNull() )
00197 g_pspec->clear();
00198 return *g_pspec;
00199 }
00200
00201 QString KKey::modFlagLabel( ModFlag modFlag )
00202 {
00203 return KKeyServer::modToStringUser( modFlag );
00204 }
00205
00206
00207
00208
00209
00210 KKeySequence::KKeySequence() { clear(); }
00211 KKeySequence::KKeySequence( const QKeySequence& seq ) { init( seq ); }
00212 KKeySequence::KKeySequence( const KKey& key ) { init( key ); }
00213 KKeySequence::KKeySequence( const KKeySequence& seq ) { init( seq ); }
00214 KKeySequence::KKeySequence( const QString& s ) { init( s ); }
00215
00216 KKeySequence::~KKeySequence()
00217 {
00218 }
00219
00220 void KKeySequence::clear()
00221 {
00222 m_nKeys = 0;
00223 m_bTriggerOnRelease = false;
00224 }
00225
00226 bool KKeySequence::init( const QKeySequence& seq )
00227 {
00228 clear();
00229 if( !seq.isEmpty() ) {
00230 for( uint i = 0; i < seq.count(); i++ ) {
00231 m_rgvar[i].init( seq[i] );
00232 if( m_rgvar[i].isNull() )
00233 return false;
00234 }
00235 m_nKeys = seq.count();
00236 m_bTriggerOnRelease = false;
00237 }
00238 return true;
00239 }
00240
00241 bool KKeySequence::init( const KKey& key )
00242 {
00243 if( !key.isNull() ) {
00244 m_nKeys = 1;
00245 m_rgvar[0].init( key );
00246 m_bTriggerOnRelease = false;
00247 } else
00248 clear();
00249 return true;
00250 }
00251
00252 bool KKeySequence::init( const KKeySequence& seq )
00253 {
00254 m_bTriggerOnRelease = false;
00255 m_nKeys = seq.m_nKeys;
00256 for( uint i = 0; i < m_nKeys; i++ ) {
00257 if( seq.m_rgvar[i].isNull() ) {
00258 kdDebug(125) << "KKeySequence::init( seq ): key[" << i << "] is null." << endl;
00259 m_nKeys = 0;
00260 return false;
00261 }
00262 m_rgvar[i] = seq.m_rgvar[i];
00263 }
00264 return true;
00265 }
00266
00267 bool KKeySequence::init( const QString& s )
00268 {
00269 m_bTriggerOnRelease = false;
00270
00271 QStringList rgs = QStringList::split( ',', s );
00272 if( s == "none" || rgs.size() == 0 ) {
00273 clear();
00274 return true;
00275 } else if( rgs.size() <= MAX_KEYS ) {
00276 m_nKeys = rgs.size();
00277 for( uint i = 0; i < m_nKeys; i++ ) {
00278 m_rgvar[i].init( KKey(rgs[i]) );
00279
00280 }
00281 return true;
00282 } else {
00283 clear();
00284 return false;
00285 }
00286 }
00287
00288 uint KKeySequence::count() const
00289 {
00290 return m_nKeys;
00291 }
00292
00293 const KKey& KKeySequence::key( uint i ) const
00294 {
00295 if( i < m_nKeys )
00296 return m_rgvar[i];
00297 else
00298 return KKey::null();
00299 }
00300
00301 bool KKeySequence::isTriggerOnRelease() const
00302 { return m_bTriggerOnRelease; }
00303
00304 bool KKeySequence::setKey( uint iKey, const KKey& key )
00305 {
00306 if( iKey <= m_nKeys && iKey < MAX_KEYS ) {
00307 m_rgvar[iKey].init( key );
00308 if( iKey == m_nKeys )
00309 m_nKeys++;
00310 return true;
00311 } else
00312 return false;
00313 }
00314
00315 bool KKeySequence::isNull() const
00316 {
00317 return m_nKeys == 0;
00318 }
00319
00320 bool KKeySequence::startsWith( const KKeySequence& seq ) const
00321 {
00322 if( m_nKeys < seq.m_nKeys )
00323 return false;
00324
00325 for( uint i = 0; i < seq.m_nKeys; i++ ) {
00326 if( m_rgvar[i] != seq.m_rgvar[i] )
00327 return false;
00328 }
00329
00330 return true;
00331 }
00332
00333 int KKeySequence::compare( const KKeySequence& seq ) const
00334 {
00335 for( uint i = 0; i < m_nKeys && i < seq.m_nKeys; i++ ) {
00336 int ret = m_rgvar[i].compare( seq.m_rgvar[i] );
00337 if( ret != 0 )
00338 return ret;
00339 }
00340 if( m_nKeys != seq.m_nKeys )
00341 return m_nKeys - seq.m_nKeys;
00342 else
00343 return 0;
00344 }
00345
00346 QKeySequence KKeySequence::qt() const
00347 {
00348 int k[4] = { 0, 0, 0, 0 };
00349
00350 for( uint i = 0; i < count(); i++ )
00351 k[i] = KKeyNative(key(i)).keyCodeQt();
00352 QKeySequence seq( k[0], k[1], k[2], k[3] );
00353 return seq;
00354 }
00355
00356 int KKeySequence::keyCodeQt() const
00357 {
00358 return (count() == 1) ? KKeyNative(key(0)).keyCodeQt() : 0;
00359 }
00360
00361 QString KKeySequence::toString() const
00362 {
00363 if( m_nKeys < 1 ) return QString::null;
00364
00365 QString s;
00366 s = m_rgvar[0].toString();
00367 for( uint i = 1; i < m_nKeys; i++ ) {
00368 s += ",";
00369 s += m_rgvar[i].toString();
00370 }
00371
00372 return s;
00373 }
00374
00375 QString KKeySequence::toStringInternal() const
00376 {
00377 if( m_nKeys < 1 ) return QString::null;
00378
00379 QString s;
00380 s = m_rgvar[0].toStringInternal();
00381 for( uint i = 1; i < m_nKeys; i++ ) {
00382 s += ",";
00383 s += m_rgvar[i].toStringInternal();
00384 }
00385
00386 return s;
00387 }
00388
00389 KKeySequence& KKeySequence::null()
00390 {
00391 if( !g_pseq )
00392 g_pseq = new KKeySequence;
00393 if( !g_pseq->isNull() )
00394 g_pseq->clear();
00395 return *g_pseq;
00396 }
00397
00398
00399
00400
00401
00402 KShortcut::KShortcut() { clear(); }
00403 KShortcut::KShortcut( int keyQt ) { init( keyQt ); }
00404 KShortcut::KShortcut( const QKeySequence& key ) { init( key ); }
00405 KShortcut::KShortcut( const KKey& key ) { init( key ); }
00406 KShortcut::KShortcut( const KKeySequence& seq ) { init( seq ); }
00407 KShortcut::KShortcut( const KShortcut& cut ) { init( cut ); }
00408 KShortcut::KShortcut( const char* ps ) { init( QString(ps) ); }
00409 KShortcut::KShortcut( const QString& s ) { init( s ); }
00410
00411 KShortcut::~KShortcut()
00412 {
00413 }
00414
00415 void KShortcut::clear()
00416 {
00417 m_nSeqs = 0;
00418 }
00419
00420 bool KShortcut::init( int keyQt )
00421 {
00422 if( keyQt ) {
00423 m_nSeqs = 1;
00424 m_rgseq[0].init( QKeySequence(keyQt) );
00425 } else
00426 clear();
00427 return true;
00428 }
00429
00430 bool KShortcut::init( const QKeySequence& key )
00431 {
00432 m_nSeqs = 1;
00433 m_rgseq[0].init( key );
00434 return true;
00435 }
00436
00437 bool KShortcut::init( const KKey& spec )
00438 {
00439 m_nSeqs = 1;
00440 m_rgseq[0].init( spec );
00441 return true;
00442 }
00443
00444 bool KShortcut::init( const KKeySequence& seq )
00445 {
00446 m_nSeqs = 1;
00447 m_rgseq[0] = seq;
00448 return true;
00449 }
00450
00451 bool KShortcut::init( const KShortcut& cut )
00452 {
00453 m_nSeqs = cut.m_nSeqs;
00454 for( uint i = 0; i < m_nSeqs; i++ )
00455 m_rgseq[i] = cut.m_rgseq[i];
00456 return true;
00457 }
00458
00459 bool KShortcut::init( const QString& s )
00460 {
00461 bool bRet = true;
00462 QStringList rgs = QStringList::split( ';', s );
00463
00464 if( s == "none" || rgs.size() == 0 )
00465 clear();
00466 else if( rgs.size() <= MAX_SEQUENCES ) {
00467 m_nSeqs = rgs.size();
00468 for( uint i = 0; i < m_nSeqs; i++ ) {
00469 QString& sSeq = rgs[i];
00470 if( sSeq.startsWith( "default(" ) )
00471 sSeq = sSeq.mid( 8, sSeq.length() - 9 );
00472 m_rgseq[i].init( sSeq );
00473
00474 }
00475 } else {
00476 clear();
00477 bRet = false;
00478 }
00479
00480 if( !s.isEmpty() ) {
00481 QString sDebug;
00482 QTextStream os( &sDebug, IO_WriteOnly );
00483 os << "KShortcut::init( \"" << s << "\" ): ";
00484 for( uint i = 0; i < m_nSeqs; i++ ) {
00485 os << " m_rgseq[" << i << "]: ";
00486 KKeyServer::Variations vars;
00487 vars.init( m_rgseq[i].key(0), true );
00488 for( uint j = 0; j < vars.count(); j++ )
00489 os << QString::number(vars.m_rgkey[j].keyCodeQt(),16) << ',';
00490 }
00491 kdDebug(125) << sDebug << endl;
00492 }
00493
00494 return bRet;
00495 }
00496
00497 uint KShortcut::count() const
00498 {
00499 return m_nSeqs;
00500 }
00501
00502 const KKeySequence& KShortcut::seq( uint i ) const
00503 {
00504 return (i < m_nSeqs) ? m_rgseq[i] : KKeySequence::null();
00505 }
00506
00507 int KShortcut::keyCodeQt() const
00508 {
00509 if( m_nSeqs >= 1 )
00510 return m_rgseq[0].keyCodeQt();
00511 return QKeySequence();
00512 }
00513
00514 bool KShortcut::isNull() const
00515 {
00516 return m_nSeqs == 0;
00517 }
00518
00519 int KShortcut::compare( const KShortcut& cut ) const
00520 {
00521 for( uint i = 0; i < m_nSeqs && i < cut.m_nSeqs; i++ ) {
00522 int ret = m_rgseq[i].compare( cut.m_rgseq[i] );
00523 if( ret != 0 )
00524 return ret;
00525 }
00526 return m_nSeqs - cut.m_nSeqs;
00527 }
00528
00529 bool KShortcut::contains( const KKey& key ) const
00530 {
00531 return contains( KKeySequence(key) );
00532 }
00533
00534 bool KShortcut::contains( const KKeyNative& keyNative ) const
00535 {
00536 KKey key = keyNative.key();
00537 key.simplify();
00538
00539 for( uint i = 0; i < count(); i++ ) {
00540 if( !m_rgseq[i].isNull()
00541 && m_rgseq[i].count() == 1
00542 && m_rgseq[i].key(0) == key )
00543 return true;
00544 }
00545 return false;
00546 }
00547
00548 bool KShortcut::contains( const KKeySequence& seq ) const
00549 {
00550 for( uint i = 0; i < count(); i++ ) {
00551 if( !m_rgseq[i].isNull() && m_rgseq[i] == seq )
00552 return true;
00553 }
00554 return false;
00555 }
00556
00557 bool KShortcut::setSeq( uint iSeq, const KKeySequence& seq )
00558 {
00559
00560 if( iSeq <= m_nSeqs && iSeq < MAX_SEQUENCES ) {
00561 m_rgseq[iSeq] = seq;
00562 if( iSeq == m_nSeqs )
00563 m_nSeqs++;
00564 return true;
00565 } else
00566 return false;
00567 }
00568
00569 void KShortcut::remove( const KKeySequence& seq )
00570 {
00571 if (seq.isNull()) return;
00572
00573 for( uint iSeq = 0; iSeq < m_nSeqs; iSeq++ )
00574 {
00575 if (m_rgseq[iSeq] == seq)
00576 {
00577 for( uint jSeq = iSeq + 1; jSeq < m_nSeqs; jSeq++)
00578 m_rgseq[jSeq-1] = m_rgseq[jSeq];
00579 m_nSeqs--;
00580 }
00581 }
00582 }
00583
00584 bool KShortcut::append( const KKeySequence& seq )
00585 {
00586 if( m_nSeqs < MAX_SEQUENCES ) {
00587 if( !seq.isNull() ) {
00588 m_rgseq[m_nSeqs] = seq;
00589 m_nSeqs++;
00590 }
00591 return true;
00592 } else
00593 return false;
00594 }
00595
00596 bool KShortcut::append( const KKey& spec )
00597 {
00598 if( m_nSeqs < MAX_SEQUENCES ) {
00599 m_rgseq[m_nSeqs].init( spec );
00600 m_nSeqs++;
00601 return true;
00602 } else
00603 return false;
00604 }
00605
00606 bool KShortcut::append( const KShortcut& cut )
00607 {
00608 uint seqs = m_nSeqs, co = cut.count();
00609 for( uint i=0; i<co; i++ ) {
00610 if (!contains(cut.seq(i))) seqs++;
00611 }
00612 if( seqs > MAX_SEQUENCES ) return false;
00613
00614 for( uint i=0; i<co; i++ ) {
00615 const KKeySequence& seq = cut.seq(i);
00616 if(!contains(seq)) {
00617 m_rgseq[m_nSeqs] = seq;
00618 m_nSeqs++;
00619 }
00620 }
00621 return true;
00622 }
00623
00624 KShortcut::operator QKeySequence () const
00625 {
00626 if( count() >= 1 )
00627 return m_rgseq[0].qt();
00628 else
00629 return QKeySequence();
00630 }
00631
00632 QString KShortcut::toString() const
00633 {
00634 QString s;
00635
00636 for( uint i = 0; i < count(); i++ ) {
00637 s += m_rgseq[i].toString();
00638 if( i < count() - 1 )
00639 s += ';';
00640 }
00641
00642 return s;
00643 }
00644
00645 QString KShortcut::toStringInternal( const KShortcut* pcutDefault ) const
00646 {
00647 QString s;
00648
00649 for( uint i = 0; i < count(); i++ ) {
00650 const KKeySequence& seq = m_rgseq[i];
00651 if( pcutDefault && i < pcutDefault->count() && seq == (*pcutDefault).seq(i) ) {
00652 s += "default(";
00653 s += seq.toStringInternal();
00654 s += ")";
00655 } else
00656 s += seq.toStringInternal();
00657 if( i < count() - 1 )
00658 s += ';';
00659 }
00660
00661 return s;
00662 }
00663
00664 KShortcut& KShortcut::null()
00665 {
00666 if( !g_pcut )
00667 g_pcut = new KShortcut;
00668 if( !g_pcut->isNull() )
00669 g_pcut->clear();
00670 return *g_pcut;
00671 }