summaryrefslogtreecommitdiffstats
path: root/tdecore/tdeaccelbase.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-02-01 17:25:43 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-02-01 17:25:43 -0600
commitd888cfa39e8b38abe17f3d425d19cb8235136a79 (patch)
tree7ae5487b84106036fdb781beec26fab10678a595 /tdecore/tdeaccelbase.cpp
parentdeac2ca49faed824fe83066080714eb6d653615b (diff)
downloadtdelibs-d888cfa39e8b38abe17f3d425d19cb8235136a79.tar.gz
tdelibs-d888cfa39e8b38abe17f3d425d19cb8235136a79.zip
Fix FTBFS
Diffstat (limited to 'tdecore/tdeaccelbase.cpp')
-rw-r--r--tdecore/tdeaccelbase.cpp616
1 files changed, 616 insertions, 0 deletions
diff --git a/tdecore/tdeaccelbase.cpp b/tdecore/tdeaccelbase.cpp
new file mode 100644
index 000000000..235803134
--- /dev/null
+++ b/tdecore/tdeaccelbase.cpp
@@ -0,0 +1,616 @@
+/*
+ Copyright (C) 1997-2000 Nicolas Hadacek <hadacek@kde.org>
+ Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
+ Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org>
+ Copyright (c) 2001,2002 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kaccelbase.h"
+
+#include <tqkeycode.h>
+#include <tqlabel.h>
+#include <tqpopupmenu.h>
+
+#include <tdeconfig.h>
+#include "kckey.h"
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kkeynative.h>
+#include "kkeyserver.h"
+#include <klocale.h>
+#include "kshortcutmenu.h"
+
+//---------------------------------------------------------------------
+// class TDEAccelBase::ActionInfo
+//---------------------------------------------------------------------
+
+//---------------------------------------------------------------------
+// class TDEAccelBase
+//---------------------------------------------------------------------
+
+TDEAccelBase::TDEAccelBase( int fInitCode )
+: m_rgActions( this )
+{
+ kdDebug(125) << "TDEAccelBase(): this = " << this << endl;
+ m_bNativeKeys = fInitCode & NATIVE_KEYS;
+ m_bEnabled = true;
+ m_sConfigGroup = "Shortcuts";
+ m_bConfigIsGlobal = false;
+ m_bAutoUpdate = false;
+ mtemp_pActionRemoving = 0;
+}
+
+TDEAccelBase::~TDEAccelBase()
+{
+ kdDebug(125) << "~TDEAccelBase(): this = " << this << endl;
+}
+
+uint TDEAccelBase::actionCount() const { return m_rgActions.count(); }
+TDEAccelActions& TDEAccelBase::actions() { return m_rgActions; }
+bool TDEAccelBase::isEnabled() const { return m_bEnabled; }
+// see TDEGlobalAccel::blockShortcuts() stuff - it's to temporarily block
+// all global shortcuts, so that the key grabs are released, but from the app's
+// point of view the TDEGlobalAccel is still enabled, so TDEGlobalAccel needs
+// to disable key grabbing even if enabled
+bool TDEAccelBase::isEnabledInternal() const { return isEnabled(); }
+
+TDEAccelAction* TDEAccelBase::actionPtr( const TQString& sAction )
+ { return m_rgActions.actionPtr( sAction ); }
+
+const TDEAccelAction* TDEAccelBase::actionPtr( const TQString& sAction ) const
+ { return m_rgActions.actionPtr( sAction ); }
+
+TDEAccelAction* TDEAccelBase::actionPtr( const KKeyServer::Key& key )
+{
+ if( !m_mapKeyToAction.contains( key ) )
+ return 0;
+ // Note: If more than one action is connected to a single key, nil will be returned.
+ return m_mapKeyToAction[key].pAction;
+}
+
+TDEAccelAction* TDEAccelBase::actionPtr( const KKey& key )
+{
+ KKeyServer::Key k2;
+ k2.init( key, !m_bNativeKeys );
+ return actionPtr( k2 );
+}
+
+void TDEAccelBase::setConfigGroup( const TQString& sConfigGroup )
+ { m_sConfigGroup = sConfigGroup; }
+
+void TDEAccelBase::setConfigGlobal( bool global )
+ { m_bConfigIsGlobal = global; }
+
+bool TDEAccelBase::setActionEnabled( const TQString& sAction, bool bEnable )
+{
+ TDEAccelAction* pAction = actionPtr( sAction );
+ if( pAction ) {
+ if( pAction->m_bEnabled != bEnable ) {
+ kdDebug(125) << "TDEAccelBase::setActionEnabled( " << sAction << ", " << bEnable << " )" << endl;
+ pAction->m_bEnabled = bEnable;
+ if( m_bAutoUpdate ) {
+ // FIXME: the action may already have it's connections inserted!
+ if( bEnable )
+ insertConnection( pAction );
+ else if( pAction->isConnected() )
+ removeConnection( pAction );
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool TDEAccelBase::setAutoUpdate( bool bAuto )
+{
+ kdDebug(125) << "TDEAccelBase::setAutoUpdate( " << bAuto << " ): m_bAutoUpdate on entrance = " << m_bAutoUpdate << endl;
+ bool b = m_bAutoUpdate;
+ if( !m_bAutoUpdate && bAuto )
+ updateConnections();
+ m_bAutoUpdate = bAuto;
+ return b;
+}
+
+TDEAccelAction* TDEAccelBase::insert( const TQString& sAction, const TQString& sDesc, const TQString& sHelp,
+ const TDEShortcut& rgCutDefaults3, const TDEShortcut& rgCutDefaults4,
+ const TQObject* pObjSlot, const char* psMethodSlot,
+ bool bConfigurable, bool bEnabled )
+{
+ //kdDebug(125) << "TDEAccelBase::insert() begin" << endl;
+ TDEAccelAction* pAction = m_rgActions.insert(
+ sAction, sDesc, sHelp,
+ rgCutDefaults3, rgCutDefaults4,
+ pObjSlot, psMethodSlot,
+ bConfigurable, bEnabled );
+
+ if( pAction && m_bAutoUpdate )
+ insertConnection( pAction );
+
+ //kdDebug(125) << "TDEAccelBase::insert() end" << endl;
+ return pAction;
+}
+
+TDEAccelAction* TDEAccelBase::insert( const TQString& sName, const TQString& sDesc )
+ { return m_rgActions.insert( sName, sDesc ); }
+
+bool TDEAccelBase::remove( const TQString& sAction )
+{
+ return m_rgActions.remove( sAction );
+}
+
+void TDEAccelBase::slotRemoveAction( TDEAccelAction* pAction )
+{
+ removeConnection( pAction );
+}
+
+bool TDEAccelBase::setActionSlot( const TQString& sAction, const TQObject* pObjSlot, const char* psMethodSlot )
+{
+ kdDebug(125) << "TDEAccelBase::setActionSlot( " << sAction << ", " << pObjSlot << ", " << psMethodSlot << " )\n";
+ TDEAccelAction* pAction = m_rgActions.actionPtr( sAction );
+ if( pAction ) {
+ // If there was a previous connection, remove it.
+ if( m_bAutoUpdate && pAction->isConnected() ) {
+ kdDebug(125) << "\tm_pObjSlot = " << pAction->m_pObjSlot << " m_psMethodSlot = " << pAction->m_psMethodSlot << endl;
+ removeConnection( pAction );
+ }
+
+ pAction->m_pObjSlot = pObjSlot;
+ pAction->m_psMethodSlot = psMethodSlot;
+
+ // If we're setting a connection,
+ if( m_bAutoUpdate && pObjSlot && psMethodSlot )
+ insertConnection( pAction );
+
+ return true;
+ } else
+ return false;
+}
+
+/*
+TDEAccelBase
+ Run Command=Meta+Enter;Alt+F2
+ TDEAccelAction = "Run Command"
+ 1) TDEAccelKeySeries = "Meta+Enter"
+ 1a) Meta+Enter
+ 1b) Meta+Keypad_Enter
+ 2) TDEAccelKeySeries = "Alt+F2"
+ 1a) Alt+F2
+
+ Konqueror=Meta+I,I
+ TDEAccelAction = "Konqueror"
+ 1) TDEAccelKeySeries = "Meta+I,I"
+ 1a) Meta+I
+ 2a) I
+
+ Something=Meta+Asterisk,X
+ TDEAccelAction = "Something"
+ 1) TDEAccelKeySeries = "Meta+Asterisk,X"
+ 1a) Meta+Shift+8
+ 1b) Meta+Keypad_8
+ 2a) X
+
+read in a config entry
+ split by ';'
+ find key sequences to disconnect
+ find new key sequences to connect
+check for conflicts with implicit keys
+ disconnect conflicting implicit keys
+connect new key sequences
+*/
+/*
+{
+ For {
+ for( TDEAccelAction::iterator itAction = m_rgActions.begin(); itAction != m_rgActions.end(); ++itAction ) {
+ TDEAccelAction& action = *itAction;
+ for( TDEAccelSeries::iterator itSeries = action.m_rgSeries.begin(); itSeries != action.m_rgSeries.end(); ++itSeries ) {
+ TDEAccelSeries& series = *itSeries;
+ if(
+ }
+ }
+ }
+ Sort by: iVariation, iSequence, iSeries, iAction
+
+ 1) TDEAccelAction = "Run Command"
+ 1) TDEAccelKeySeries = "Meta+Enter"
+ 1a) Meta+Enter
+ 1b) Meta+Keypad_Enter
+ 2) TDEAccelKeySeries = "Alt+F2"
+ 1a) Alt+F2
+
+ 2) TDEAccelAction = "Enter Calculation"
+ 1) TDEAccelKeySeries = "Meta+Keypad_Enter"
+ 1a) Meta+Keypad_Enter
+
+ List =
+ Meta+Enter -> 1, 1, 1a
+ Meta+Keypad_Enter -> 2, 1, 1a
+ Alt+F2 -> 1, 2, 1a
+ [Meta+Keypad_Enter] -> [1, 1, 1b]
+
+}
+*/
+
+#ifdef Q_WS_X11
+struct TDEAccelBase::X
+{
+ uint iAction, iSeq, iVari;
+ KKeyServer::Key key;
+
+ X() {}
+ X( uint _iAction, uint _iSeq, uint _iVari, const KKeyServer::Key& _key )
+ { iAction = _iAction; iSeq = _iSeq; iVari = _iVari; key = _key; }
+
+ int compare( const X& x )
+ {
+ int n = key.compare( x.key );
+ if( n != 0 ) return n;
+ if( iVari != x.iVari ) return iVari - x.iVari;
+ if( iSeq != x.iSeq ) return iSeq - x.iSeq;
+ return 0;
+ }
+
+ bool operator <( const X& x ) { return compare( x ) < 0; }
+ bool operator >( const X& x ) { return compare( x ) > 0; }
+ bool operator <=( const X& x ) { return compare( x ) <= 0; }
+};
+#endif //Q_WS_X11
+
+/*
+#1 Ctrl+A
+#2 Ctrl+A
+#3 Ctrl+B
+ ------
+ Ctrl+A => Null
+ Ctrl+B => #3
+
+#1 Ctrl+A
+#1 Ctrl+B;Ctrl+A
+ ------
+ Ctrl+A => #1
+ Ctrl+B => #2
+
+#1 Ctrl+A
+#1 Ctrl+B,C
+#1 Ctrl+B,D
+ ------
+ Ctrl+A => #1
+ Ctrl+B => Null
+
+#1 Ctrl+A
+#2 Ctrl+Plus(Ctrl+KP_Add)
+ ------
+ Ctrl+A => #1
+ Ctrl+Plus => #2
+ Ctrl+KP_Add => #2
+
+#1 Ctrl+Plus(Ctrl+KP_Add)
+#2 Ctrl+KP_Add
+ ------
+ Ctrl+Plus => #1
+ Ctrl+KP_Add => #2
+
+#1 Ctrl+Plus(Ctrl+KP_Add)
+#2 Ctrl+A;Ctrl+KP_Add
+ ------
+ Ctrl+A => #2
+ Ctrl+Plus => #1
+ Ctrl+KP_Add => #2
+*/
+
+bool TDEAccelBase::updateConnections()
+{
+#ifdef Q_WS_X11
+ kdDebug(125) << "TDEAccelBase::updateConnections() this = " << this << endl;
+ // Retrieve the list of keys to be connected, sorted by priority.
+ // (key, variation, seq)
+ TQValueVector<X> rgKeys;
+ createKeyList( rgKeys );
+ m_rgActionsNonUnique.clear();
+
+ KKeyToActionMap mapKeyToAction;
+ for( uint i = 0; i < rgKeys.size(); i++ ) {
+ X& x = rgKeys[i];
+ KKeyServer::Key& key = x.key;
+ ActionInfo info;
+ bool bNonUnique = false;
+
+ info.pAction = m_rgActions.actionPtr( x.iAction );
+ info.iSeq = x.iSeq;
+ info.iVariation = x.iVari;
+
+ // If this is a multi-key shortcut,
+ if( info.pAction->shortcut().seq(info.iSeq).count() > 1 )
+ bNonUnique = true;
+ // If this key is requested by more than one action,
+ else if( i < rgKeys.size() - 1 && key == rgKeys[i+1].key ) {
+ // If multiple actions requesting this key
+ // have the same priority as the first one,
+ if( info.iVariation == rgKeys[i+1].iVari && info.iSeq == rgKeys[i+1].iSeq )
+ bNonUnique = true;
+
+ kdDebug(125) << "key conflict = " << key.key().toStringInternal()
+ << " action1 = " << info.pAction->name()
+ << " action2 = " << m_rgActions.actionPtr( rgKeys[i+1].iAction )->name()
+ << " non-unique = " << bNonUnique << endl;
+
+ // Skip over the other records with this same key.
+ while( i < rgKeys.size() - 1 && key == rgKeys[i+1].key )
+ i++;
+ }
+
+ if( bNonUnique ) {
+ // Remove connection to single action if there is one
+ if( m_mapKeyToAction.contains( key ) ) {
+ TDEAccelAction* pAction = m_mapKeyToAction[key].pAction;
+ if( pAction ) {
+ m_mapKeyToAction.remove( key );
+ disconnectKey( *pAction, key );
+ pAction->decConnections();
+ m_rgActionsNonUnique.append( pAction );
+ }
+ }
+ // Indicate that no single action is associated with this key.
+ m_rgActionsNonUnique.append( info.pAction );
+ info.pAction = 0;
+ }
+
+ //kdDebug(125) << "mapKeyToAction[" << key.toStringInternal() << "] = " << info.pAction << endl;
+ mapKeyToAction[key] = info;
+ }
+
+ // Disconnect keys which no longer have bindings:
+ for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
+ const KKeyServer::Key& key = it.key();
+ TDEAccelAction* pAction = (*it).pAction;
+ // If this key is longer used or it points to a different action now,
+ if( !mapKeyToAction.contains( key ) || mapKeyToAction[key].pAction != pAction ) {
+ if( pAction ) {
+ disconnectKey( *pAction, key );
+ pAction->decConnections();
+ } else
+ disconnectKey( key );
+ }
+ }
+
+ // Connect any unconnected keys:
+ // In other words, connect any keys which are present in the
+ // new action map, but which are _not_ present in the old one.
+ for( KKeyToActionMap::iterator it = mapKeyToAction.begin(); it != mapKeyToAction.end(); ++it ) {
+ const KKeyServer::Key& key = it.key();
+ TDEAccelAction* pAction = (*it).pAction;
+ if( !m_mapKeyToAction.contains( key ) || m_mapKeyToAction[key].pAction != pAction ) {
+ // TODO: Decide what to do if connect fails.
+ // Probably should remove this item from map.
+ if( pAction ) {
+ if( connectKey( *pAction, key ) )
+ pAction->incConnections();
+ } else
+ connectKey( key );
+ }
+ }
+
+ // Store new map.
+ m_mapKeyToAction = mapKeyToAction;
+
+#ifndef NDEBUG
+ for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
+ kdDebug(125) << "Key: " << it.key().key().toStringInternal() << " => '"
+ << (((*it).pAction) ? (*it).pAction->name() : TQString::null) << "'" << endl;
+ }
+#endif
+#endif //Q_WS_X11
+ return true;
+}
+
+#ifdef Q_WS_X11
+// Construct a list of keys to be connected, sorted highest priority first.
+void TDEAccelBase::createKeyList( TQValueVector<struct X>& rgKeys )
+{
+ //kdDebug(125) << "TDEAccelBase::createKeyList()" << endl;
+ if( !isEnabledInternal())
+ return;
+
+ // create the list
+ // For each action
+ for( uint iAction = 0; iAction < m_rgActions.count(); iAction++ ) {
+ TDEAccelAction* pAction = m_rgActions.actionPtr( iAction );
+ if( pAction && pAction->m_pObjSlot && pAction->m_psMethodSlot && pAction != mtemp_pActionRemoving ) {
+ // For each key sequence associated with action
+ for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
+ const KKeySequence& seq = pAction->shortcut().seq(iSeq);
+ if( seq.count() > 0 ) {
+ KKeyServer::Variations vars;
+ vars.init( seq.key(0), !m_bNativeKeys );
+ for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
+ if( vars.key(iVari).code() && vars.key(iVari).sym() )
+ rgKeys.push_back( X( iAction, iSeq, iVari, vars.key( iVari ) ) );
+ //kdDebug(125) << "\t" << pAction->name() << ": " << vars.key(iVari).toStringInternal() << endl;
+ }
+ }
+ //else
+ // kdDebug(125) << "\t*" << pAction->name() << ":" << endl;
+ }
+ }
+ }
+
+ // sort by priority: iVariation[of first key], iSequence, iAction
+ qHeapSort( rgKeys.begin(), rgKeys.end() );
+}
+#endif //Q_WS_X11
+
+bool TDEAccelBase::insertConnection( TDEAccelAction* pAction )
+{
+ if( !pAction->m_pObjSlot || !pAction->m_psMethodSlot )
+ return true;
+
+ kdDebug(125) << "TDEAccelBase::insertConnection( " << pAction << "=\"" << pAction->m_sName << "\"; shortcut = " << pAction->shortcut().toStringInternal() << " ) this = " << this << endl;
+
+ // For each sequence associated with the given action:
+ for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
+ // Get the first key of the sequence.
+ KKeyServer::Variations vars;
+ vars.init( pAction->shortcut().seq(iSeq).key(0), !m_bNativeKeys );
+ for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
+ const KKeyServer::Key& key = vars.key( iVari );
+
+ //if( !key.isNull() ) {
+ if( key.sym() ) {
+ if( !m_mapKeyToAction.contains( key ) ) {
+ // If this is a single-key shortcut,
+ if( pAction->shortcut().seq(iSeq).count() == 1 ) {
+ m_mapKeyToAction[key] = ActionInfo( pAction, iSeq, iVari );
+ if( connectKey( *pAction, key ) )
+ pAction->incConnections();
+ }
+ // Else this is a multi-key shortcut,
+ else {
+ m_mapKeyToAction[key] = ActionInfo( 0, 0, 0 );
+ // Insert into non-unique list if it's not already there.
+ if( m_rgActionsNonUnique.findIndex( pAction ) == -1 )
+ m_rgActionsNonUnique.append( pAction );
+ if( connectKey( key ) )
+ pAction->incConnections();
+ }
+ } else {
+ // There is a key conflict. A full update
+ // check is necessary.
+ // TODO: make this more efficient where possible.
+ if( m_mapKeyToAction[key].pAction != pAction
+ && m_mapKeyToAction[key].pAction != 0 ) {
+ kdDebug(125) << "Key conflict with action = " << m_mapKeyToAction[key].pAction->name()
+ << " key = " << key.key().toStringInternal() << " : call updateConnections()" << endl;
+ return updateConnections();
+ }
+ }
+ }
+ }
+ }
+
+ //kdDebug(125) << "\tActions = " << m_rgActions.size() << endl;
+ //for( TDEAccelActions::const_iterator it = m_rgActions.begin(); it != m_rgActions.end(); ++it ) {
+ // kdDebug(125) << "\t" << &(*it) << " '" << (*it).m_sName << "'" << endl;
+ //}
+
+ //kdDebug(125) << "\tKeys = " << m_mapKeyToAction.size() << endl;
+ //for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
+ // //kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << (*it)->m_sName << "'" << endl;
+ // kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << *it << "'" << endl;
+ // kdDebug(125) << "\t\t'" << (*it)->m_sName << "'" << endl;
+ //}
+
+ return true;
+}
+
+bool TDEAccelBase::removeConnection( TDEAccelAction* pAction )
+{
+ kdDebug(125) << "TDEAccelBase::removeConnection( " << pAction << " = \"" << pAction->m_sName << "\"; shortcut = " << pAction->m_cut.toStringInternal() << " ): this = " << this << endl;
+
+ //for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it )
+ // kdDebug(125) << "\tKey: " << it.key().toString() << " => '" << (*it)->m_sName << "'" << " " << *it << endl;
+
+ if( m_rgActionsNonUnique.findIndex( pAction ) >= 0 ) {
+ mtemp_pActionRemoving = pAction;
+ bool b = updateConnections();
+ mtemp_pActionRemoving = 0;
+ return b;
+ }
+
+ KKeyToActionMap::iterator it = m_mapKeyToAction.begin();
+ while( it != m_mapKeyToAction.end() ) {
+ KKeyServer::Key key = it.key();
+ ActionInfo* pInfo = &(*it);
+
+ // If the given action is connected to this key,
+ if( pAction == pInfo->pAction ) {
+ disconnectKey( *pAction, key );
+ pAction->decConnections();
+
+ KKeyToActionMap::iterator itRemove = it++;
+ m_mapKeyToAction.remove( itRemove );
+ } else
+ ++it;
+ }
+ return true;
+}
+
+bool TDEAccelBase::setShortcut( const TQString& sAction, const TDEShortcut& cut )
+{
+ TDEAccelAction* pAction = actionPtr( sAction );
+ if( pAction ) {
+ if( m_bAutoUpdate )
+ removeConnection( pAction );
+
+ pAction->setShortcut( cut );
+
+ if( m_bAutoUpdate && !pAction->shortcut().isNull() )
+ insertConnection( pAction );
+ return true;
+ } else
+ return false;
+}
+
+void TDEAccelBase::readSettings( TDEConfigBase* pConfig )
+{
+ m_rgActions.readActions( m_sConfigGroup, pConfig );
+ if( m_bAutoUpdate )
+ updateConnections();
+}
+
+void TDEAccelBase::writeSettings( TDEConfigBase* pConfig ) const
+{
+ m_rgActions.writeActions( m_sConfigGroup, pConfig, m_bConfigIsGlobal, m_bConfigIsGlobal );
+}
+
+TQPopupMenu* TDEAccelBase::createPopupMenu( TQWidget* pParent, const KKeySequence& seq )
+{
+ TDEShortcutMenu* pMenu = new TDEShortcutMenu( pParent, &actions(), seq );
+
+ bool bActionInserted = false;
+ bool bInsertSeparator = false;
+ for( uint i = 0; i < actionCount(); i++ ) {
+ const TDEAccelAction* pAction = actions().actionPtr( i );
+
+ if( !pAction->isEnabled() )
+ continue;
+
+ // If an action has already been inserted into the menu
+ // and we have a label instead of an action here,
+ // then indicate that we should insert a separator before the next menu entry.
+ if( bActionInserted && !pAction->isConfigurable() && pAction->name().contains( ':' ) )
+ bInsertSeparator = true;
+
+ for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
+ const KKeySequence& seqAction = pAction->shortcut().seq(iSeq);
+ if( seqAction.startsWith( seq ) ) {
+ if( bInsertSeparator ) {
+ pMenu->insertSeparator();
+ bInsertSeparator = false;
+ }
+
+ pMenu->insertAction( i, seqAction );
+
+ //kdDebug(125) << "sLabel = " << sLabel << ", seq = " << (TQString)seqMenu.qt() << ", i = " << i << endl;
+ //kdDebug(125) << "pMenu->accel(" << i << ") = " << (TQString)pMenu->accel(i) << endl;
+ bActionInserted = true;
+ break;
+ }
+ }
+ }
+ pMenu->updateShortcuts();
+ return pMenu;
+}