• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kshortcut.cpp

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

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal