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.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:03:25 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003