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.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:18 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001