kdecore Library API Documentation

kaccelbase.cpp

00001 /*
00002     Copyright (C) 1997-2000 Nicolas Hadacek <hadacek@kde.org>
00003     Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
00004     Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org>
00005     Copyright (c) 2001,2002 Ellis Whitehead <ellis@kde.org>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to
00019     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020     Boston, MA 02111-1307, USA.
00021 */
00022 
00023 #include "kaccelbase.h"
00024 
00025 #include <qkeycode.h>
00026 #include <qlabel.h>
00027 #include <qpopupmenu.h>
00028 
00029 #include <kconfig.h>
00030 #include "kckey.h"
00031 #include <kdebug.h>
00032 #include <kglobal.h>
00033 #include <kkeynative.h>
00034 #include "kkeyserver.h"
00035 #include <klocale.h>
00036 #include "kshortcutmenu.h"
00037 
00038 //---------------------------------------------------------------------
00039 // class KAccelBase::ActionInfo
00040 //---------------------------------------------------------------------
00041 
00042 //---------------------------------------------------------------------
00043 // class KAccelBase
00044 //---------------------------------------------------------------------
00045 
00046 KAccelBase::KAccelBase( int fInitCode )
00047 :   m_rgActions( this )
00048 {
00049     kdDebug(125) << "KAccelBase(): this = " << this << endl;
00050     m_bNativeKeys = fInitCode & NATIVE_KEYS;
00051     m_bEnabled = true;
00052     m_sConfigGroup = "Shortcuts";
00053     m_bConfigIsGlobal = false;
00054     m_bAutoUpdate = false;
00055     mtemp_pActionRemoving = 0;
00056 }
00057 
00058 KAccelBase::~KAccelBase()
00059 {
00060     kdDebug(125) << "~KAccelBase(): this = " << this << endl;
00061 }
00062 
00063 uint KAccelBase::actionCount() const { return m_rgActions.count(); }
00064 KAccelActions& KAccelBase::actions() { return m_rgActions; }
00065 bool KAccelBase::isEnabled() const { return m_bEnabled; }
00066 
00067 KAccelAction* KAccelBase::actionPtr( const QString& sAction )
00068     { return m_rgActions.actionPtr( sAction ); }
00069 
00070 const KAccelAction* KAccelBase::actionPtr( const QString& sAction ) const
00071     { return m_rgActions.actionPtr( sAction ); }
00072 
00073 KAccelAction* KAccelBase::actionPtr( const KKeyServer::Key& key )
00074 {
00075     if( !m_mapKeyToAction.contains( key ) )
00076         return 0;
00077     // Note: If more than one action is connected to a single key, nil will be returned.
00078     return m_mapKeyToAction[key].pAction;
00079 }
00080 
00081 KAccelAction* KAccelBase::actionPtr( const KKey& key )
00082 {
00083     KKeyServer::Key k2;
00084     k2.init( key, !m_bNativeKeys );
00085     return actionPtr( k2 );
00086 }
00087 
00088 void KAccelBase::setConfigGroup( const QString& sConfigGroup )
00089     { m_sConfigGroup = sConfigGroup; }
00090 
00091 void KAccelBase::setConfigGlobal( bool global )
00092     { m_bConfigIsGlobal = global; }
00093 
00094 bool KAccelBase::setActionEnabled( const QString& sAction, bool bEnable )
00095 {
00096     KAccelAction* pAction = actionPtr( sAction );
00097     if( pAction ) {
00098         if( pAction->m_bEnabled != bEnable ) {
00099             kdDebug(125) << "KAccelBase::setActionEnabled( " << sAction << ", " << bEnable << " )" << endl;
00100             pAction->m_bEnabled = bEnable;
00101             if( m_bAutoUpdate ) {
00102                 // FIXME: the action may already have it's connections inserted!
00103                 if( bEnable )
00104                     insertConnection( pAction );
00105                 else if( pAction->isConnected() )
00106                     removeConnection( pAction );
00107             }
00108         }
00109         return true;
00110     }
00111     return false;
00112 }
00113 
00114 bool KAccelBase::setAutoUpdate( bool bAuto )
00115 {
00116     kdDebug(125) << "KAccelBase::setAutoUpdate( " << bAuto << " ): m_bAutoUpdate on entrance = " << m_bAutoUpdate << endl;
00117     bool b = m_bAutoUpdate;
00118     if( !m_bAutoUpdate && bAuto )
00119         updateConnections();
00120     m_bAutoUpdate = bAuto;
00121     return b;
00122 }
00123 
00124 KAccelAction* KAccelBase::insert( const QString& sAction, const QString& sDesc, const QString& sHelp,
00125             const KShortcut& rgCutDefaults3, const KShortcut& rgCutDefaults4,
00126             const QObject* pObjSlot, const char* psMethodSlot,
00127             bool bConfigurable, bool bEnabled )
00128 {
00129     //kdDebug(125) << "KAccelBase::insert() begin" << endl;
00130     KAccelAction* pAction = m_rgActions.insert(
00131         sAction, sDesc, sHelp,
00132         rgCutDefaults3, rgCutDefaults4,
00133         pObjSlot, psMethodSlot,
00134         bConfigurable, bEnabled );
00135 
00136     if( pAction && m_bAutoUpdate )
00137         insertConnection( pAction );
00138 
00139     //kdDebug(125) << "KAccelBase::insert() end" << endl;
00140     return pAction;
00141 }
00142 
00143 KAccelAction* KAccelBase::insert( const QString& sName, const QString& sDesc )
00144     { return m_rgActions.insert( sName, sDesc ); }
00145 
00146 bool KAccelBase::remove( const QString& sAction )
00147 {
00148     return m_rgActions.remove( sAction );
00149 }
00150 
00151 void KAccelBase::slotRemoveAction( KAccelAction* pAction )
00152 {
00153     removeConnection( pAction );
00154 }
00155 
00156 bool KAccelBase::setActionSlot( const QString& sAction, const QObject* pObjSlot, const char* psMethodSlot )
00157 {
00158     kdDebug(125) << "KAccelBase::setActionSlot( " << sAction << ", " << pObjSlot << ", " << psMethodSlot << " )\n";
00159     KAccelAction* pAction = m_rgActions.actionPtr( sAction );
00160     if( pAction ) {
00161         // If there was a previous connection, remove it.
00162         if( m_bAutoUpdate && pAction->isConnected() ) {
00163             kdDebug(125) << "\tm_pObjSlot = " << pAction->m_pObjSlot << " m_psMethodSlot = " << pAction->m_psMethodSlot << endl;
00164             removeConnection( pAction );
00165         }
00166 
00167         pAction->m_pObjSlot = pObjSlot;
00168         pAction->m_psMethodSlot = psMethodSlot;
00169 
00170         // If we're setting a connection,
00171         if( m_bAutoUpdate && pObjSlot && psMethodSlot )
00172             insertConnection( pAction );
00173 
00174         return true;
00175     } else
00176         return false;
00177 }
00178 
00179 /*
00180 KAccelBase
00181     Run Command=Meta+Enter;Alt+F2
00182     KAccelAction = "Run Command"
00183         1) KAccelKeySeries = "Meta+Enter"
00184             1a) Meta+Enter
00185             1b) Meta+Keypad_Enter
00186         2) KAccelKeySeries = "Alt+F2"
00187             1a) Alt+F2
00188 
00189     Konqueror=Meta+I,I
00190     KAccelAction = "Konqueror"
00191         1) KAccelKeySeries = "Meta+I,I"
00192             1a) Meta+I
00193             2a) I
00194 
00195     Something=Meta+Asterisk,X
00196     KAccelAction = "Something"
00197         1) KAccelKeySeries = "Meta+Asterisk,X"
00198             1a) Meta+Shift+8
00199             1b) Meta+Keypad_8
00200             2a) X
00201 
00202 read in a config entry
00203     split by ';'
00204     find key sequences to disconnect
00205     find new key sequences to connect
00206 check for conflicts with implicit keys
00207     disconnect conflicting implicit keys
00208 connect new key sequences
00209 */
00210 /*
00211 {
00212     For {
00213         for( KAccelAction::iterator itAction = m_rgActions.begin(); itAction != m_rgActions.end(); ++itAction ) {
00214             KAccelAction& action = *itAction;
00215             for( KAccelSeries::iterator itSeries = action.m_rgSeries.begin(); itSeries != action.m_rgSeries.end(); ++itSeries ) {
00216                 KAccelSeries& series = *itSeries;
00217                 if(
00218             }
00219         }
00220     }
00221     Sort by: iVariation, iSequence, iSeries, iAction
00222 
00223     1) KAccelAction = "Run Command"
00224         1) KAccelKeySeries = "Meta+Enter"
00225             1a) Meta+Enter
00226             1b) Meta+Keypad_Enter
00227         2) KAccelKeySeries = "Alt+F2"
00228             1a) Alt+F2
00229 
00230     2) KAccelAction = "Enter Calculation"
00231         1) KAccelKeySeries = "Meta+Keypad_Enter"
00232             1a) Meta+Keypad_Enter
00233 
00234     List =
00235         Meta+Enter      -> 1, 1, 1a
00236         Meta+Keypad_Enter   -> 2, 1, 1a
00237         Alt+F2          -> 1, 2, 1a
00238         [Meta+Keypad_Enter] -> [1, 1, 1b]
00239 
00240 }
00241 */
00242 
00243 #ifdef Q_WS_X11
00244 struct KAccelBase::X
00245 {
00246     uint iAction, iSeq, iVari;
00247     KKeyServer::Key key;
00248 
00249     X() {}
00250     X( uint _iAction, uint _iSeq, uint _iVari, const KKeyServer::Key& _key )
00251         { iAction = _iAction; iSeq = _iSeq; iVari = _iVari; key = _key; }
00252 
00253     int compare( const X& x )
00254     {
00255         int n = key.compare( x.key );
00256         if( n != 0 )           return n;
00257         if( iVari != x.iVari ) return iVari - x.iVari;
00258         if( iSeq != x.iSeq )   return iSeq - x.iSeq;
00259         return 0;
00260     }
00261 
00262     bool operator <( const X& x )  { return compare( x ) < 0; }
00263     bool operator >( const X& x )  { return compare( x ) > 0; }
00264     bool operator <=( const X& x ) { return compare( x ) <= 0; }
00265 };
00266 #endif //Q_WS_X11
00267 
00268 /*
00269 #1 Ctrl+A
00270 #2 Ctrl+A
00271 #3 Ctrl+B
00272    ------
00273    Ctrl+A => Null
00274    Ctrl+B => #3
00275 
00276 #1 Ctrl+A
00277 #1 Ctrl+B;Ctrl+A
00278    ------
00279    Ctrl+A => #1
00280    Ctrl+B => #2
00281 
00282 #1 Ctrl+A
00283 #1 Ctrl+B,C
00284 #1 Ctrl+B,D
00285    ------
00286    Ctrl+A => #1
00287    Ctrl+B => Null
00288 
00289 #1 Ctrl+A
00290 #2 Ctrl+Plus(Ctrl+KP_Add)
00291    ------
00292    Ctrl+A => #1
00293    Ctrl+Plus => #2
00294    Ctrl+KP_Add => #2
00295 
00296 #1 Ctrl+Plus(Ctrl+KP_Add)
00297 #2 Ctrl+KP_Add
00298    ------
00299    Ctrl+Plus => #1
00300    Ctrl+KP_Add => #2
00301 
00302 #1 Ctrl+Plus(Ctrl+KP_Add)
00303 #2 Ctrl+A;Ctrl+KP_Add
00304    ------
00305    Ctrl+A => #2
00306    Ctrl+Plus => #1
00307    Ctrl+KP_Add => #2
00308 */
00309 
00310 bool KAccelBase::updateConnections()
00311 {
00312 #ifdef Q_WS_X11
00313     kdDebug(125) << "KAccelBase::updateConnections()  this = " << this << endl;
00314     // Retrieve the list of keys to be connected, sorted by priority.
00315     //  (key, variation, seq)
00316     QValueVector<X> rgKeys;
00317     createKeyList( rgKeys );
00318     m_rgActionsNonUnique.clear();
00319 
00320     KKeyToActionMap mapKeyToAction;
00321     for( uint i = 0; i < rgKeys.size(); i++ ) {
00322         X& x = rgKeys[i];
00323         KKeyServer::Key& key = x.key;
00324         ActionInfo info;
00325         bool bNonUnique = false;
00326 
00327         info.pAction = m_rgActions.actionPtr( x.iAction );
00328         info.iSeq = x.iSeq;
00329         info.iVariation = x.iVari;
00330 
00331         // If this is a multi-key shortcut,
00332         if( info.pAction->shortcut().seq(info.iSeq).count() > 1 )
00333             bNonUnique = true;
00334         // If this key is requested by more than one action,
00335         else if( i < rgKeys.size() - 1 && key == rgKeys[i+1].key ) {
00336             // If multiple actions requesting this key
00337             //  have the same priority as the first one,
00338             if( info.iVariation == rgKeys[i+1].iVari && info.iSeq == rgKeys[i+1].iSeq )
00339                 bNonUnique = true;
00340 
00341             kdDebug(125) << "key conflict = " << key.key().toStringInternal()
00342                 << " action1 = " << info.pAction->name()
00343                 << " action2 = " << m_rgActions.actionPtr( rgKeys[i+1].iAction )->name()
00344                 << " non-unique = " << bNonUnique << endl;
00345 
00346             // Skip over the other records with this same key.
00347             while( i < rgKeys.size() - 1 && key == rgKeys[i+1].key )
00348                 i++;
00349         }
00350 
00351         if( bNonUnique ) {
00352             // Remove connection to single action if there is one
00353             if( m_mapKeyToAction.contains( key ) ) {
00354                 KAccelAction* pAction = m_mapKeyToAction[key].pAction;
00355                 if( pAction ) {
00356                     m_mapKeyToAction.remove( key );
00357                     disconnectKey( *pAction, key );
00358                     pAction->decConnections();
00359                     m_rgActionsNonUnique.append( pAction );
00360                 }
00361             }
00362             // Indicate that no single action is associated with this key.
00363             m_rgActionsNonUnique.append( info.pAction );
00364             info.pAction = 0;
00365         }
00366 
00367         //kdDebug(125) << "mapKeyToAction[" << key.toStringInternal() << "] = " << info.pAction << endl;
00368         mapKeyToAction[key] = info;
00369     }
00370 
00371     // Disconnect keys which no longer have bindings:
00372     for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
00373         const KKeyServer::Key& key = it.key();
00374         KAccelAction* pAction = (*it).pAction;
00375         // If this key is longer used or it points to a different action now,
00376         if( !mapKeyToAction.contains( key ) || mapKeyToAction[key].pAction != pAction ) {
00377             if( pAction ) {
00378                 disconnectKey( *pAction, key );
00379                 pAction->decConnections();
00380             } else
00381                 disconnectKey( key );
00382         }
00383     }
00384 
00385     // Connect any unconnected keys:
00386     // In other words, connect any keys which are present in the
00387     //  new action map, but which are _not_ present in the old one.
00388     for( KKeyToActionMap::iterator it = mapKeyToAction.begin(); it != mapKeyToAction.end(); ++it ) {
00389         const KKeyServer::Key& key = it.key();
00390         KAccelAction* pAction = (*it).pAction;
00391         if( !m_mapKeyToAction.contains( key ) || m_mapKeyToAction[key].pAction != pAction ) {
00392             // TODO: Decide what to do if connect fails.
00393             //  Probably should remove this item from map.
00394             if( pAction ) {
00395                 if( connectKey( *pAction, key ) )
00396                     pAction->incConnections();
00397             } else
00398                 connectKey( key );
00399         }
00400     }
00401 
00402     // Store new map.
00403     m_mapKeyToAction = mapKeyToAction;
00404 
00405 #ifndef NDEBUG
00406     for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
00407         kdDebug(125) << "Key: " << it.key().key().toStringInternal() << " => '"
00408             << (((*it).pAction) ? (*it).pAction->name() : QString::null) << "'" << endl;
00409     }
00410 #endif
00411 #endif //Q_WS_X11
00412     return true;
00413 }
00414 
00415 #ifdef Q_WS_X11
00416 // Construct a list of keys to be connected, sorted highest priority first.
00417 void KAccelBase::createKeyList( QValueVector<struct X>& rgKeys )
00418 {
00419     //kdDebug(125) << "KAccelBase::createKeyList()" << endl;
00420     if( !m_bEnabled )
00421         return;
00422 
00423     // create the list
00424     // For each action
00425     for( uint iAction = 0; iAction < m_rgActions.count(); iAction++ ) {
00426         KAccelAction* pAction = m_rgActions.actionPtr( iAction );
00427         if( pAction && pAction->m_pObjSlot && pAction->m_psMethodSlot && pAction != mtemp_pActionRemoving ) {
00428             // For each key sequence associated with action
00429             for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
00430                 const KKeySequence& seq = pAction->shortcut().seq(iSeq);
00431                 if( seq.count() > 0 ) {
00432                     KKeyServer::Variations vars;
00433                     vars.init( seq.key(0), !m_bNativeKeys );
00434                     for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
00435                         if( vars.key(iVari).code() && vars.key(iVari).sym() )
00436                             rgKeys.push_back( X( iAction, iSeq, iVari, vars.key( iVari ) ) );
00437                         //kdDebug(125) << "\t" << pAction->name() << ": " << vars.key(iVari).toStringInternal() << endl;
00438                     }
00439                 }
00440                 //else
00441                 //  kdDebug(125) << "\t*" << pAction->name() << ":" << endl;
00442             }
00443         }
00444     }
00445 
00446     // sort by priority: iVariation[of first key], iSequence, iAction
00447     qHeapSort( rgKeys.begin(), rgKeys.end() );
00448 }
00449 #endif //Q_WS_X11
00450 
00451 bool KAccelBase::insertConnection( KAccelAction* pAction )
00452 {
00453     if( !pAction->m_pObjSlot || !pAction->m_psMethodSlot )
00454         return true;
00455 
00456     kdDebug(125) << "KAccelBase::insertConnection( " << pAction << "=\"" << pAction->m_sName << "\"; shortcut = " << pAction->shortcut().toStringInternal() << " )  this = " << this << endl;
00457 
00458     // For each sequence associated with the given action:
00459     for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
00460         // Get the first key of the sequence.
00461         KKeyServer::Variations vars;
00462         vars.init( pAction->shortcut().seq(iSeq).key(0), !m_bNativeKeys );
00463         for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
00464             const KKeyServer::Key& key = vars.key( iVari );
00465 
00466             //if( !key.isNull() ) {
00467             if( key.sym() ) {
00468                 if( !m_mapKeyToAction.contains( key ) ) {
00469                     // If this is a single-key shortcut,
00470                     if( pAction->shortcut().seq(iSeq).count() == 1 ) {
00471                         m_mapKeyToAction[key] = ActionInfo( pAction, iSeq, iVari );
00472                         if( connectKey( *pAction, key ) )
00473                             pAction->incConnections();
00474                     }
00475                     // Else this is a multi-key shortcut,
00476                     else {
00477                         m_mapKeyToAction[key] = ActionInfo( 0, 0, 0 );
00478                         // Insert into non-unique list if it's not already there.
00479                         if( m_rgActionsNonUnique.findIndex( pAction ) == -1 )
00480                             m_rgActionsNonUnique.append( pAction );
00481                         if( connectKey( key ) )
00482                             pAction->incConnections();
00483                     }
00484                 } else {
00485                     // There is a key conflict.  A full update
00486                     //  check is necessary.
00487                     // TODO: make this more efficient where possible.
00488                     if( m_mapKeyToAction[key].pAction != pAction
00489                         && m_mapKeyToAction[key].pAction != 0 ) {
00490                         kdDebug(125) << "Key conflict with action = " << m_mapKeyToAction[key].pAction->name() 
00491                             << " key = " << key.key().toStringInternal() << " : call updateConnections()" << endl;
00492                         return updateConnections();
00493                     }
00494                 }
00495             }
00496         }
00497     }
00498 
00499     //kdDebug(125) << "\tActions = " << m_rgActions.size() << endl;
00500     //for( KAccelActions::const_iterator it = m_rgActions.begin(); it != m_rgActions.end(); ++it ) {
00501     //  kdDebug(125) << "\t" << &(*it) << " '" << (*it).m_sName << "'" << endl;
00502     //}
00503 
00504     //kdDebug(125) << "\tKeys = " << m_mapKeyToAction.size() << endl;
00505     //for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
00506     //  //kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << (*it)->m_sName << "'" << endl;
00507     //  kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << *it << "'" << endl;
00508     //  kdDebug(125) << "\t\t'" << (*it)->m_sName << "'" << endl;
00509     //}
00510 
00511     return true;
00512 }
00513 
00514 bool KAccelBase::removeConnection( KAccelAction* pAction )
00515 {
00516     kdDebug(125) << "KAccelBase::removeConnection( " << pAction << " = \"" << pAction->m_sName << "\"; shortcut = " << pAction->m_cut.toStringInternal() << " ): this = " << this << endl;
00517 
00518     //for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it )
00519     //  kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << (*it)->m_sName << "'" << " " << *it << endl;
00520 
00521     if( m_rgActionsNonUnique.findIndex( pAction ) >= 0 ) {
00522         mtemp_pActionRemoving = pAction;
00523         bool b = updateConnections();
00524         mtemp_pActionRemoving = 0;
00525         return b;
00526     }
00527 
00528     KKeyToActionMap::iterator it = m_mapKeyToAction.begin();
00529     while( it != m_mapKeyToAction.end() ) {
00530         KKeyServer::Key key = it.key();
00531         ActionInfo* pInfo = &(*it);
00532 
00533         // If the given action is connected to this key,
00534         if( pAction == pInfo->pAction ) {
00535             disconnectKey( *pAction, key );
00536             pAction->decConnections();
00537 
00538             KKeyToActionMap::iterator itRemove = it++;
00539             m_mapKeyToAction.remove( itRemove );
00540         } else
00541             ++it;
00542     }
00543     return true;
00544 }
00545 
00546 bool KAccelBase::setShortcut( const QString& sAction, const KShortcut& cut )
00547 {
00548     KAccelAction* pAction = actionPtr( sAction );
00549     if( pAction ) {
00550         if( m_bAutoUpdate )
00551             removeConnection( pAction );
00552 
00553         pAction->setShortcut( cut );
00554 
00555         if( m_bAutoUpdate && !pAction->shortcut().isNull() )
00556             insertConnection( pAction );
00557         return true;
00558     } else
00559         return false;
00560 }
00561 
00562 void KAccelBase::readSettings( KConfigBase* pConfig )
00563 {
00564     m_rgActions.readActions( m_sConfigGroup, pConfig );
00565     if( m_bAutoUpdate )
00566         updateConnections();
00567 }
00568 
00569 void KAccelBase::writeSettings( KConfigBase* pConfig ) const
00570 {
00571     m_rgActions.writeActions( m_sConfigGroup, pConfig, m_bConfigIsGlobal, m_bConfigIsGlobal );
00572 }
00573 
00574 QPopupMenu* KAccelBase::createPopupMenu( QWidget* pParent, const KKeySequence& seq )
00575 {
00576     KShortcutMenu* pMenu = new KShortcutMenu( pParent, &actions(), seq );
00577 
00578     bool bActionInserted = false;
00579     bool bInsertSeparator = false;
00580     for( uint i = 0; i < actionCount(); i++ ) {
00581         const KAccelAction* pAction = actions().actionPtr( i );
00582 
00583         if( !pAction->isEnabled() )
00584             continue;
00585 
00586         // If an action has already been inserted into the menu
00587         //  and we have a label instead of an action here,
00588         //  then indicate that we should insert a separator before the next menu entry.
00589         if( bActionInserted && !pAction->isConfigurable() && pAction->name().contains( ':' ) )
00590             bInsertSeparator = true;
00591 
00592         for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
00593             const KKeySequence& seqAction = pAction->shortcut().seq(iSeq);
00594             if( seqAction.startsWith( seq ) ) {
00595                 if( bInsertSeparator ) {
00596                     pMenu->insertSeparator();
00597                     bInsertSeparator = false;
00598                 }
00599 
00600                 pMenu->insertAction( i, seqAction );
00601 
00602                 //kdDebug(125) << "sLabel = " << sLabel << ", seq = " << (QString)seqMenu.qt() << ", i = " << i << endl;
00603                 //kdDebug(125) << "pMenu->accel(" << i << ") = " << (QString)pMenu->accel(i) << endl;
00604                 bActionInserted = true;
00605                 break;
00606             }
00607         }
00608     }
00609     pMenu->updateShortcuts();
00610     return pMenu;
00611 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 16 06:46:35 2005 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003