kdecore Library API Documentation

kshortcut.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 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 // KKey 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 //KKeyServer::Sym sym; 00070 00071 //if( sym.initQt( keyQt ) 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 // TODO: if key.count() > 1, should we return failure? 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 // i.e., "Ctrl++" = "Ctrl+Plus" 00113 if( sKey.endsWith( "++" ) ) 00114 sKey = sKey.left( sKey.length() - 1 ) + "plus"; 00115 QStringList rgs = QStringList::split( '+', sKey, true ); 00116 00117 uint i; 00118 // Check for modifier keys first. 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 break; 00127 } 00128 // If there is one non-blank key left: 00129 if( (i == rgs.size() - 1 && !rgs[i].isEmpty()) ) { 00130 KKeyServer::Sym sym( rgs[i] ); 00131 m_sym = sym.m_sym; 00132 } 00133 00134 if( m_sym == 0 ) 00135 m_mod = 0; 00136 00137 kdDebug(125) << "KKey::init( \"" << sSpec << "\" ):" 00138 << " m_sym = " << QString::number(m_sym, 16) 00139 << ", m_mod = " << QString::number(m_mod, 16) << endl; 00140 00141 return m_sym != 0; 00142 } 00143 00144 bool KKey::isNull() const { return m_sym == 0; } 00145 uint KKey::sym() const { return m_sym; } 00146 uint KKey::modFlags() const { return m_mod; } 00147 00148 int KKey::compare( const KKey& spec ) const 00149 { 00150 if( m_sym != spec.m_sym ) 00151 return m_sym - spec.m_sym; 00152 if( m_mod != spec.m_mod ) 00153 return m_mod - spec.m_mod; 00154 return 0; 00155 } 00156 00157 int KKey::keyCodeQt() const 00158 { 00159 return KKeyNative( *this ).keyCodeQt(); 00160 } 00161 00162 QString KKey::toString() const 00163 { 00164 QString s; 00165 00166 s = KKeyServer::modToStringUser( m_mod ); 00167 if( !s.isEmpty() ) 00168 s += '+'; 00169 s += KKeyServer::Sym(m_sym).toString(); 00170 00171 return s; 00172 } 00173 00174 QString KKey::toStringInternal() const 00175 { 00176 //kdDebug(125) << "KKey::toStringInternal(): this = " << this 00177 // << " mod = " << QString::number(m_mod, 16) 00178 // << " key = " << QString::number(m_sym, 16) << endl; 00179 QString s; 00180 00181 s = KKeyServer::modToStringInternal( m_mod ); 00182 if( !s.isEmpty() ) 00183 s += '+'; 00184 s += KKeyServer::Sym(m_sym).toStringInternal(); 00185 return s; 00186 } 00187 00188 KKey& KKey::null() 00189 { 00190 if( !g_pspec ) 00191 g_pspec = new KKey; 00192 if( !g_pspec->isNull() ) 00193 g_pspec->clear(); 00194 return *g_pspec; 00195 } 00196 00197 QString KKey::modFlagLabel( ModFlag modFlag ) 00198 { 00199 return KKeyServer::modToStringUser( modFlag ); 00200 } 00201 00202 //--------------------------------------------------------------------- 00203 // KKeySequence 00204 //--------------------------------------------------------------------- 00205 00206 KKeySequence::KKeySequence() { clear(); } 00207 KKeySequence::KKeySequence( const QKeySequence& seq ) { init( seq ); } 00208 KKeySequence::KKeySequence( const KKey& key ) { init( key ); } 00209 KKeySequence::KKeySequence( const KKeySequence& seq ) { init( seq ); } 00210 KKeySequence::KKeySequence( const QString& s ) { init( s ); } 00211 00212 KKeySequence::~KKeySequence() 00213 { 00214 } 00215 00216 void KKeySequence::clear() 00217 { 00218 m_nKeys = 0; 00219 m_bTriggerOnRelease = false; 00220 } 00221 00222 bool KKeySequence::init( const QKeySequence& seq ) 00223 { 00224 clear(); 00225 #if QT_VERSION >= 0x030100 00226 if( !seq.isEmpty() ) { 00227 for( uint i = 0; i < seq.count(); i++ ) { 00228 m_rgvar[i].init( seq[i] ); 00229 if( m_rgvar[i].isNull() ) 00230 return false; 00231 } 00232 m_nKeys = seq.count(); 00233 m_bTriggerOnRelease = false; 00234 } 00235 #else // Qt 3.0.x 00236 if( seq ) { 00237 m_rgvar[ 0 ].init( seq ); 00238 if( !m_rgvar[ 0 ].isNull() ) { 00239 m_nKeys = 1; 00240 m_bTriggerOnRelease = false; 00241 } 00242 } 00243 #endif 00244 return true; 00245 } 00246 00247 bool KKeySequence::init( const KKey& key ) 00248 { 00249 if( !key.isNull() ) { 00250 m_nKeys = 1; 00251 m_rgvar[0].init( key ); 00252 m_bTriggerOnRelease = false; 00253 } else 00254 clear(); 00255 return true; 00256 } 00257 00258 bool KKeySequence::init( const KKeySequence& seq ) 00259 { 00260 m_bTriggerOnRelease = false; 00261 m_nKeys = seq.m_nKeys; 00262 for( uint i = 0; i < m_nKeys; i++ ) { 00263 if( seq.m_rgvar[i].isNull() ) { 00264 kdDebug(125) << "KKeySequence::init( seq ): key[" << i << "] is null." << endl; 00265 m_nKeys = 0; 00266 return false; 00267 } 00268 m_rgvar[i] = seq.m_rgvar[i]; 00269 } 00270 return true; 00271 } 00272 00273 bool KKeySequence::init( const QString& s ) 00274 { 00275 m_bTriggerOnRelease = false; 00276 //kdDebug(125) << "KKeySequence::init( " << s << " )" << endl; 00277 QStringList rgs = QStringList::split( ',', s ); 00278 if( s == "none" || rgs.size() == 0 ) { 00279 clear(); 00280 return true; 00281 } else if( rgs.size() <= MAX_KEYS ) { 00282 m_nKeys = rgs.size(); 00283 for( uint i = 0; i < m_nKeys; i++ ) { 00284 m_rgvar[i].init( KKey(rgs[i]) ); 00285 //kdDebug(125) << "\t'" << rgs[i] << "' => " << m_rgvar[i].toStringInternal() << endl; 00286 } 00287 return true; 00288 } else { 00289 clear(); 00290 return false; 00291 } 00292 } 00293 00294 uint KKeySequence::count() const 00295 { 00296 return m_nKeys; 00297 } 00298 00299 const KKey& KKeySequence::key( uint i ) const 00300 { 00301 if( i < m_nKeys ) 00302 return m_rgvar[i]; 00303 else 00304 return KKey::null(); 00305 } 00306 00307 bool KKeySequence::isTriggerOnRelease() const 00308 { return m_bTriggerOnRelease; } 00309 00310 bool KKeySequence::setKey( uint iKey, const KKey& key ) 00311 { 00312 if( iKey <= m_nKeys && iKey < MAX_KEYS ) { 00313 m_rgvar[iKey].init( key ); 00314 if( iKey == m_nKeys ) 00315 m_nKeys++; 00316 return true; 00317 } else 00318 return false; 00319 } 00320 00321 bool KKeySequence::isNull() const 00322 { 00323 return m_nKeys == 0; 00324 } 00325 00326 bool KKeySequence::startsWith( const KKeySequence& seq ) const 00327 { 00328 if( m_nKeys < seq.m_nKeys ) 00329 return false; 00330 00331 for( uint i = 0; i < seq.m_nKeys; i++ ) { 00332 if( m_rgvar[i] != seq.m_rgvar[i] ) 00333 return false; 00334 } 00335 00336 return true; 00337 } 00338 00339 int KKeySequence::compare( const KKeySequence& seq ) const 00340 { 00341 for( uint i = 0; i < m_nKeys && i < seq.m_nKeys; i++ ) { 00342 int ret = m_rgvar[i].compare( seq.m_rgvar[i] ); 00343 if( ret != 0 ) 00344 return ret; 00345 } 00346 if( m_nKeys != seq.m_nKeys ) 00347 return m_nKeys - seq.m_nKeys; 00348 else 00349 return 0; 00350 } 00351 00352 QKeySequence KKeySequence::qt() const 00353 { 00354 int k[4] = { 0, 0, 0, 0 }; 00355 00356 for( uint i = 0; i < count(); i++ ) 00357 k[i] = KKeyNative(key(i)).keyCodeQt(); 00358 #if QT_VERSION >= 0x030100 00359 QKeySequence seq( k[0], k[1], k[2], k[3] ); 00360 #else // Qt-3.0.x 00361 QKeySequence seq; 00362 if( count() == 1 ) 00363 seq = KKeyNative( key( 0 ) ).keyCodeQt(); 00364 #endif 00365 return seq; 00366 } 00367 00368 int KKeySequence::keyCodeQt() const 00369 { 00370 return (count() == 1) ? KKeyNative(key(0)).keyCodeQt() : 0; 00371 } 00372 00373 QString KKeySequence::toString() const 00374 { 00375 if( m_nKeys < 1 ) return QString::null; 00376 00377 QString s; 00378 s = m_rgvar[0].toString(); 00379 for( uint i = 1; i < m_nKeys; i++ ) { 00380 s += ","; 00381 s += m_rgvar[i].toString(); 00382 } 00383 00384 return s; 00385 } 00386 00387 QString KKeySequence::toStringInternal() const 00388 { 00389 if( m_nKeys < 1 ) return QString::null; 00390 00391 QString s; 00392 s = m_rgvar[0].toStringInternal(); 00393 for( uint i = 1; i < m_nKeys; i++ ) { 00394 s += ","; 00395 s += m_rgvar[i].toStringInternal(); 00396 } 00397 00398 return s; 00399 } 00400 00401 KKeySequence& KKeySequence::null() 00402 { 00403 if( !g_pseq ) 00404 g_pseq = new KKeySequence; 00405 if( !g_pseq->isNull() ) 00406 g_pseq->clear(); 00407 return *g_pseq; 00408 } 00409 00410 //--------------------------------------------------------------------- 00411 // KShortcut 00412 //--------------------------------------------------------------------- 00413 00414 KShortcut::KShortcut() { clear(); } 00415 KShortcut::KShortcut( int keyQt ) { init( keyQt ); } 00416 KShortcut::KShortcut( const QKeySequence& key ) { init( key ); } 00417 KShortcut::KShortcut( const KKey& key ) { init( key ); } 00418 KShortcut::KShortcut( const KKeySequence& seq ) { init( seq ); } 00419 KShortcut::KShortcut( const KShortcut& cut ) { init( cut ); } 00420 KShortcut::KShortcut( const char* ps ) { init( QString(ps) ); } 00421 KShortcut::KShortcut( const QString& s ) { init( s ); } 00422 00423 KShortcut::~KShortcut() 00424 { 00425 } 00426 00427 void KShortcut::clear() 00428 { 00429 m_nSeqs = 0; 00430 } 00431 00432 bool KShortcut::init( int keyQt ) 00433 { 00434 if( keyQt ) { 00435 m_nSeqs = 1; 00436 m_rgseq[0].init( QKeySequence(keyQt) ); 00437 } else 00438 clear(); 00439 return true; 00440 } 00441 00442 bool KShortcut::init( const QKeySequence& key ) 00443 { 00444 m_nSeqs = 1; 00445 m_rgseq[0].init( key ); 00446 return true; 00447 } 00448 00449 bool KShortcut::init( const KKey& spec ) 00450 { 00451 m_nSeqs = 1; 00452 m_rgseq[0].init( spec ); 00453 return true; 00454 } 00455 00456 bool KShortcut::init( const KKeySequence& seq ) 00457 { 00458 m_nSeqs = 1; 00459 m_rgseq[0] = seq; 00460 return true; 00461 } 00462 00463 bool KShortcut::init( const KShortcut& cut ) 00464 { 00465 m_nSeqs = cut.m_nSeqs; 00466 for( uint i = 0; i < m_nSeqs; i++ ) 00467 m_rgseq[i] = cut.m_rgseq[i]; 00468 return true; 00469 } 00470 00471 bool KShortcut::init( const QString& s ) 00472 { 00473 bool bRet = true; 00474 QStringList rgs = QStringList::split( ';', s ); 00475 00476 if( s == "none" || rgs.size() == 0 ) 00477 clear(); 00478 else if( rgs.size() <= MAX_SEQUENCES ) { 00479 m_nSeqs = rgs.size(); 00480 for( uint i = 0; i < m_nSeqs; i++ ) { 00481 QString& sSeq = rgs[i]; 00482 if( sSeq.startsWith( "default(" ) ) 00483 sSeq = sSeq.mid( 8, sSeq.length() - 9 ); 00484 m_rgseq[i].init( sSeq ); 00485 //kdDebug(125) << "*\t'" << sSeq << "' => " << m_rgseq[i].toStringInternal() << endl; 00486 } 00487 } else { 00488 clear(); 00489 bRet = false; 00490 } 00491 00492 if( !s.isEmpty() ) { 00493 QString sDebug; 00494 QTextStream os( &sDebug, IO_WriteOnly ); 00495 os << "KShortcut::init( \"" << s << "\" ): "; 00496 for( uint i = 0; i < m_nSeqs; i++ ) { 00497 os << " m_rgseq[" << i << "]: "; 00498 KKeyServer::Variations vars; 00499 vars.init( m_rgseq[i].key(0), true ); 00500 for( uint j = 0; j < vars.count(); j++ ) 00501 os << QString::number(vars.m_rgkey[j].keyCodeQt(),16) << ','; 00502 } 00503 kdDebug(125) << sDebug << endl; 00504 } 00505 00506 return bRet; 00507 } 00508 00509 uint KShortcut::count() const 00510 { 00511 return m_nSeqs; 00512 } 00513 00514 const KKeySequence& KShortcut::seq( uint i ) const 00515 { 00516 return (i < m_nSeqs) ? m_rgseq[i] : KKeySequence::null(); 00517 } 00518 00519 int KShortcut::keyCodeQt() const 00520 { 00521 if( m_nSeqs >= 1 ) 00522 return m_rgseq[0].keyCodeQt(); 00523 return QKeySequence(); 00524 } 00525 00526 bool KShortcut::isNull() const 00527 { 00528 return m_nSeqs == 0; 00529 } 00530 00531 int KShortcut::compare( const KShortcut& cut ) const 00532 { 00533 for( uint i = 0; i < m_nSeqs && i < cut.m_nSeqs; i++ ) { 00534 int ret = m_rgseq[i].compare( cut.m_rgseq[i] ); 00535 if( ret != 0 ) 00536 return ret; 00537 } 00538 return m_nSeqs - cut.m_nSeqs; 00539 } 00540 00541 bool KShortcut::contains( const KKey& key ) const 00542 { 00543 return contains( KKeySequence(key) ); 00544 } 00545 00546 bool KShortcut::contains( const KKeyNative& keyNative ) const 00547 { 00548 KKey key = keyNative.key(); 00549 key.simplify(); 00550 00551 for( uint i = 0; i < count(); i++ ) { 00552 if( !m_rgseq[i].isNull() 00553 && m_rgseq[i].count() == 1 00554 && m_rgseq[i].key(0) == key ) 00555 return true; 00556 } 00557 return false; 00558 } 00559 00560 bool KShortcut::contains( const KKeySequence& seq ) const 00561 { 00562 for( uint i = 0; i < count(); i++ ) { 00563 if( !m_rgseq[i].isNull() && m_rgseq[i] == seq ) 00564 return true; 00565 } 00566 return false; 00567 } 00568 00569 bool KShortcut::setSeq( uint iSeq, const KKeySequence& seq ) 00570 { 00571 // TODO: check if seq is null, and act accordingly. 00572 if( iSeq <= m_nSeqs && iSeq < MAX_SEQUENCES ) { 00573 m_rgseq[iSeq] = seq; 00574 if( iSeq == m_nSeqs ) 00575 m_nSeqs++; 00576 return true; 00577 } else 00578 return false; 00579 } 00580 00581 void KShortcut::remove( const KKeySequence& seq ) 00582 { 00583 if (seq.isNull()) return; 00584 00585 for( uint iSeq = 0; iSeq < m_nSeqs; iSeq++ ) 00586 { 00587 if (m_rgseq[iSeq] == seq) 00588 { 00589 for( uint jSeq = iSeq + 1; jSeq < m_nSeqs; jSeq++) 00590 m_rgseq[jSeq-1] = m_rgseq[jSeq]; 00591 m_nSeqs--; 00592 } 00593 } 00594 } 00595 00596 bool KShortcut::append( const KKeySequence& seq ) 00597 { 00598 if( m_nSeqs < MAX_SEQUENCES ) { 00599 if( !seq.isNull() ) { 00600 m_rgseq[m_nSeqs] = seq; 00601 m_nSeqs++; 00602 } 00603 return true; 00604 } else 00605 return false; 00606 } 00607 00608 bool KShortcut::append( const KKey& spec ) 00609 { 00610 if( m_nSeqs < MAX_SEQUENCES ) { 00611 m_rgseq[m_nSeqs].init( spec ); 00612 m_nSeqs++; 00613 return true; 00614 } else 00615 return false; 00616 } 00617 00618 bool KShortcut::append( const KShortcut& cut ) 00619 { 00620 uint seqs = m_nSeqs, co = cut.count(); 00621 for( uint i=0; i<co; i++ ) { 00622 if (!contains(cut.seq(i))) seqs++; 00623 } 00624 if( seqs > MAX_SEQUENCES ) return false; 00625 00626 for( uint i=0; i<co; i++ ) { 00627 const KKeySequence& seq = cut.seq(i); 00628 if(!contains(seq)) { 00629 m_rgseq[m_nSeqs] = seq; 00630 m_nSeqs++; 00631 } 00632 } 00633 return true; 00634 } 00635 00636 KShortcut::operator QKeySequence () const 00637 { 00638 if( count() >= 1 ) 00639 return m_rgseq[0].qt(); 00640 else 00641 return QKeySequence(); 00642 } 00643 00644 QString KShortcut::toString() const 00645 { 00646 QString s; 00647 00648 for( uint i = 0; i < count(); i++ ) { 00649 s += m_rgseq[i].toString(); 00650 if( i < count() - 1 ) 00651 s += ';'; 00652 } 00653 00654 return s; 00655 } 00656 00657 QString KShortcut::toStringInternal( const KShortcut* pcutDefault ) const 00658 { 00659 QString s; 00660 00661 for( uint i = 0; i < count(); i++ ) { 00662 const KKeySequence& seq = m_rgseq[i]; 00663 if( pcutDefault && i < pcutDefault->count() && seq == (*pcutDefault).seq(i) ) { 00664 s += "default("; 00665 s += seq.toStringInternal(); 00666 s += ")"; 00667 } else 00668 s += seq.toStringInternal(); 00669 if( i < count() - 1 ) 00670 s += ';'; 00671 } 00672 00673 return s; 00674 } 00675 00676 KShortcut& KShortcut::null() 00677 { 00678 if( !g_pcut ) 00679 g_pcut = new KShortcut; 00680 if( !g_pcut->isNull() ) 00681 g_pcut->clear(); 00682 return *g_pcut; 00683 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:47:39 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003