23 #include "kaccelbase.h"
25 #include <tqkeycode.h>
27 #include <tqpopupmenu.h>
33 #include <kkeynative.h>
34 #include "kkeyserver.h"
36 #include "kshortcutmenu.h"
46 KAccelBase::KAccelBase(
int fInitCode )
49 kdDebug(125) <<
"KAccelBase(): 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;
58 KAccelBase::~KAccelBase()
60 kdDebug(125) <<
"~KAccelBase(): this = " <<
this <<
endl;
63 uint KAccelBase::actionCount()
const {
return m_rgActions.count(); }
64 KAccelActions& KAccelBase::actions() {
return m_rgActions; }
65 bool KAccelBase::isEnabled()
const {
return m_bEnabled; }
70 bool KAccelBase::isEnabledInternal()
const {
return isEnabled(); }
72 KAccelAction* KAccelBase::actionPtr(
const TQString& sAction )
73 {
return m_rgActions.actionPtr( sAction ); }
75 const KAccelAction* KAccelBase::actionPtr(
const TQString& sAction )
const
76 {
return m_rgActions.actionPtr( sAction ); }
80 if( !m_mapKeyToAction.contains( key ) )
83 return m_mapKeyToAction[key].pAction;
86 KAccelAction* KAccelBase::actionPtr(
const KKey& key )
89 k2.
init( key, !m_bNativeKeys );
90 return actionPtr( k2 );
93 void KAccelBase::setConfigGroup(
const TQString& sConfigGroup )
94 { m_sConfigGroup = sConfigGroup; }
96 void KAccelBase::setConfigGlobal(
bool global )
97 { m_bConfigIsGlobal = global; }
99 bool KAccelBase::setActionEnabled(
const TQString& sAction,
bool bEnable )
101 KAccelAction* pAction = actionPtr( sAction );
103 if( pAction->m_bEnabled != bEnable ) {
104 kdDebug(125) <<
"KAccelBase::setActionEnabled( " << sAction <<
", " << bEnable <<
" )" <<
endl;
105 pAction->m_bEnabled = bEnable;
106 if( m_bAutoUpdate ) {
109 insertConnection( pAction );
110 else if( pAction->isConnected() )
111 removeConnection( pAction );
119 bool KAccelBase::setAutoUpdate(
bool bAuto )
121 kdDebug(125) <<
"KAccelBase::setAutoUpdate( " << bAuto <<
" ): m_bAutoUpdate on entrance = " << m_bAutoUpdate <<
endl;
122 bool b = m_bAutoUpdate;
123 if( !m_bAutoUpdate && bAuto )
125 m_bAutoUpdate = bAuto;
129 KAccelAction* KAccelBase::insert(
const TQString& sAction,
const TQString& sDesc,
const TQString& sHelp,
131 const TQObject* pObjSlot,
const char* psMethodSlot,
132 bool bConfigurable,
bool bEnabled )
135 KAccelAction* pAction = m_rgActions.insert(
136 sAction, sDesc, sHelp,
137 rgCutDefaults3, rgCutDefaults4,
138 pObjSlot, psMethodSlot,
139 bConfigurable, bEnabled );
141 if( pAction && m_bAutoUpdate )
142 insertConnection( pAction );
148 KAccelAction* KAccelBase::insert(
const TQString& sName,
const TQString& sDesc )
149 {
return m_rgActions.insert( sName, sDesc ); }
151 bool KAccelBase::remove(
const TQString& sAction )
153 return m_rgActions.remove( sAction );
156 void KAccelBase::slotRemoveAction( KAccelAction* pAction )
158 removeConnection( pAction );
161 bool KAccelBase::setActionSlot(
const TQString& sAction,
const TQObject* pObjSlot,
const char* psMethodSlot )
163 kdDebug(125) <<
"KAccelBase::setActionSlot( " << sAction <<
", " << pObjSlot <<
", " << psMethodSlot <<
" )\n";
164 KAccelAction* pAction = m_rgActions.actionPtr( sAction );
167 if( m_bAutoUpdate && pAction->isConnected() ) {
168 kdDebug(125) <<
"\tm_pObjSlot = " << pAction->m_pObjSlot <<
" m_psMethodSlot = " << pAction->m_psMethodSlot <<
endl;
169 removeConnection( pAction );
172 pAction->m_pObjSlot = pObjSlot;
173 pAction->m_psMethodSlot = psMethodSlot;
176 if( m_bAutoUpdate && pObjSlot && psMethodSlot )
177 insertConnection( pAction );
251 uint iAction, iSeq, iVari;
255 X( uint _iAction, uint _iSeq, uint _iVari,
const KKeyServer::Key& _key )
256 { iAction = _iAction; iSeq = _iSeq; iVari = _iVari; key = _key; }
258 int compare(
const X& x )
261 if( n != 0 )
return n;
262 if( iVari != x.iVari )
return iVari - x.iVari;
263 if( iSeq != x.iSeq )
return iSeq - x.iSeq;
267 bool operator <(
const X& x ) {
return compare( x ) < 0; }
268 bool operator >(
const X& x ) {
return compare( x ) > 0; }
269 bool operator <=(
const X& x ) {
return compare( x ) <= 0; }
315 bool KAccelBase::updateConnections()
318 kdDebug(125) <<
"KAccelBase::updateConnections() this = " <<
this <<
endl;
321 TQValueVector<X> rgKeys;
322 createKeyList( rgKeys );
323 m_rgActionsNonUnique.clear();
325 KKeyToActionMap mapKeyToAction;
326 for( uint i = 0; i < rgKeys.size(); i++ ) {
330 bool bNonUnique =
false;
332 info.pAction = m_rgActions.actionPtr( x.iAction );
334 info.iVariation = x.iVari;
337 if( info.pAction->shortcut().seq(info.iSeq).count() > 1 )
340 else if( i < rgKeys.size() - 1 && key == rgKeys[i+1].
key ) {
343 if( info.iVariation == rgKeys[i+1].iVari && info.iSeq == rgKeys[i+1].iSeq )
347 <<
" action1 = " << info.pAction->name()
348 <<
" action2 = " << m_rgActions.actionPtr( rgKeys[i+1].iAction )->name()
349 <<
" non-unique = " << bNonUnique <<
endl;
352 while( i < rgKeys.size() - 1 && key == rgKeys[i+1].
key )
358 if( m_mapKeyToAction.contains( key ) ) {
359 KAccelAction* pAction = m_mapKeyToAction[key].pAction;
361 m_mapKeyToAction.remove( key );
362 disconnectKey( *pAction, key );
363 pAction->decConnections();
364 m_rgActionsNonUnique.append( pAction );
368 m_rgActionsNonUnique.append( info.pAction );
373 mapKeyToAction[key] = info;
377 for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
379 KAccelAction* pAction = (*it).pAction;
381 if( !mapKeyToAction.contains( key ) || mapKeyToAction[key].pAction != pAction ) {
383 disconnectKey( *pAction, key );
384 pAction->decConnections();
386 disconnectKey( key );
393 for( KKeyToActionMap::iterator it = mapKeyToAction.begin(); it != mapKeyToAction.end(); ++it ) {
395 KAccelAction* pAction = (*it).pAction;
396 if( !m_mapKeyToAction.contains( key ) || m_mapKeyToAction[key].pAction != pAction ) {
400 if( connectKey( *pAction, key ) )
401 pAction->incConnections();
408 m_mapKeyToAction = mapKeyToAction;
411 for( KKeyToActionMap::iterator it = m_mapKeyToAction.begin(); it != m_mapKeyToAction.end(); ++it ) {
412 kdDebug(125) <<
"Key: " << it.key().key().toStringInternal() <<
" => '"
413 << (((*it).pAction) ? (*it).pAction->name() : TQString::null) <<
"'" << endl;
422 void KAccelBase::createKeyList( TQValueVector<struct X>& rgKeys )
425 if( !isEnabledInternal())
430 for( uint iAction = 0; iAction < m_rgActions.count(); iAction++ ) {
431 KAccelAction* pAction = m_rgActions.actionPtr( iAction );
432 if( pAction && pAction->m_pObjSlot && pAction->m_psMethodSlot && pAction != mtemp_pActionRemoving ) {
434 for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
435 const KKeySequence& seq = pAction->shortcut().seq(iSeq);
436 if( seq.
count() > 0 ) {
438 vars.init( seq.
key(0), !m_bNativeKeys );
439 for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
440 if( vars.key(iVari).
code() && vars.key(iVari).
sym() )
441 rgKeys.push_back( X( iAction, iSeq, iVari, vars.key( iVari ) ) );
452 qHeapSort( rgKeys.begin(), rgKeys.end() );
456 bool KAccelBase::insertConnection( KAccelAction* pAction )
458 if( !pAction->m_pObjSlot || !pAction->m_psMethodSlot )
461 kdDebug(125) <<
"KAccelBase::insertConnection( " << pAction <<
"=\"" << pAction->m_sName <<
"\"; shortcut = " << pAction->shortcut().toStringInternal() <<
" ) this = " <<
this <<
endl;
464 for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
467 vars.init( pAction->shortcut().seq(iSeq).key(0), !m_bNativeKeys );
468 for( uint iVari = 0; iVari < vars.count(); iVari++ ) {
473 if( !m_mapKeyToAction.contains( key ) ) {
475 if( pAction->shortcut().seq(iSeq).count() == 1 ) {
476 m_mapKeyToAction[key] = ActionInfo( pAction, iSeq, iVari );
477 if( connectKey( *pAction, key ) )
478 pAction->incConnections();
482 m_mapKeyToAction[key] = ActionInfo( 0, 0, 0 );
484 if( m_rgActionsNonUnique.findIndex( pAction ) == -1 )
485 m_rgActionsNonUnique.append( pAction );
486 if( connectKey( key ) )
487 pAction->incConnections();
493 if( m_mapKeyToAction[key].pAction != pAction
494 && m_mapKeyToAction[key].pAction != 0 ) {
495 kdDebug(125) <<
"Key conflict with action = " << m_mapKeyToAction[key].pAction->name()
497 return updateConnections();
519 bool KAccelBase::removeConnection( KAccelAction* pAction )
521 kdDebug(125) <<
"KAccelBase::removeConnection( " << pAction <<
" = \"" << pAction->m_sName <<
"\"; shortcut = " << pAction->m_cut.toStringInternal() <<
" ): this = " <<
this <<
endl;
526 if( m_rgActionsNonUnique.findIndex( pAction ) >= 0 ) {
527 mtemp_pActionRemoving = pAction;
528 bool b = updateConnections();
529 mtemp_pActionRemoving = 0;
533 KKeyToActionMap::iterator it = m_mapKeyToAction.begin();
534 while( it != m_mapKeyToAction.end() ) {
536 ActionInfo* pInfo = &(*it);
539 if( pAction == pInfo->pAction ) {
540 disconnectKey( *pAction, key );
541 pAction->decConnections();
543 KKeyToActionMap::iterator itRemove = it++;
544 m_mapKeyToAction.remove( itRemove );
551 bool KAccelBase::setShortcut(
const TQString& sAction,
const KShortcut& cut )
553 KAccelAction* pAction = actionPtr( sAction );
556 removeConnection( pAction );
558 pAction->setShortcut( cut );
560 if( m_bAutoUpdate && !pAction->shortcut().isNull() )
561 insertConnection( pAction );
567 void KAccelBase::readSettings(
KConfigBase* pConfig )
569 m_rgActions.readActions( m_sConfigGroup, pConfig );
574 void KAccelBase::writeSettings(
KConfigBase* pConfig )
const
576 m_rgActions.writeActions( m_sConfigGroup, pConfig, m_bConfigIsGlobal, m_bConfigIsGlobal );
579 TQPopupMenu* KAccelBase::createPopupMenu( TQWidget* pParent,
const KKeySequence& seq )
581 KShortcutMenu* pMenu =
new KShortcutMenu( pParent, &actions(), seq );
583 bool bActionInserted =
false;
584 bool bInsertSeparator =
false;
585 for( uint i = 0; i < actionCount(); i++ ) {
586 const KAccelAction* pAction = actions().actionPtr( i );
588 if( !pAction->isEnabled() )
594 if( bActionInserted && !pAction->isConfigurable() && pAction->name().contains(
':' ) )
595 bInsertSeparator =
true;
597 for( uint iSeq = 0; iSeq < pAction->shortcut().count(); iSeq++ ) {
598 const KKeySequence& seqAction = pAction->shortcut().seq(iSeq);
600 if( bInsertSeparator ) {
601 pMenu->insertSeparator();
602 bInsertSeparator =
false;
605 pMenu->insertAction( i, seqAction );
609 bActionInserted =
true;
614 pMenu->updateShortcuts();