00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "kactioncollection.h"
00027 #include "kactionshortcutlist.h"
00028
00029 #include <qptrdict.h>
00030 #include <qvariant.h>
00031
00032 #include <kaccel.h>
00033 #include <kaccelbase.h>
00034 #include <kapplication.h>
00035 #include <kdebug.h>
00036 #include <kxmlguifactory.h>
00037
00038 class KActionCollection::KActionCollectionPrivate
00039 {
00040 public:
00041 KActionCollectionPrivate()
00042 {
00043 m_instance = 0;
00044
00045
00046 m_bAutoConnectShortcuts = true;
00047 m_widget = 0;
00048 m_kaccel = m_builderKAccel = 0;
00049 m_dctHighlightContainers.setAutoDelete( true );
00050 m_highlight = false;
00051 m_currentHighlightAction = 0;
00052 m_statusCleared = true;
00053 }
00054
00055 KInstance *m_instance;
00056 QString m_sXMLFile;
00057 bool m_bAutoConnectShortcuts;
00058
00059
00060
00061
00062 QValueList<KActionCollection*> m_docList;
00063 QWidget *m_widget;
00064 KAccel *m_kaccel;
00065 KAccel *m_builderKAccel;
00066
00067 QAsciiDict<KAction> m_actionDict;
00068 QPtrDict< QPtrList<KAction> > m_dctHighlightContainers;
00069 bool m_highlight;
00070 KAction *m_currentHighlightAction;
00071 bool m_statusCleared;
00072 };
00073
00074 KActionCollection::KActionCollection( QWidget *parent, const char *name,
00075 KInstance *instance )
00076 : QObject( parent, name )
00077 {
00078 kdDebug(129) << "KActionCollection::KActionCollection( " << parent << ", " << name << " ): this = " << this << endl;
00079 d = new KActionCollectionPrivate;
00080 if( parent )
00081 setWidget( parent );
00082
00083 setInstance( instance );
00084 }
00085
00086
00087 KActionCollection::KActionCollection( QWidget *watch, QObject* parent, const char *name,
00088 KInstance *instance )
00089 : QObject( parent, name )
00090 {
00091 kdDebug(129) << "KActionCollection::KActionCollection( " << watch << ", " << parent << ", " << name << " ): this = " << this << endl;
00092 d = new KActionCollectionPrivate;
00093 if( watch )
00094 setWidget( watch );
00095
00096 setInstance( instance );
00097 }
00098
00099
00100 KActionCollection::KActionCollection( QObject *parent, const char *name,
00101 KInstance *instance )
00102 : QObject( parent, name )
00103 {
00104 kdWarning(129) << "KActionCollection::KActionCollection( QObject *parent, const char *name, KInstance *instance )" << endl;
00105 kdDebug(129) << kdBacktrace() << endl;
00106 d = new KActionCollectionPrivate;
00107 QWidget* w = dynamic_cast<QWidget*>( parent );
00108 if( w )
00109 setWidget( w );
00110
00111 setInstance( instance );
00112 }
00113
00114 KActionCollection::KActionCollection( const KActionCollection © )
00115 : QObject()
00116 {
00117 kdWarning(129) << "KActionCollection::KActionCollection( const KActionCollection & ): function is severely deprecated." << endl;
00118 d = new KActionCollectionPrivate;
00119 *this = copy;
00120 }
00121
00122
00123 KActionCollection::~KActionCollection()
00124 {
00125 kdDebug(129) << "KActionCollection::~KActionCollection(): this = " << this << endl;
00126 for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) {
00127 KAction* pAction = it.current();
00128 if ( pAction->m_parentCollection == this )
00129 pAction->m_parentCollection = 0L;
00130 }
00131
00132 delete d->m_kaccel;
00133 delete d->m_builderKAccel;
00134 delete d; d = 0;
00135 }
00136
00137 void KActionCollection::setWidget( QWidget* w )
00138 {
00139
00140
00141
00142
00143
00144 if ( !d->m_widget ) {
00145 d->m_widget = w;
00146 d->m_kaccel = new KAccel( w, this, "KActionCollection-KAccel" );
00147 }
00148 else if ( d->m_widget != w )
00149 kdWarning(129) << "KActionCollection::setWidget(): tried to change widget from " << d->m_widget << " to " << w << endl;
00150 }
00151
00152 void KActionCollection::setAutoConnectShortcuts( bool b )
00153 {
00154 d->m_bAutoConnectShortcuts = b;
00155 }
00156
00157 bool KActionCollection::isAutoConnectShortcuts()
00158 {
00159 return d->m_bAutoConnectShortcuts;
00160 }
00161
00162 bool KActionCollection::addDocCollection( KActionCollection* pDoc )
00163 {
00164 d->m_docList.append( pDoc );
00165 return true;
00166 }
00167
00168 void KActionCollection::beginXMLPlug( QWidget *widget )
00169 {
00170 kdDebug(129) << "KActionCollection::beginXMLPlug( buildWidget = " << widget << " ): this = " << this << " d->m_builderKAccel = " << d->m_builderKAccel << endl;
00171
00172 if( widget && !d->m_builderKAccel ) {
00173 d->m_builderKAccel = new KAccel( widget, this, "KActionCollection-BuilderKAccel" );
00174 }
00175 }
00176
00177 void KActionCollection::endXMLPlug()
00178 {
00179 kdDebug(129) << "KActionCollection::endXMLPlug(): this = " << this << endl;
00180
00181 }
00182
00183 void KActionCollection::prepareXMLUnplug()
00184 {
00185 kdDebug(129) << "KActionCollection::prepareXMLUnplug(): this = " << this << endl;
00186 unplugShortcuts( d->m_kaccel );
00187
00188 if( d->m_builderKAccel ) {
00189 unplugShortcuts( d->m_builderKAccel );
00190 delete d->m_builderKAccel;
00191 d->m_builderKAccel = 0;
00192 }
00193 }
00194
00195 void KActionCollection::unplugShortcuts( KAccel* kaccel )
00196 {
00197 for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) {
00198 KAction* pAction = it.current();
00199 pAction->removeKAccel( kaccel );
00200 }
00201
00202 for( uint i = 0; i < d->m_docList.count(); i++ )
00203 d->m_docList[i]->unplugShortcuts( kaccel );
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 KAccel* KActionCollection::kaccel()
00268 {
00269
00270
00271
00272
00273 return d->m_kaccel;
00274 }
00275
00276 const KAccel* KActionCollection::kaccel() const
00277 {
00278
00279
00280
00281
00282 return d->m_kaccel;
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 void KActionCollection::_insert( KAction* action )
00300 {
00301 char unnamed_name[100];
00302 const char *name = action->name();
00303 if( qstrcmp( name, "unnamed" ) == 0 )
00304 {
00305 sprintf(unnamed_name, "unnamed-%p", (void *)action);
00306 name = unnamed_name;
00307 }
00308 KAction *a = d->m_actionDict[ name ];
00309 if ( a == action )
00310 return;
00311
00312 d->m_actionDict.insert( name, action );
00313
00314 emit inserted( action );
00315 }
00316
00317 void KActionCollection::_remove( KAction* action )
00318 {
00319 delete _take( action );
00320 }
00321
00322 KAction* KActionCollection::_take( KAction* action )
00323 {
00324 char unnamed_name[100];
00325 const char *name = action->name();
00326 if( qstrcmp( name, "unnamed" ) == 0 )
00327 {
00328 sprintf(unnamed_name, "unnamed-%p", (void *) action);
00329 name = unnamed_name;
00330 }
00331
00332 KAction *a = d->m_actionDict.take( name );
00333 if ( !a || a != action )
00334 return 0;
00335
00336 if ( a->m_parentCollection == this )
00337 a->m_parentCollection = 0;
00338
00339 emit removed( action );
00340 return a;
00341 }
00342
00343 void KActionCollection::_clear()
00344 {
00345 QAsciiDictIterator<KAction> it( d->m_actionDict );
00346 while ( it.current() )
00347 _remove( it.current() );
00348 }
00349
00350 void KActionCollection::insert( KAction* action ) { _insert( action ); }
00351 void KActionCollection::remove( KAction* action ) { _remove( action ); }
00352 KAction* KActionCollection::take( KAction* action ) { return _take( action ); }
00353 void KActionCollection::clear() { _clear(); }
00354 KAccel* KActionCollection::accel() { return kaccel(); }
00355 const KAccel* KActionCollection::accel() const { return kaccel(); }
00356 KAccel* KActionCollection::builderKAccel() const { return d->m_builderKAccel; }
00357
00358 KAction* KActionCollection::action( const char* name, const char* classname ) const
00359 {
00360 KAction* pAction = 0;
00361
00362 if ( !classname && name )
00363 pAction = d->m_actionDict[ name ];
00364
00365 else {
00366 QAsciiDictIterator<KAction> it( d->m_actionDict );
00367 for( ; it.current(); ++it )
00368 {
00369 if ( ( !name || strcmp( it.current()->name(), name ) == 0 ) &&
00370 ( !classname || strcmp( it.current()->className(), classname ) == 0 ) ) {
00371 pAction = it.current();
00372 break;
00373 }
00374 }
00375 }
00376
00377 if( !pAction ) {
00378 for( uint i = 0; i < d->m_docList.count() && !pAction; i++ )
00379 pAction = d->m_docList[i]->action( name, classname );
00380 }
00381
00382 return pAction;
00383 }
00384
00385 KAction* KActionCollection::action( int index ) const
00386 {
00387 QAsciiDictIterator<KAction> it( d->m_actionDict );
00388 it += index;
00389 return it.current();
00390
00391 }
00392
00393 bool KActionCollection::readShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig )
00394 {
00395 return KActionShortcutList(this).readSettings( sConfigGroup, pConfig );
00396 }
00397
00398 bool KActionCollection::writeShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) const
00399 {
00400 return KActionShortcutList((KActionCollection*)this).writeSettings( sConfigGroup, pConfig );
00401 }
00402
00403 uint KActionCollection::count() const
00404 {
00405 return d->m_actionDict.count();
00406 }
00407
00408 QStringList KActionCollection::groups() const
00409 {
00410 QStringList lst;
00411
00412 QAsciiDictIterator<KAction> it( d->m_actionDict );
00413 for( ; it.current(); ++it )
00414 if ( !it.current()->group().isEmpty() && !lst.contains( it.current()->group() ) )
00415 lst.append( it.current()->group() );
00416
00417 return lst;
00418 }
00419
00420 KActionPtrList KActionCollection::actions( const QString& group ) const
00421 {
00422 KActionPtrList lst;
00423
00424 QAsciiDictIterator<KAction> it( d->m_actionDict );
00425 for( ; it.current(); ++it )
00426 if ( it.current()->group() == group )
00427 lst.append( it.current() );
00428 else if ( it.current()->group().isEmpty() && group.isEmpty() )
00429 lst.append( it.current() );
00430
00431 return lst;
00432 }
00433
00434 KActionPtrList KActionCollection::actions() const
00435 {
00436 KActionPtrList lst;
00437
00438 QAsciiDictIterator<KAction> it( d->m_actionDict );
00439 for( ; it.current(); ++it )
00440 lst.append( it.current() );
00441
00442 return lst;
00443 }
00444
00445 void KActionCollection::setInstance( KInstance *instance )
00446 {
00447 if ( instance )
00448 d->m_instance = instance;
00449 else
00450 d->m_instance = KGlobal::instance();
00451 }
00452
00453 KInstance *KActionCollection::instance() const
00454 {
00455 return d->m_instance;
00456 }
00457
00458 void KActionCollection::setXMLFile( const QString& sXMLFile )
00459 {
00460 d->m_sXMLFile = sXMLFile;
00461 }
00462
00463 const QString& KActionCollection::xmlFile() const
00464 {
00465 return d->m_sXMLFile;
00466 }
00467
00468 void KActionCollection::setHighlightingEnabled( bool enable )
00469 {
00470 d->m_highlight = enable;
00471 }
00472
00473 bool KActionCollection::highlightingEnabled() const
00474 {
00475 return d->m_highlight;
00476 }
00477
00478 void KActionCollection::connectHighlight( QWidget *container, KAction *action )
00479 {
00480 if ( !d->m_highlight )
00481 return;
00482
00483 QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ];
00484
00485 if ( !actionList )
00486 {
00487 actionList = new QPtrList<KAction>;
00488
00489 if ( container->inherits( "QPopupMenu" ) )
00490 {
00491 connect( container, SIGNAL( highlighted( int ) ),
00492 this, SLOT( slotMenuItemHighlighted( int ) ) );
00493 connect( container, SIGNAL( aboutToHide() ),
00494 this, SLOT( slotMenuAboutToHide() ) );
00495 }
00496 else if ( container->inherits( "KToolBar" ) )
00497 {
00498 connect( container, SIGNAL( highlighted( int, bool ) ),
00499 this, SLOT( slotToolBarButtonHighlighted( int, bool ) ) );
00500 }
00501
00502 connect( container, SIGNAL( destroyed() ),
00503 this, SLOT( slotDestroyed() ) );
00504
00505 d->m_dctHighlightContainers.insert( container, actionList );
00506 }
00507
00508 actionList->append( action );
00509 }
00510
00511 void KActionCollection::disconnectHighlight( QWidget *container, KAction *action )
00512 {
00513 if ( !d->m_highlight )
00514 return;
00515
00516 QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ];
00517
00518 if ( !actionList )
00519 return;
00520
00521 actionList->removeRef( action );
00522
00523 if ( actionList->count() == 0 )
00524 d->m_dctHighlightContainers.remove( container );
00525 }
00526
00527 void KActionCollection::slotMenuItemHighlighted( int id )
00528 {
00529 if ( !d->m_highlight )
00530 return;
00531
00532 if ( d->m_currentHighlightAction )
00533 emit actionHighlighted( d->m_currentHighlightAction, false );
00534
00535 QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) );
00536
00537 d->m_currentHighlightAction = findAction( container, id );
00538
00539 if ( !d->m_currentHighlightAction )
00540 {
00541 if ( !d->m_statusCleared )
00542 emit clearStatusText();
00543 d->m_statusCleared = true;
00544 return;
00545 }
00546
00547 d->m_statusCleared = false;
00548 emit actionHighlighted( d->m_currentHighlightAction );
00549 emit actionHighlighted( d->m_currentHighlightAction, true );
00550 emit actionStatusText( d->m_currentHighlightAction->toolTip() );
00551 }
00552
00553 void KActionCollection::slotMenuAboutToHide()
00554 {
00555 if ( d->m_currentHighlightAction )
00556 emit actionHighlighted( d->m_currentHighlightAction, false );
00557 d->m_currentHighlightAction = 0;
00558
00559 if ( !d->m_statusCleared )
00560 emit clearStatusText();
00561 d->m_statusCleared = true;
00562 }
00563
00564 void KActionCollection::slotToolBarButtonHighlighted( int id, bool highlight )
00565 {
00566 if ( !d->m_highlight )
00567 return;
00568
00569 QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) );
00570
00571 KAction *action = findAction( container, id );
00572
00573 if ( !action )
00574 {
00575 d->m_currentHighlightAction = 0;
00576
00577
00578 return;
00579 }
00580
00581 emit actionHighlighted( action, highlight );
00582
00583 if ( highlight )
00584 d->m_currentHighlightAction = action;
00585 else
00586 {
00587 d->m_currentHighlightAction = 0;
00588
00589 }
00590 }
00591
00592 void KActionCollection::slotDestroyed()
00593 {
00594 d->m_dctHighlightContainers.remove( reinterpret_cast<void *>( const_cast<QObject *>(sender()) ) );
00595 }
00596
00597 KAction *KActionCollection::findAction( QWidget *container, int id )
00598 {
00599 QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ reinterpret_cast<void *>( container ) ];
00600
00601 if ( !actionList )
00602 return 0;
00603
00604 QPtrListIterator<KAction> it( *actionList );
00605 for (; it.current(); ++it )
00606 if ( it.current()->isPlugged( container, id ) )
00607 return it.current();
00608
00609 return 0;
00610 }
00611
00612
00613 KActionCollection KActionCollection::operator+(const KActionCollection &c ) const
00614 {
00615 kdWarning(129) << "KActionCollection::operator+(): function is severely deprecated." << endl;
00616 KActionCollection ret( *this );
00617
00618 QValueList<KAction *> actions = c.actions();
00619 QValueList<KAction *>::ConstIterator it = actions.begin();
00620 QValueList<KAction *>::ConstIterator end = actions.end();
00621 for (; it != end; ++it )
00622 ret.insert( *it );
00623
00624 return ret;
00625 }
00626
00627 KActionCollection &KActionCollection::operator=( const KActionCollection © )
00628 {
00629 kdWarning(129) << "KActionCollection::operator=(): function is severely deprecated." << endl;
00630
00631
00632
00633
00634 d->m_widget = copy.d->m_widget;
00635 d->m_kaccel = copy.d->m_kaccel;
00636 d->m_actionDict = copy.d->m_actionDict;
00637 setInstance( copy.instance() );
00638 return *this;
00639 }
00640
00641 KActionCollection &KActionCollection::operator+=( const KActionCollection &c )
00642 {
00643 kdWarning(129) << "KActionCollection::operator+=(): function is severely deprecated." << endl;
00644 QAsciiDictIterator<KAction> it(c.d->m_actionDict);
00645 for ( ; it.current(); ++it )
00646 insert( it.current() );
00647
00648 return *this;
00649 }
00650
00651
00652
00653
00654
00655
00656 KActionShortcutList::KActionShortcutList( KActionCollection* pColl )
00657 : m_actions( *pColl )
00658 { }
00659 KActionShortcutList::~KActionShortcutList()
00660 { }
00661 uint KActionShortcutList::count() const
00662 { return m_actions.count(); }
00663 QString KActionShortcutList::name( uint i ) const
00664 { return m_actions.action(i)->name(); }
00665 QString KActionShortcutList::label( uint i ) const
00666 { return m_actions.action(i)->text(); }
00667 QString KActionShortcutList::whatsThis( uint i ) const
00668 { return m_actions.action(i)->whatsThis(); }
00669 const KShortcut& KActionShortcutList::shortcut( uint i ) const
00670 { return m_actions.action(i)->shortcut(); }
00671 const KShortcut& KActionShortcutList::shortcutDefault( uint i ) const
00672 { return m_actions.action(i)->shortcutDefault(); }
00673 bool KActionShortcutList::isConfigurable( uint i ) const
00674 { return m_actions.action(i)->isShortcutConfigurable(); }
00675 bool KActionShortcutList::setShortcut( uint i, const KShortcut& cut )
00676 { return m_actions.action(i)->setShortcut( cut ); }
00677 const KInstance* KActionShortcutList::instance() const
00678 { return m_actions.instance(); }
00679 QVariant KActionShortcutList::getOther( Other, uint ) const
00680 { return QVariant(); }
00681 bool KActionShortcutList::setOther( Other, uint, QVariant )
00682 { return false; }
00683
00684 bool KActionShortcutList::save() const
00685 {
00686 kdDebug(129) << "KActionShortcutList::save(): xmlFile = " << m_actions.xmlFile() << endl;
00687
00688 if( m_actions.xmlFile().isEmpty() )
00689 return writeSettings();
00690
00691 QString tagActionProp = QString::fromLatin1("ActionProperties");
00692 QString tagAction = QString::fromLatin1("Action");
00693 QString attrName = QString::fromLatin1("name");
00694 QString attrShortcut = QString::fromLatin1("shortcut");
00695 QString attrAccel = QString::fromLatin1("accel");
00696
00697
00698 QString sXml( KXMLGUIFactory::readConfigFile( m_actions.xmlFile(), false, instance() ) );
00699 QDomDocument doc;
00700 doc.setContent( sXml );
00701
00702
00703
00704
00705 QDomElement elem;
00706 QDomNode it = doc.documentElement().firstChild();
00707 for( ; !it.isNull(); it = it.nextSibling() ) {
00708 QDomElement e = it.toElement();
00709 if( e.tagName() == tagActionProp ) {
00710 elem = e;
00711 break;
00712 }
00713 }
00714
00715
00716 if( elem.isNull() ) {
00717 elem = doc.createElement( tagActionProp );
00718 doc.documentElement().appendChild( elem );
00719 }
00720
00721
00722 uint nSize = count();
00723 for( uint i = 0; i < nSize; i++ ) {
00724 const QString& sName = name(i);
00725
00726 bool bSameAsDefault = (shortcut(i) == shortcutDefault(i));
00727
00728
00729
00730 QDomElement act_elem;
00731 for( it = elem.firstChild(); !it.isNull(); it = it.nextSibling() ) {
00732 QDomElement e = it.toElement();
00733 if( e.attribute( attrName ) == sName ) {
00734 act_elem = e;
00735 break;
00736 }
00737 }
00738
00739
00740 if( act_elem.isNull() ) {
00741 if( bSameAsDefault )
00742 continue;
00743
00744 act_elem = doc.createElement( tagAction );
00745 act_elem.setAttribute( attrName, sName );
00746 }
00747
00748 act_elem.removeAttribute( attrAccel );
00749 if( bSameAsDefault ) {
00750 act_elem.removeAttribute( attrShortcut );
00751
00752 if( act_elem.attributes().count() == 1 )
00753 elem.removeChild( act_elem );
00754 } else {
00755 act_elem.setAttribute( attrShortcut, shortcut(i).toStringInternal() );
00756 elem.appendChild( act_elem );
00757 }
00758 }
00759
00760
00761 return KXMLGUIFactory::saveConfigFile( doc, m_actions.xmlFile(), instance() );
00762 }
00763
00764
00765
00766
00767
00768 KActionPtrShortcutList::KActionPtrShortcutList( KActionPtrList& list )
00769 : m_actions( list )
00770 { }
00771 KActionPtrShortcutList::~KActionPtrShortcutList()
00772 { }
00773 uint KActionPtrShortcutList::count() const
00774 { return m_actions.count(); }
00775 QString KActionPtrShortcutList::name( uint i ) const
00776 { return m_actions[i]->name(); }
00777 QString KActionPtrShortcutList::label( uint i ) const
00778 { return m_actions[i]->text(); }
00779 QString KActionPtrShortcutList::whatsThis( uint i ) const
00780 { return m_actions[i]->whatsThis(); }
00781 const KShortcut& KActionPtrShortcutList::shortcut( uint i ) const
00782 { return m_actions[i]->shortcut(); }
00783 const KShortcut& KActionPtrShortcutList::shortcutDefault( uint i ) const
00784 { return m_actions[i]->shortcutDefault(); }
00785 bool KActionPtrShortcutList::isConfigurable( uint i ) const
00786 { return m_actions[i]->isShortcutConfigurable(); }
00787 bool KActionPtrShortcutList::setShortcut( uint i, const KShortcut& cut )
00788 { return m_actions[i]->setShortcut( cut ); }
00789 QVariant KActionPtrShortcutList::getOther( Other, uint ) const
00790 { return QVariant(); }
00791 bool KActionPtrShortcutList::setOther( Other, uint, QVariant )
00792 { return false; }
00793 bool KActionPtrShortcutList::save() const
00794 { return false; }
00795
00796 void KActionShortcutList::virtual_hook( int id, void* data )
00797 { KShortcutList::virtual_hook( id, data ); }
00798
00799 void KActionPtrShortcutList::virtual_hook( int id, void* data )
00800 { KShortcutList::virtual_hook( id, data ); }
00801
00802 void KActionCollection::virtual_hook( int, void* )
00803 { }
00804
00805
00806
00807
00808 #include "kactioncollection.moc"