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_x11.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 struct X
00244 {
00245     uint iAction, iSeq, iVari;
00246     KKeyServer::Key key;
00247 
00248     X() {}
00249     X( uint _iAction, uint _iSeq, uint _iVari, const KKeyServer::Key& _key )
00250         { iAction = _iAction; iSeq = _iSeq; iVari = _iVari; key = _key; }
00251 
00252     int compare( const X& x )
00253     {
00254         int n = key.compare( x.key );
00255         if( n != 0 )           return n;
00256         if( iVari != x.iVari ) return iVari - x.iVari;
00257         if( iSeq != x.iSeq )   return iSeq - x.iSeq;
00258         return 0;
00259     }
00260 
00261     bool operator <( const X& x )  { return compare( x ) < 0; }
00262     bool operator >( const X& x )  { return compare( x ) > 0; }
00263     bool operator <=( const X& x ) { return compare( x ) <= 0; }
00264 };
00265 
00266 /*
00267 #1 Ctrl+A
00268 #2 Ctrl+A
00269 #3 Ctrl+B
00270    ------
00271    Ctrl+A => Null
00272    Ctrl+B => #3
00273 
00274 #1 Ctrl+A
00275 #1 Ctrl+B;Ctrl+A
00276    ------
00277    Ctrl+A => #1
00278    Ctrl+B => #2
00279 
00280 #1 Ctrl+A
00281 #1 Ctrl+B,C
00282 #1 Ctrl+B,D
00283    ------
00284    Ctrl+A => #1
00285    Ctrl+B => Null
00286 
00287 #1 Ctrl+A
00288 #2 Ctrl+Plus(Ctrl+KP_Add)
00289    ------
00290    Ctrl+A => #1
00291    Ctrl+Plus => #2
00292    Ctrl+KP_Add => #2
00293 
00294 #1 Ctrl+Plus(Ctrl+KP_Add)
00295 #2 Ctrl+KP_Add
00296    ------
00297    Ctrl+Plus => #1
00298    Ctrl+KP_Add => #2
00299 
00300 #1 Ctrl+Plus(Ctrl+KP_Add)
00301 #2 Ctrl+A;Ctrl+KP_Add
00302    ------
00303    Ctrl+A => #2
00304    Ctrl+Plus => #1
00305    Ctrl+KP_Add => #2
00306 */
00307 
00308 bool KAccelBase::updateConnections()
00309 {
00310     kdDebug(125) << "KAccelBase::updateConnections()  this = " << this << endl;
00311     // Retrieve the list of keys to be connected, sorted by priority.
00312     //  (key, variation, seq)
00313     QValueVector<X> rgKeys;
00314     createKeyList( rgKeys );
00315     m_rgActionsNonUnique.clear();
00316 
00317     KKeyToActionMap mapKeyToAction;
00318     for( uint i = 0; i < rgKeys.size(); i++ ) {
00319         X& x = rgKeys[i];
00320         KKeyServer::Key& key = x.key;
00321         ActionInfo info;
00322         bool bNonUnique = false;
00323 
00324         info.pAction = m_rgActions.actionPtr( x.iAction );
00325         info.iSeq = x.iSeq;
00326         info.iVariation = x.iVari;
00327 
00328         // If this is a multi-key shortcut,
00329         if( info.pAction->shortcut().seq(info.iSeq).count() > 1 )
00330             bNonUnique = true;
00331         // If this key is requested by more than one action,
00332         else if( i < rgKeys.size() - 1 && key == rgKeys[i+1].key ) {
00333             // If multiple actions requesting this key
00334             //  have the same priority as the first one,
00335             if( info.iVariation == rgKeys[i+1].iVari && info.iSeq == rgKeys[i+1].iSeq )
00336                 bNonUnique = true;
00337 
00338             kdDebug(125) << "key conflict = " << key.key().toStringInternal()
00339                 << " action1 = " << info.pAction->name()
00340                 << " action2 = " << m_rgActions.actionPtr( rgKeys[i+1].iAction )->name() 
00341                 << " non-unique = " << bNonUnique << endl;
00342             
00343             // Skip over the other records with this same key.
00344             while( i < rgKeys.size() - 1 && key == rgKeys[i+1].key )
00345                 i++;
00346         }
00347 
00348         if( bNonUnique ) {
00349             // Remove connection to single action if there is one
00350             if( m_mapKeyToAction.contains( key ) ) {
00351                 KAccelAction* pAction = m_mapKeyToAction[key].pAction;
00352                 if( pAction ) {
00353                     m_mapKeyToAction.remove( key );
00354                     disconnectKey( *pAction, key );
00355                     pAction->decConnections();
00356                     m_rgActionsNonUnique.append( pAction );
00357                 }
00358             }
00359             // Indicate that no single action is associated with this key.
00360             m_rgActionsNonUnique.append( info.pAction );
00361             info.pAction = 0;
00362         }
00363 
00364         //kdDebug(125) << "mapKeyToAction[" << key.toStringInternal() << "] = " << info.pAction << endl;
00365         mapKeyToAction[key] = info;
00366     }
00367 
00368     // Disconnect keys which no longer have bindings:
00369     for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
00370         const KKeyServer::Key& key = it.key();
00371         KAccelAction* pAction = (*it).pAction;
00372         // If this key is longer used or it points to a different action now,
00373         if( !mapKeyToAction.contains( key ) || mapKeyToAction[key].pAction != pAction ) {
00374             if( pAction ) {
00375                 disconnectKey( *pAction, key );
00376                 pAction->decConnections();
00377             } else
00378                 disconnectKey( key );
00379         }
00380     }
00381 
00382     // Connect any unconnected keys:
00383     // In other words, connect any keys which are present in the
00384     //  new action map, but which are _not_ present in the old one.
00385     for( KKeyToActionMap::iterator it = mapKeyToAction.begin(); it != mapKeyToAction.end(); ++it ) {
00386         const KKeyServer::Key& key = it.key();
00387         KAccelAction* pAction = (*it).pAction;
00388         if( !m_mapKeyToAction.contains( key ) || m_mapKeyToAction[key].pAction != pAction ) {
00389             // TODO: Decide what to do if connect fails.
00390             //  Probably should remove this item from map.
00391             if( pAction ) {
00392                 if( connectKey( *pAction, key ) )
00393                     pAction->incConnections();
00394             } else
00395                 connectKey( key );
00396         }
00397     }
00398 
00399     // Store new map.
00400     m_mapKeyToAction = mapKeyToAction;
00401 
00402 #ifndef NDEBUG
00403     for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
00404         kdDebug(125) << "Key: " << it.key().key().toStringInternal() << " => '"
00405             << (((*it).pAction) ? (*it).pAction->name() : QString::null) << "'" << endl;
00406     }
00407 #endif
00408     return true;
00409 }
00410 
00411 // Construct a list of keys to be connected, sorted highest priority first.
00412 void KAccelBase::createKeyList( QValueVector<struct X>& rgKeys )
00413 {
00414     //kdDebug(125) << "KAccelBase::createKeyList()" << endl;
00415     if( !m_bEnabled )
00416         return;
00417 
00418     // create the list
00419     // For each action
00420     for( uint iAction = 0; iAction < m_rgActions.count(); iAction++ ) {
00421         KAccelAction* pAction = m_rgActions.actionPtr( iAction );
00422         if( pAction && pAction->m_pObjSlot && pAction->m_psMethodSlot && pAction != mtemp_pActionRemoving ) {
00423             // For each key sequence associated with action
00424             for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
00425                 const KKeySequence& seq = pAction->shortcut().seq(iSeq);
00426                 if( seq.count() > 0 ) {
00427                     KKeyServer::Variations vars;
00428                     vars.init( seq.key(0), !m_bNativeKeys );
00429                     for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
00430                         if( vars.key(iVari).code() && vars.key(iVari).sym() )
00431                             rgKeys.push_back( X( iAction, iSeq, iVari, vars.key( iVari ) ) );
00432                         //kdDebug(125) << "\t" << pAction->name() << ": " << vars.key(iVari).toStringInternal() << endl;
00433                     }
00434                 }
00435                 //else
00436                 //  kdDebug(125) << "\t*" << pAction->name() << ":" << endl;
00437             }
00438         }
00439     }
00440 
00441     // sort by priority: iVariation[of first key], iSequence, iAction
00442     qHeapSort( rgKeys.begin(), rgKeys.end() );
00443 }
00444 
00445 bool KAccelBase::insertConnection( KAccelAction* pAction )
00446 {
00447     if( !pAction->m_pObjSlot || !pAction->m_psMethodSlot )
00448         return true;
00449 
00450     kdDebug(125) << "KAccelBase::insertConnection( " << pAction << "=\"" << pAction->m_sName << "\"; shortcut = " << pAction->shortcut().toStringInternal() << " )  this = " << this << endl;
00451 
00452     // For each sequence associated with the given action:
00453     for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
00454         // Get the first key of the sequence.
00455         KKeyServer::Variations vars;
00456         vars.init( pAction->shortcut().seq(iSeq).key(0), !m_bNativeKeys );
00457         for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
00458             const KKeyServer::Key& key = vars.key( iVari );
00459 
00460             //if( !key.isNull() ) {
00461             if( key.sym() ) {
00462                 if( !m_mapKeyToAction.contains( key ) ) {
00463                     // If this is a single-key shortcut,
00464                     if( pAction->shortcut().seq(iSeq).count() == 1 ) {
00465                         m_mapKeyToAction[key] = ActionInfo( pAction, iSeq, iVari );
00466                         if( connectKey( *pAction, key ) )
00467                             pAction->incConnections();
00468                     }
00469                     // Else this is a multi-key shortcut,
00470                     else {
00471                         m_mapKeyToAction[key] = ActionInfo( 0, 0, 0 );
00472                         // Insert into non-unique list if it's not already there.
00473                         if( m_rgActionsNonUnique.findIndex( pAction ) == -1 )
00474                             m_rgActionsNonUnique.append( pAction );
00475                         if( connectKey( key ) )
00476                             pAction->incConnections();
00477                     }
00478                 } else {
00479                     // There is a key conflict.  A full update
00480                     //  check is necessary.
00481                     // TODO: make this more efficient where possible.
00482                     if( m_mapKeyToAction[key].pAction != pAction
00483                         && m_mapKeyToAction[key].pAction != 0 ) {
00484                         kdDebug(125) << "Key conflict: call updateConnections():" 
00485                             << " key = " << key.key().toStringInternal() << endl;
00486                         return updateConnections();
00487                     }
00488                 }
00489             }
00490         }
00491     }
00492 
00493     //kdDebug(125) << "\tActions = " << m_rgActions.size() << endl;
00494     //for( KAccelActions::const_iterator it = m_rgActions.begin(); it != m_rgActions.end(); ++it ) {
00495     //  kdDebug(125) << "\t" << &(*it) << " '" << (*it).m_sName << "'" << endl;
00496     //}
00497 
00498     //kdDebug(125) << "\tKeys = " << m_mapKeyToAction.size() << endl;
00499     //for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
00500     //  //kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << (*it)->m_sName << "'" << endl;
00501     //  kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << *it << "'" << endl;
00502     //  kdDebug(125) << "\t\t'" << (*it)->m_sName << "'" << endl;
00503     //}
00504 
00505     return true;
00506 }
00507 
00508 bool KAccelBase::removeConnection( KAccelAction* pAction )
00509 {
00510     kdDebug(125) << "KAccelBase::removeConnection( " << pAction << " = \"" << pAction->m_sName << "\"; shortcut = " << pAction->m_cut.toStringInternal() << " ): this = " << this << endl;
00511 
00512     //for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it )
00513     //  kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << (*it)->m_sName << "'" << " " << *it << endl;
00514 
00515     if( m_rgActionsNonUnique.findIndex( pAction ) >= 0 ) {
00516         mtemp_pActionRemoving = pAction;
00517         bool b = updateConnections();
00518         mtemp_pActionRemoving = 0;
00519         return b;
00520     }
00521 
00522     KKeyToActionMap::iterator it = m_mapKeyToAction.begin();
00523     while( it != m_mapKeyToAction.end() ) {
00524         KKeyServer::Key key = it.key();
00525         ActionInfo* pInfo = &(*it);
00526 
00527         // If the given action is connected to this key,
00528         if( pAction == pInfo->pAction ) {
00529             disconnectKey( *pAction, key );
00530             pAction->decConnections();
00531 
00532             KKeyToActionMap::iterator itRemove = it++;
00533             m_mapKeyToAction.remove( itRemove );
00534         } else
00535             it++;
00536     }
00537     return true;
00538 }
00539 
00540 bool KAccelBase::setShortcut( const QString& sAction, const KShortcut& cut )
00541 {
00542     KAccelAction* pAction = actionPtr( sAction );
00543     if( pAction ) {
00544         if( m_bAutoUpdate )
00545             removeConnection( pAction );
00546 
00547         pAction->setShortcut( cut );
00548 
00549         if( m_bAutoUpdate && !pAction->shortcut().isNull() )
00550             insertConnection( pAction );
00551         return true;
00552     } else
00553         return false;
00554 }
00555 
00556 void KAccelBase::readSettings( KConfigBase* pConfig )
00557 {
00558     m_rgActions.readActions( m_sConfigGroup, pConfig );
00559     if( m_bAutoUpdate )
00560         updateConnections();
00561 }
00562 
00563 void KAccelBase::writeSettings( KConfigBase* pConfig ) const
00564 {
00565     m_rgActions.writeActions( m_sConfigGroup, pConfig, m_bConfigIsGlobal, m_bConfigIsGlobal );
00566 }
00567 
00568 QPopupMenu* KAccelBase::createPopupMenu( QWidget* pParent, const KKeySequence& seq )
00569 {
00570     KShortcutMenu* pMenu = new KShortcutMenu( pParent, &actions(), seq );
00571     
00572     bool bActionInserted = false;
00573     bool bInsertSeparator = false;
00574     for( uint i = 0; i < actionCount(); i++ ) {
00575         const KAccelAction* pAction = actions().actionPtr( i );
00576 
00577         if( !pAction->isEnabled() )
00578             continue;
00579 
00580         // If an action has already been inserted into the menu
00581         //  and we have a label instead of an action here,
00582         //  then indicate that we should insert a separator before the next menu entry.
00583         if( bActionInserted && !pAction->isConfigurable() && pAction->name().contains( ':' ) )
00584             bInsertSeparator = true;
00585 
00586         for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
00587             const KKeySequence& seqAction = pAction->shortcut().seq(iSeq);
00588             if( seqAction.startsWith( seq ) ) {
00589                 if( bInsertSeparator ) {
00590                     pMenu->insertSeparator();
00591                     bInsertSeparator = false;
00592                 }
00593 
00594                 pMenu->insertAction( i, seqAction );
00595 
00596                 //kdDebug(125) << "sLabel = " << sLabel << ", seq = " << (QString)seqMenu.qt() << ", i = " << i << endl;
00597                 //kdDebug(125) << "pMenu->accel(" << i << ") = " << (QString)pMenu->accel(i) << endl;
00598                 bActionInserted = true;
00599                 break;
00600             }
00601         }
00602     }
00603     pMenu->updateShortcuts();
00604     return pMenu;
00605 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:14:45 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001