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     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 QString& sSpec )
00107 {
00108     clear();
00109 
00110     QString 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     QStringList rgs = QStringList::split( '+', sKey, true );
00117 
00118     uint i;
00119     // Check for modifier keys first.
00120     for( i = 0; i < rgs.size(); i++ ) {
00121         QString 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 break;
00128     }
00129     // If there is one non-blank key left:
00130     if( (i == rgs.size() - 1 && !rgs[i].isEmpty()) ) {
00131         KKeyServer::Sym sym( rgs[i] );
00132         m_sym = sym.m_sym;
00133     }
00134 
00135     if( m_sym == 0 )
00136     {
00137         if(m_mod==KKey::WIN)
00138             m_sym=0xffeb;
00139         else
00140             m_mod = 0;
00141     }
00142 
00143     kdDebug(125) << "KKey::init( \"" << sSpec << "\" ):"
00144         << " m_sym = " << QString::number(m_sym, 16)
00145         << ", m_mod = " << QString::number(m_mod, 16) << endl;
00146 
00147     return m_sym != 0;
00148 }
00149 
00150 bool KKey::isNull() const          { return m_sym == 0; }
00151 uint KKey::sym() const             { return m_sym; }
00152 uint KKey::modFlags() const        { return m_mod; }
00153 
00154 int KKey::compare( const KKey& spec ) const
00155 {
00156     if( m_sym != spec.m_sym )
00157         return m_sym - spec.m_sym;
00158     if( m_mod != spec.m_mod )
00159         return m_mod - spec.m_mod;
00160     return 0;
00161 }
00162 
00163 int KKey::keyCodeQt() const
00164 {
00165     return KKeyNative( *this ).keyCodeQt();
00166 }
00167 
00168 QString KKey::toString() const
00169 {
00170     QString s;
00171 
00172     s = KKeyServer::modToStringUser( m_mod );
00173     if( !s.isEmpty() )
00174         s += '+';
00175     s += KKeyServer::Sym(m_sym).toString();
00176 
00177     return s;
00178 }
00179 
00180 QString KKey::toStringInternal() const
00181 {
00182     //kdDebug(125) << "KKey::toStringInternal(): this = " << this
00183     //  << " mod = " << QString::number(m_mod, 16)
00184     //  << " key = " << QString::number(m_sym, 16) << endl;
00185     QString s;
00186 
00187     s = KKeyServer::modToStringInternal( m_mod );
00188     if( !s.isEmpty() )
00189         s += '+';
00190     s += KKeyServer::Sym(m_sym).toStringInternal();
00191     return s;
00192 }
00193 
00194 KKey& KKey::null()
00195 {
00196     if( !g_pspec )
00197         g_pspec = new KKey;
00198     if( !g_pspec->isNull() )
00199         g_pspec->clear();
00200     return *g_pspec;
00201 }
00202 
00203 QString KKey::modFlagLabel( ModFlag modFlag )
00204 {
00205     return KKeyServer::modToStringUser( modFlag );
00206 }
00207 
00208 //---------------------------------------------------------------------
00209 // KKeySequence
00210 //---------------------------------------------------------------------
00211 
00212 KKeySequence::KKeySequence()                          { clear(); }
00213 KKeySequence::KKeySequence( const QKeySequence& seq ) { init( seq ); }
00214 KKeySequence::KKeySequence( const KKey& key )         { init( key ); }
00215 KKeySequence::KKeySequence( const KKeySequence& seq ) { init( seq ); }
00216 KKeySequence::KKeySequence( const QString& s )        { init( s ); }
00217 
00218 KKeySequence::~KKeySequence()
00219 {
00220 }
00221 
00222 void KKeySequence::clear()
00223 {
00224     m_nKeys = 0;
00225     m_bTriggerOnRelease = false;
00226 }
00227 
00228 bool KKeySequence::init( const QKeySequence& seq )
00229 {
00230     clear();
00231 #if QT_VERSION >= 0x030100
00232     if( !seq.isEmpty() ) {
00233         for( uint i = 0; i < seq.count(); i++ ) {   
00234             m_rgvar[i].init( seq[i] );
00235             if( m_rgvar[i].isNull() )
00236                 return false;
00237         }
00238         m_nKeys = seq.count();
00239         m_bTriggerOnRelease = false;
00240     }
00241 #else // Qt 3.0.x
00242     if( seq ) {
00243         m_rgvar[ 0 ].init(  seq );
00244         if( !m_rgvar[ 0 ].isNull() ) {
00245             m_nKeys = 1;
00246             m_bTriggerOnRelease = false;
00247         }
00248     }
00249 #endif
00250     return true;
00251 }
00252 
00253 bool KKeySequence::init( const KKey& key )
00254 {
00255     if( !key.isNull() ) {
00256         m_nKeys = 1;
00257         m_rgvar[0].init( key );
00258         m_bTriggerOnRelease = false;
00259     } else
00260         clear();
00261     return true;
00262 }
00263 
00264 bool KKeySequence::init( const KKeySequence& seq )
00265 {
00266     m_bTriggerOnRelease = false;
00267     m_nKeys = seq.m_nKeys;
00268     for( uint i = 0; i < m_nKeys; i++ ) {
00269         if( seq.m_rgvar[i].isNull() ) {
00270             kdWarning(125) << "KKeySequence::init( seq ): key[" << i << "] is null." << endl;
00271             m_nKeys = 0;
00272             return false;
00273         }
00274         m_rgvar[i] = seq.m_rgvar[i];
00275     }
00276     return true;
00277 }
00278 
00279 bool KKeySequence::init( const QString& s )
00280 {
00281     m_bTriggerOnRelease = false;
00282     //kdDebug(125) << "KKeySequence::init( " << s << " )" << endl;
00283     QStringList rgs = QStringList::split( ',', s );
00284     if( s == "none" || rgs.size() == 0 ) {
00285         clear();
00286         return true;
00287     } else if( rgs.size() <= MAX_KEYS ) {
00288         m_nKeys = rgs.size();
00289         for( uint i = 0; i < m_nKeys; i++ ) {
00290             m_rgvar[i].init( KKey(rgs[i]) );
00291             //kdDebug(125) << "\t'" << rgs[i] << "' => " << m_rgvar[i].toStringInternal() << endl;
00292         }
00293         return true;
00294     } else {
00295         clear();
00296         return false;
00297     }
00298 }
00299 
00300 uint KKeySequence::count() const
00301 {
00302     return m_nKeys;
00303 }
00304 
00305 const KKey& KKeySequence::key( uint i ) const
00306 {
00307     if( i < m_nKeys )
00308         return m_rgvar[i];
00309     else
00310         return KKey::null();
00311 }
00312 
00313 bool KKeySequence::isTriggerOnRelease() const
00314     { return m_bTriggerOnRelease; }
00315 
00316 bool KKeySequence::setKey( uint iKey, const KKey& key )
00317 {
00318     if( iKey <= m_nKeys && iKey < MAX_KEYS ) {
00319         m_rgvar[iKey].init( key );
00320         if( iKey == m_nKeys )
00321             m_nKeys++;
00322         return true;
00323     } else
00324         return false;
00325 }
00326 
00327 bool KKeySequence::isNull() const
00328 {
00329     return m_nKeys == 0;
00330 }
00331 
00332 bool KKeySequence::startsWith( const KKeySequence& seq ) const
00333 {
00334     if( m_nKeys < seq.m_nKeys )
00335         return false;
00336 
00337     for( uint i = 0; i < seq.m_nKeys; i++ ) {
00338         if( m_rgvar[i] != seq.m_rgvar[i] )
00339             return false;
00340     }
00341 
00342     return true;
00343 }
00344 
00345 int KKeySequence::compare( const KKeySequence& seq ) const
00346 {
00347     for( uint i = 0; i < m_nKeys && i < seq.m_nKeys; i++ ) {
00348         int ret = m_rgvar[i].compare( seq.m_rgvar[i] );
00349         if( ret != 0 )
00350             return ret;
00351     }
00352     if( m_nKeys != seq.m_nKeys )
00353         return m_nKeys - seq.m_nKeys;
00354     else
00355         return 0;
00356 }
00357 
00358 QKeySequence KKeySequence::qt() const
00359 {
00360     int k[4] = { 0, 0, 0, 0 };
00361     
00362     for( uint i = 0; i < count(); i++ )
00363         k[i] = KKeyNative(key(i)).keyCodeQt();
00364 #if QT_VERSION >= 0x030100
00365     QKeySequence seq( k[0], k[1], k[2], k[3] );
00366 #else // Qt-3.0.x
00367     QKeySequence seq;
00368     if(  count() == 1 )
00369         seq = KKeyNative( key( 0 ) ).keyCodeQt();
00370 #endif
00371     return seq;
00372 }
00373 
00374 int KKeySequence::keyCodeQt() const
00375 {
00376     return (count() == 1) ? KKeyNative(key(0)).keyCodeQt() : 0;
00377 }
00378 
00379 QString KKeySequence::toString() const
00380 {
00381     if( m_nKeys < 1 ) return QString::null;
00382 
00383     QString s;
00384     s = m_rgvar[0].toString();
00385     for( uint i = 1; i < m_nKeys; i++ ) {
00386         s += ",";
00387         s += m_rgvar[i].toString();
00388     }
00389 
00390     return s;
00391 }
00392 
00393 QString KKeySequence::toStringInternal() const
00394 {
00395     if( m_nKeys < 1 ) return QString::null;
00396 
00397     QString s;
00398     s = m_rgvar[0].toStringInternal();
00399     for( uint i = 1; i < m_nKeys; i++ ) {
00400         s += ",";
00401         s += m_rgvar[i].toStringInternal();
00402     }
00403 
00404     return s;
00405 }
00406 
00407 KKeySequence& KKeySequence::null()
00408 {
00409     if( !g_pseq )
00410         g_pseq = new KKeySequence;
00411     if( !g_pseq->isNull() )
00412         g_pseq->clear();
00413     return *g_pseq;
00414 }
00415 
00416 //---------------------------------------------------------------------
00417 // KShortcut
00418 //---------------------------------------------------------------------
00419 
00420 KShortcut::KShortcut()                            { clear(); }
00421 KShortcut::KShortcut( int keyQt )                 { init( keyQt ); }
00422 KShortcut::KShortcut( const QKeySequence& key )   { init( key ); }
00423 KShortcut::KShortcut( const KKey& key )           { init( key ); }
00424 KShortcut::KShortcut( const KKeySequence& seq )   { init( seq ); }
00425 KShortcut::KShortcut( const KShortcut& cut )      { init( cut ); }
00426 KShortcut::KShortcut( const char* ps )            { init( QString(ps) ); }
00427 KShortcut::KShortcut( const QString& s )          { init( s ); }
00428 
00429 KShortcut::~KShortcut()
00430 {
00431 }
00432 
00433 void KShortcut::clear()
00434 {
00435     m_nSeqs = 0;
00436 }
00437 
00438 bool KShortcut::init( int keyQt )
00439 {
00440     if( keyQt ) {
00441         m_nSeqs = 1;
00442         m_rgseq[0].init( QKeySequence(keyQt) );
00443     } else
00444         clear();
00445     return true;
00446 }
00447 
00448 bool KShortcut::init( const QKeySequence& key )
00449 {
00450     m_nSeqs = 1;
00451     m_rgseq[0].init( key );
00452     return true;
00453 }
00454 
00455 bool KShortcut::init( const KKey& spec )
00456 {
00457     m_nSeqs = 1;
00458     m_rgseq[0].init( spec );
00459     return true;
00460 }
00461 
00462 bool KShortcut::init( const KKeySequence& seq )
00463 {
00464     m_nSeqs = 1;
00465     m_rgseq[0] = seq;
00466     return true;
00467 }
00468 
00469 bool KShortcut::init( const KShortcut& cut )
00470 {
00471     m_nSeqs = cut.m_nSeqs;
00472     for( uint i = 0; i < m_nSeqs; i++ )
00473         m_rgseq[i] = cut.m_rgseq[i];
00474     return true;
00475 }
00476 
00477 bool KShortcut::init( const QString& s )
00478 {
00479     bool bRet = true;
00480     QStringList rgs = QStringList::split( ';', s );
00481 
00482     if( s == "none" || rgs.size() == 0 ) 
00483         clear();
00484     else if( rgs.size() <= MAX_SEQUENCES ) {
00485         m_nSeqs = rgs.size();
00486         for( uint i = 0; i < m_nSeqs; i++ ) {
00487             QString& sSeq = rgs[i];
00488             if( sSeq.startsWith( "default(" ) )
00489                 sSeq = sSeq.mid( 8, sSeq.length() - 9 );
00490             m_rgseq[i].init( sSeq );
00491             //kdDebug(125) << "*\t'" << sSeq << "' => " << m_rgseq[i].toStringInternal() << endl;
00492         }
00493     } else {
00494         clear();
00495         bRet = false;
00496     }
00497 
00498     if( !s.isEmpty() ) {
00499         QString sDebug;
00500         QTextStream os( &sDebug, IO_WriteOnly );
00501         os << "KShortcut::init( \"" << s << "\" ): ";
00502         for( uint i = 0; i < m_nSeqs; i++ ) {
00503             os << " m_rgseq[" << i << "]: ";
00504             KKeyServer::Variations vars;
00505             vars.init( m_rgseq[i].key(0), true );
00506             for( uint j = 0; j < vars.count(); j++ )
00507                 os << QString::number(vars.m_rgkey[j].keyCodeQt(),16) << ',';
00508         }
00509         kdDebug(125) << sDebug << endl;
00510     }
00511 
00512     return bRet;
00513 }
00514 
00515 uint KShortcut::count() const
00516 {
00517     return m_nSeqs;
00518 }
00519 
00520 const KKeySequence& KShortcut::seq( uint i ) const
00521 {
00522     return (i < m_nSeqs) ? m_rgseq[i] : KKeySequence::null();
00523 }
00524 
00525 int KShortcut::keyCodeQt() const
00526 {
00527     if( m_nSeqs >= 1 )
00528         return m_rgseq[0].keyCodeQt();
00529     return QKeySequence();
00530 }
00531 
00532 bool KShortcut::isNull() const
00533 {
00534     return m_nSeqs == 0;
00535 }
00536 
00537 int KShortcut::compare( const KShortcut& cut ) const
00538 {
00539     for( uint i = 0; i < m_nSeqs && i < cut.m_nSeqs; i++ ) {
00540         int ret = m_rgseq[i].compare( cut.m_rgseq[i] );
00541         if( ret != 0 )
00542             return ret;
00543     }
00544     return m_nSeqs - cut.m_nSeqs;
00545 }
00546 
00547 bool KShortcut::contains( const KKey& key ) const
00548 {
00549     return contains( KKeySequence(key) );
00550 }
00551 
00552 bool KShortcut::contains( const KKeyNative& keyNative ) const
00553 {
00554     KKey key = keyNative.key();
00555     key.simplify();
00556     
00557     for( uint i = 0; i < count(); i++ ) {
00558         if( !m_rgseq[i].isNull()
00559             && m_rgseq[i].count() == 1
00560             && m_rgseq[i].key(0) == key )
00561             return true;
00562     }
00563     return false;
00564 }
00565 
00566 bool KShortcut::contains( const KKeySequence& seq ) const
00567 {
00568     for( uint i = 0; i < count(); i++ ) {
00569         if( !m_rgseq[i].isNull() && m_rgseq[i] == seq )
00570             return true;
00571     }
00572     return false;
00573 }
00574 
00575 bool KShortcut::setSeq( uint iSeq, const KKeySequence& seq )
00576 {
00577     // TODO: check if seq is null, and act accordingly.
00578     if( iSeq <= m_nSeqs && iSeq < MAX_SEQUENCES ) {
00579         m_rgseq[iSeq] = seq;
00580         if( iSeq == m_nSeqs )
00581             m_nSeqs++;
00582         return true;
00583     } else
00584         return false;
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 KShortcut::operator QKeySequence () const
00600 {
00601     if( count() >= 1 )
00602         return m_rgseq[0].qt();
00603     else
00604         return QKeySequence();
00605 }
00606 
00607 QString KShortcut::toString() const
00608 {
00609     QString s;
00610 
00611     for( uint i = 0; i < count(); i++ ) {
00612         s += m_rgseq[i].toString();
00613         if( i < count() - 1 )
00614             s += ';';
00615     }
00616 
00617     return s;
00618 }
00619 
00620 QString KShortcut::toStringInternal( const KShortcut* pcutDefault ) const
00621 {
00622     QString s;
00623 
00624     for( uint i = 0; i < count(); i++ ) {
00625         const KKeySequence& seq = m_rgseq[i];
00626         if( pcutDefault && i < pcutDefault->count() && seq == (*pcutDefault).seq(i) ) {
00627             s += "default(";
00628             s += seq.toStringInternal();
00629             s += ")";
00630         } else
00631             s += seq.toStringInternal();
00632         if( i < count() - 1 )
00633             s += ';';
00634     }
00635 
00636     return s;
00637 }
00638 
00639 KShortcut& KShortcut::null()
00640 {
00641     if( !g_pcut )
00642         g_pcut = new KShortcut;
00643     if( !g_pcut->isNull() )
00644         g_pcut->clear();
00645     return *g_pcut;
00646 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Mon Oct 24 13:08:18 2011 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001