23#include "tdeaccelbase.h"
27#include <tqpopupmenu.h>
33#include <kkeynative.h>
34#include "kkeyserver.h"
36#include "tdeshortcutmenu.h"
46TDEAccelBase::TDEAccelBase(
int fInitCode )
49 kdDebug(125) <<
"TDEAccelBase(): this = " <<
this <<
endl;
50 m_bNativeKeys = fInitCode & NATIVE_KEYS;
52 m_sConfigGroup =
"Shortcuts";
53 m_bConfigIsGlobal =
false;
54 m_bAutoUpdate =
false;
55 mtemp_pActionRemoving = 0;
58TDEAccelBase::~TDEAccelBase()
60 kdDebug(125) <<
"~TDEAccelBase(): this = " <<
this <<
endl;
63uint TDEAccelBase::actionCount()
const {
return m_rgActions.count(); }
64TDEAccelActions& TDEAccelBase::actions() {
return m_rgActions; }
65bool TDEAccelBase::isEnabled()
const {
return m_bEnabled; }
70bool TDEAccelBase::isEnabledInternal()
const {
return isEnabled(); }
72TDEAccelAction* TDEAccelBase::actionPtr(
const TQString& sAction )
73 {
return m_rgActions.actionPtr( sAction ); }
75const TDEAccelAction* TDEAccelBase::actionPtr(
const TQString& sAction )
const
76 {
return m_rgActions.actionPtr( sAction ); }
80 if( !m_mapKeyToAction.contains( key ) )
83 return m_mapKeyToAction[
key].pAction;
86TDEAccelAction* TDEAccelBase::actionPtr(
const KKey& key )
89 k2.
init( key, !m_bNativeKeys );
90 return actionPtr( k2 );
93void TDEAccelBase::setConfigGroup(
const TQString& sConfigGroup )
94 { m_sConfigGroup = sConfigGroup; }
96void TDEAccelBase::setConfigGlobal(
bool global )
97 { m_bConfigIsGlobal = global; }
99bool TDEAccelBase::setActionEnabled(
const TQString& sAction,
bool bEnable )
101 TDEAccelAction* pAction = actionPtr( sAction );
103 if( pAction->m_bEnabled != bEnable ) {
104 kdDebug(125) <<
"TDEAccelBase::setActionEnabled( " << sAction <<
", " << bEnable <<
" )" <<
endl;
105 pAction->m_bEnabled = bEnable;
106 if( m_bAutoUpdate ) {
109 insertConnection( pAction );
110 else if( pAction->isConnected() )
111 removeConnection( pAction );
119bool TDEAccelBase::setAutoUpdate(
bool bAuto )
121 kdDebug(125) <<
"TDEAccelBase::setAutoUpdate( " << bAuto <<
" ): m_bAutoUpdate on entrance = " << m_bAutoUpdate <<
endl;
122 bool b = m_bAutoUpdate;
123 if( !m_bAutoUpdate && bAuto )
125 m_bAutoUpdate = bAuto;
129TDEAccelAction* TDEAccelBase::insert(
const TQString& sAction,
const TQString& sDesc,
const TQString& sHelp,
131 const TQObject* pObjSlot,
const char* psMethodSlot,
132 bool bConfigurable,
bool bEnabled )
134 kdDebug(125) <<
"TDEAccelBase::insert() begin" <<
endl;
136 TDEAccelAction* pAction = m_rgActions.insert(
137 sAction, sDesc, sHelp,
138 rgCutDefaults3, rgCutDefaults4,
139 pObjSlot, psMethodSlot,
140 bConfigurable, bEnabled );
142 if( pAction && m_bAutoUpdate )
143 insertConnection( pAction );
149TDEAccelAction* TDEAccelBase::insert(
const TQString& sName,
const TQString& sDesc )
150 {
return m_rgActions.insert( sName, sDesc ); }
152bool TDEAccelBase::remove(
const TQString& sAction )
154 return m_rgActions.remove( sAction );
157void TDEAccelBase::slotRemoveAction( TDEAccelAction* pAction )
159 removeConnection( pAction );
162bool TDEAccelBase::setActionSlot(
const TQString& sAction,
const TQObject* pObjSlot,
const char* psMethodSlot )
164 kdDebug(125) <<
"TDEAccelBase::setActionSlot( " << sAction <<
", " << pObjSlot <<
", " << psMethodSlot <<
" )\n";
165 TDEAccelAction* pAction = m_rgActions.actionPtr( sAction );
168 if( m_bAutoUpdate && pAction->isConnected() ) {
169 kdDebug(125) <<
"\tm_pObjSlot = " << pAction->m_pObjSlot <<
" m_psMethodSlot = " << pAction->m_psMethodSlot <<
endl;
170 removeConnection( pAction );
173 pAction->m_pObjSlot = pObjSlot;
174 pAction->m_psMethodSlot = psMethodSlot;
177 if( m_bAutoUpdate && pObjSlot && psMethodSlot )
178 insertConnection( pAction );
250struct TDEAccelBase::X
252 uint iAction, iSeq, iVari;
256 X( uint _iAction, uint _iSeq, uint _iVari,
const KKeyServer::Key& _key )
257 { iAction = _iAction; iSeq = _iSeq; iVari = _iVari;
key = _key; }
259 int compare(
const X& x )
261 int n =
key.compare( x.key );
262 if( n != 0 )
return n;
263 if( iVari != x.iVari )
return iVari - x.iVari;
264 if( iSeq != x.iSeq )
return iSeq - x.iSeq;
268 bool operator <(
const X& x ) {
return compare( x ) < 0; }
269 bool operator >(
const X& x ) {
return compare( x ) > 0; }
270 bool operator <=(
const X& x ) {
return compare( x ) <= 0; }
316bool TDEAccelBase::updateConnections()
319 kdDebug(125) <<
"TDEAccelBase::updateConnections() this = " <<
this <<
endl;
322 TQValueVector<X> rgKeys;
323 createKeyList( rgKeys );
324 m_rgActionsNonUnique.clear();
326 KKeyToActionMap mapKeyToAction;
327 for( uint i = 0; i < rgKeys.size(); i++ ) {
331 bool bNonUnique =
false;
333 info.pAction = m_rgActions.actionPtr( x.iAction );
335 info.iVariation = x.iVari;
338 if( info.pAction->shortcut().seq(info.iSeq).count() > 1 )
341 else if( i < rgKeys.size() - 1 && key == rgKeys[i+1].key ) {
344 if( info.iVariation == rgKeys[i+1].iVari && info.iSeq == rgKeys[i+1].iSeq )
347 kdDebug(125) <<
"key conflict = " <<
key.key().toStringInternal()
348 <<
" action1 = " << info.pAction->name()
349 <<
" action2 = " << m_rgActions.actionPtr( rgKeys[i+1].iAction )->name()
350 <<
" non-unique = " << bNonUnique <<
endl;
353 while( i < rgKeys.size() - 1 && key == rgKeys[i+1].key )
359 if( m_mapKeyToAction.contains( key ) ) {
360 TDEAccelAction* pAction = m_mapKeyToAction[
key].pAction;
362 m_mapKeyToAction.remove( key );
363 disconnectKey( *pAction, key );
364 pAction->decConnections();
365 m_rgActionsNonUnique.append( pAction );
369 m_rgActionsNonUnique.append( info.pAction );
373 kdDebug(125) <<
"mapKeyToAction[" <<
key.key().toStringInternal() <<
"] = " << info.pAction <<
endl;
374 mapKeyToAction[
key] = info;
378 for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
380 TDEAccelAction* pAction = (*it).pAction;
382 if( !mapKeyToAction.contains( key ) || mapKeyToAction[key].pAction != pAction ) {
384 disconnectKey( *pAction, key );
385 pAction->decConnections();
387 disconnectKey( key );
394 for( KKeyToActionMap::iterator it = mapKeyToAction.begin(); it != mapKeyToAction.end(); ++it ) {
396 TDEAccelAction* pAction = (*it).pAction;
397 if( !m_mapKeyToAction.contains( key ) || m_mapKeyToAction[key].pAction != pAction ) {
401 if( connectKey( *pAction, key ) )
402 pAction->incConnections();
409 m_mapKeyToAction = mapKeyToAction;
412 for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
413 kdDebug(125) <<
"Key: " << it.key().key().toStringInternal() <<
" => '"
414 << (((*it).pAction) ? (*it).pAction->name() : TQString::null) <<
"'" <<
endl;
423void TDEAccelBase::createKeyList( TQValueVector<struct X>& rgKeys )
425 kdDebug(125) <<
"TDEAccelBase::createKeyList()" <<
endl;
426 if( !isEnabledInternal()) {
432 for( uint iAction = 0; iAction < m_rgActions.count(); iAction++ ) {
433 TDEAccelAction* pAction = m_rgActions.actionPtr( iAction );
434 if( pAction && pAction->m_pObjSlot && pAction->m_psMethodSlot && pAction != mtemp_pActionRemoving ) {
436 for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
437 const KKeySequence& seq = pAction->shortcut().seq(iSeq);
438 if( seq.
count() > 0 ) {
440 vars.init( seq.
key(0), !m_bNativeKeys );
441 for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
442 if( vars.key(iVari).
code() && vars.key(iVari).
sym() ) {
443 rgKeys.push_back( X( iAction, iSeq, iVari, vars.key( iVari ) ) );
445 kdDebug(125) <<
"\t" << pAction->name() <<
": " << vars.key(iVari).
key().
toStringInternal() <<
" [action specified: " << pAction->toStringInternal() <<
"]" <<
endl;
456 qHeapSort( rgKeys.begin(), rgKeys.end() );
460bool TDEAccelBase::insertConnection( TDEAccelAction* pAction )
462 if( !pAction->m_pObjSlot || !pAction->m_psMethodSlot )
465 kdDebug(125) <<
"TDEAccelBase::insertConnection( " << pAction <<
"=\"" << pAction->m_sName <<
"\"; shortcut = " << pAction->shortcut().toStringInternal() <<
" ) this = " <<
this <<
endl;
468 for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
471 vars.init( pAction->shortcut().seq(iSeq).key(0), !m_bNativeKeys );
472 for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
477 if( !m_mapKeyToAction.contains( key ) ) {
479 if( pAction->shortcut().seq(iSeq).count() == 1 ) {
480 m_mapKeyToAction[
key] = ActionInfo( pAction, iSeq, iVari );
481 if( connectKey( *pAction, key ) )
482 pAction->incConnections();
486 m_mapKeyToAction[
key] = ActionInfo( 0, 0, 0 );
488 if( m_rgActionsNonUnique.findIndex( pAction ) == -1 )
489 m_rgActionsNonUnique.append( pAction );
490 if( connectKey( key ) )
491 pAction->incConnections();
497 if( m_mapKeyToAction[key].pAction != pAction
498 && m_mapKeyToAction[key].pAction != 0 ) {
499 kdDebug(125) <<
"Key conflict with action = " << m_mapKeyToAction[
key].pAction->name()
500 <<
" key = " <<
key.key().toStringInternal() <<
" : call updateConnections()" <<
endl;
501 return updateConnections();
523bool TDEAccelBase::removeConnection( TDEAccelAction* pAction )
525 kdDebug(125) <<
"TDEAccelBase::removeConnection( " << pAction <<
" = \"" << pAction->m_sName <<
"\"; shortcut = " << pAction->m_cut.toStringInternal() <<
" ): this = " <<
this <<
endl;
530 if( m_rgActionsNonUnique.findIndex( pAction ) >= 0 ) {
531 mtemp_pActionRemoving = pAction;
532 bool b = updateConnections();
533 mtemp_pActionRemoving = 0;
537 KKeyToActionMap::iterator it = m_mapKeyToAction.begin();
538 while( it != m_mapKeyToAction.end() ) {
540 ActionInfo* pInfo = &(*it);
543 if( pAction == pInfo->pAction ) {
544 disconnectKey( *pAction, key );
545 pAction->decConnections();
547 KKeyToActionMap::iterator itRemove = it++;
548 m_mapKeyToAction.remove( itRemove );
555bool TDEAccelBase::setShortcut(
const TQString& sAction,
const TDEShortcut& cut )
557 TDEAccelAction* pAction = actionPtr( sAction );
560 removeConnection( pAction );
562 pAction->setShortcut( cut );
564 if( m_bAutoUpdate && !pAction->shortcut().isNull() )
565 insertConnection( pAction );
573 m_rgActions.readActions( m_sConfigGroup, pConfig );
578void TDEAccelBase::writeSettings(
TDEConfigBase* pConfig )
const
580 m_rgActions.writeActions( m_sConfigGroup, pConfig, m_bConfigIsGlobal, m_bConfigIsGlobal );
583TQPopupMenu* TDEAccelBase::createPopupMenu( TQWidget* pParent,
const KKeySequence& seq )
585 TDEShortcutMenu* pMenu =
new TDEShortcutMenu( pParent, &actions(), seq );
587 bool bActionInserted =
false;
588 bool bInsertSeparator =
false;
589 for( uint i = 0; i < actionCount(); i++ ) {
590 const TDEAccelAction* pAction = actions().actionPtr( i );
592 if( !pAction->isEnabled() )
598 if( bActionInserted && !pAction->isConfigurable() && pAction->name().contains(
':' ) )
599 bInsertSeparator =
true;
601 for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
602 const KKeySequence& seqAction = pAction->shortcut().seq(iSeq);
604 if( bInsertSeparator ) {
605 pMenu->insertSeparator();
606 bInsertSeparator =
false;
609 pMenu->insertAction( i, seqAction );
613 bActionInserted =
true;
618 pMenu->updateShortcuts();
A KKeySequence object holds a sequence of up to 4 keys.
bool startsWith(const KKeySequence &keySeq) const
Returns true if this key sequence begins with the given sequence.
uint count() const
Returns the number of key strokes of this sequence.
const KKey & key(uint i) const
Return the i'th key of this sequence, or a null key if there are less then i keys.
A KKey object represents a single key with possible modifiers (Shift, Ctrl, Alt, Win).
TQString toStringInternal() const
Returns an untranslated text representation of the key in the form "modifier+key",...
KDE Configuration Management abstract base class.
The TDEShortcut class is used to represent a keyboard shortcut to an action.
TQString toString() const
Returns a description of the shortcut as semicolon-separated ket sequences, as returned by KKeySequen...
kdbgstream kdDebug(int area=0)
Returns a debug stream.
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
uint sym() const
Returns the symbol of the key.
KKey key() const
Converts this Key to a KKey.
uint code() const
Returns the code of the key.
bool init(const KKey &key, bool bQt)
Initializes the key with a KKey.
TODO: please document this class.