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