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 Fri Apr 22 16:00:21 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003