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