• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

kaction.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
00003               (C) 1999 Simon Hausmann <hausmann@kde.org>
00004               (C) 2000 Nicolas Hadacek <haadcek@kde.org>
00005               (C) 2000 Kurt Granroth <granroth@kde.org>
00006               (C) 2000 Michael Koch <koch@kde.org>
00007               (C) 2001 Holger Freyther <freyther@kde.org>
00008               (C) 2002 Ellis Whitehead <ellis@kde.org>
00009               (C) 2002 Joseph Wenninger <jowenn@kde.org>
00010 
00011     This library is free software; you can redistribute it and/or
00012     modify it under the terms of the GNU Library General Public
00013     License version 2 as published by the Free Software Foundation.
00014 
00015     This library is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018     Library General Public License for more details.
00019 
00020     You should have received a copy of the GNU Library General Public License
00021     along with this library; see the file COPYING.LIB.  If not, write to
00022     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00023     Boston, MA 02110-1301, USA.
00024 */
00025 
00026 #include "kaction.h"
00027 
00028 #include <assert.h>
00029 
00030 #include <qtooltip.h>
00031 #include <qwhatsthis.h>
00032 
00033 #include <kaccel.h>
00034 #include <kaccelbase.h>
00035 #include <kaccelprivate.h>
00036 #include <kapplication.h>
00037 #include <kdebug.h>
00038 #include <kguiitem.h>
00039 #include <kmainwindow.h>
00040 #include <kmenubar.h>
00041 #include <kpopupmenu.h>
00042 #include <ktoolbar.h>
00043 #include <ktoolbarbutton.h>
00044 
00066 int KAction::getToolButtonID()
00067 {
00068     static int toolbutton_no = -2;
00069     return toolbutton_no--;
00070 }
00071 
00072 //---------------------------------------------------------------------
00073 // KAction::KActionPrivate
00074 //---------------------------------------------------------------------
00075 
00076 class KAction::KActionPrivate : public KGuiItem
00077 {
00078 public:
00079   KActionPrivate() : KGuiItem()
00080   {
00081     m_kaccel = 0;
00082     m_configurable = true;
00083   }
00084 
00085   KAccel *m_kaccel;
00086   QValueList<KAccel*> m_kaccelList;
00087 
00088   QString m_groupText;
00089   QString m_group;
00090 
00091   KShortcut m_cut;
00092   KShortcut m_cutDefault;
00093 
00094   bool m_configurable;
00095 
00096   struct Container
00097   {
00098     Container() { m_container = 0; m_representative = 0; m_id = 0; }
00099     Container( const Container& s ) { m_container = s.m_container;
00100                                       m_id = s.m_id; m_representative = s.m_representative; }
00101     QWidget* m_container;
00102     int m_id;
00103     QWidget* m_representative;
00104   };
00105 
00106   QValueList<Container> m_containers;
00107 };
00108 
00109 //---------------------------------------------------------------------
00110 // KAction
00111 //---------------------------------------------------------------------
00112 
00113 KAction::KAction( const QString& text, const KShortcut& cut,
00114              const QObject* receiver, const char* slot,
00115              KActionCollection* parent, const char* name )
00116 : QObject( parent, name ), d(new KActionPrivate)
00117 {
00118     initPrivate( text, cut, receiver, slot );
00119 }
00120 
00121 KAction::KAction( const QString& text, const QString& sIconName, const KShortcut& cut,
00122     const QObject* receiver, const char* slot,
00123     KActionCollection* parent, const char* name )
00124 : QObject( parent, name ), d(new KActionPrivate)
00125 {
00126     initPrivate( text, cut, receiver, slot );
00127     d->setIconName( sIconName );
00128 }
00129 
00130 KAction::KAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
00131     const QObject* receiver, const char* slot,
00132     KActionCollection* parent, const char* name )
00133 : QObject( parent, name ), d(new KActionPrivate)
00134 {
00135     initPrivate( text, cut, receiver, slot );
00136     d->setIconSet( pix );
00137 }
00138 
00139 KAction::KAction( const KGuiItem& item, const KShortcut& cut,
00140     const QObject* receiver, const char* slot,
00141     KActionCollection* parent, const char* name )
00142 : QObject( parent, name ), d(new KActionPrivate)
00143 {
00144     initPrivate( item.text(), cut, receiver, slot );
00145     if( item.hasIcon() )
00146         setIcon( item.iconName() );
00147     setToolTip( item.toolTip() );
00148     setWhatsThis( item.whatsThis() );
00149 }
00150 
00151 #ifndef KDE_NO_COMPAT // KDE 4: remove
00152 KAction::KAction( const QString& text, const KShortcut& cut,
00153                   QObject* parent, const char* name )
00154  : QObject( parent, name ), d(new KActionPrivate)
00155 {
00156     initPrivate( text, cut, 0, 0 );
00157 }
00158 
00159 KAction::KAction( const QString& text, const KShortcut& cut,
00160                   const QObject* receiver,
00161                   const char* slot, QObject* parent, const char* name )
00162  : QObject( parent, name ), d(new KActionPrivate)
00163 {
00164     initPrivate( text, cut, receiver, slot );
00165 }
00166 
00167 KAction::KAction( const QString& text, const QIconSet& pix,
00168                   const KShortcut& cut,
00169                   QObject* parent, const char* name )
00170  : QObject( parent, name ), d(new KActionPrivate)
00171 {
00172     initPrivate( text, cut, 0, 0 );
00173     setIconSet( pix );
00174 }
00175 
00176 KAction::KAction( const QString& text, const QString& pix,
00177                   const KShortcut& cut,
00178                   QObject* parent, const char* name )
00179 : QObject( parent, name ), d(new KActionPrivate)
00180 {
00181     initPrivate( text, cut, 0, 0 );
00182     d->setIconName( pix );
00183 }
00184 
00185 KAction::KAction( const QString& text, const QIconSet& pix,
00186                   const KShortcut& cut,
00187                   const QObject* receiver, const char* slot, QObject* parent,
00188                   const char* name )
00189  : QObject( parent, name ), d(new KActionPrivate)
00190 {
00191     initPrivate( text, cut, receiver, slot );
00192     setIconSet( pix );
00193 }
00194 
00195 KAction::KAction( const QString& text, const QString& pix,
00196                   const KShortcut& cut,
00197                   const QObject* receiver, const char* slot, QObject* parent,
00198                   const char* name )
00199   : QObject( parent, name ), d(new KActionPrivate)
00200 {
00201     initPrivate( text, cut, receiver, slot );
00202     d->setIconName(pix);
00203 }
00204 
00205 KAction::KAction( QObject* parent, const char* name )
00206  : QObject( parent, name ), d(new KActionPrivate)
00207 {
00208     initPrivate( QString::null, KShortcut(), 0, 0 );
00209 }
00210 #endif // KDE 4: remove end
00211 
00212 KAction::~KAction()
00213 {
00214     kdDebug(129) << "KAction::~KAction( this = \"" << name() << "\" )" << endl; // -- ellis
00215 #ifndef KDE_NO_COMPAT
00216      if (d->m_kaccel)
00217        unplugAccel();
00218 #endif
00219 
00220     // If actionCollection hasn't already been destructed,
00221     if ( m_parentCollection ) {
00222         m_parentCollection->take( this );
00223 
00224         const QValueList<KAccel*> & accelList = d->m_kaccelList;
00225         QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
00226         const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
00227 
00228         const char * const namePtr = name();
00229         for (; itr != itrEnd; ++itr )
00230             (*itr)->remove(namePtr);
00231 
00232     }
00233 
00234     // Do not call unplugAll from here, as tempting as it sounds.
00235     // KAction is designed around the idea that you need to plug
00236     // _and_ to unplug it "manually". Unplugging leads to an important
00237     // slowdown when e.g. closing the window, in which case we simply
00238     // want to destroy everything asap, not to remove actions one by one
00239     // from the GUI.
00240 
00241     delete d;
00242 }
00243 
00244 void KAction::initPrivate( const QString& text, const KShortcut& cut,
00245                   const QObject* receiver, const char* slot )
00246 {
00247     d->m_cutDefault = cut;
00248 
00249     m_parentCollection = dynamic_cast<KActionCollection *>( parent() );
00250     kdDebug(129) << "KAction::initPrivate(): this = " << this << " name = \"" << name() << "\" cut = " << cut.toStringInternal() << " m_parentCollection = " << m_parentCollection << endl;
00251     if ( m_parentCollection )
00252         m_parentCollection->insert( this );
00253 
00254     if ( receiver && slot )
00255         connect( this, SIGNAL( activated() ), receiver, slot );
00256 
00257     if( !cut.isNull() && !qstrcmp( name(), "unnamed" ) )
00258         kdWarning(129) << "KAction::initPrivate(): trying to assign a shortcut (" << cut.toStringInternal() << ") to an unnamed action." << endl;
00259     d->setText( text );
00260     initShortcut( cut );
00261 }
00262 
00263 bool KAction::isPlugged() const
00264 {
00265   return (!d->m_containers.empty()) || d->m_kaccel;
00266 }
00267 
00268 bool KAction::isPlugged( const QWidget *container ) const
00269 {
00270   return findContainer( container ) > -1;
00271 }
00272 
00273 bool KAction::isPlugged( const QWidget *container, int id ) const
00274 {
00275   int i = findContainer( container );
00276   return ( i > -1 && itemId( i ) == id );
00277 }
00278 
00279 bool KAction::isPlugged( const QWidget *container, const QWidget *_representative ) const
00280 {
00281   int i = findContainer( container );
00282   return ( i > -1 && representative( i ) == _representative );
00283 }
00284 
00285 
00286 /*
00287 Three actionCollection conditions:
00288     1) Scope is known on creation and KAccel object is created (e.g. KMainWindow)
00289     2) Scope is unknown and no KAccel object is available (e.g. KXMLGUIClient)
00290         a) addClient() will be called on object
00291         b) we just want to add the actions to another KXMLGUIClient object
00292 
00293 The question is how to do we incorporate #2b into the XMLGUI framework?
00294 
00295 
00296 We have a KCommandHistory object with undo and redo actions in a passed actionCollection
00297 We have a KoDoc object which holds a KCommandHistory object and the actionCollection
00298 We have two KoView objects which both point to the same KoDoc object
00299 Undo and Redo should be available in both KoView objects, and
00300     calling the undo->setEnabled() should affect both KoViews
00301 
00302 When addClient is called, it needs to be able to find the undo and redo actions
00303 When it calls plug() on them, they need to be inserted into the KAccel object of the appropriate KoView
00304 
00305 In this case, the actionCollection belongs to KoDoc and we need to let it know that its shortcuts
00306 have the same scope as the KoView actionCollection
00307 
00308 KXMLGUIClient::addSubActionCollection
00309 
00310 Document:
00311     create document actions
00312 
00313 View
00314     create view actions
00315     add document actionCollection as sub-collection
00316 
00317 A parentCollection is created
00318 Scenario 1: parentCollection has a focus widget set (e.g. via KMainWindow)
00319     A KAccel object is created in the parentCollection
00320     A KAction is created with parent=parentCollection
00321     The shortcut is inserted into this actionCollection
00322     Scenario 1a: xml isn't used
00323         done
00324     Scenario 1b: KXMLGUIBuilder::addClient() called
00325         setWidget is called -- ignore
00326         shortcuts are set
00327 Scenario 2: parentCollection has no focus widget (e.g., KParts)
00328     A KAction is created with parent=parentCollection
00329     Scenario 2a: xml isn't used
00330         no shortcuts
00331     Scenario 2b: KXMLGUIBuilder::addClient() called
00332         setWidget is called
00333         shortcuts are inserted into current KAccel
00334         shortcuts are set in all other KAccels, if the action is present in the other KAccels
00335 */
00336 
00337 /*
00338 shortcut may be set:
00339     - on construction
00340     - on plug
00341     - on reading XML
00342     - on plugAccel (deprecated)
00343 
00344 On Construction: [via initShortcut()]
00345     insert into KAccel of m_parentCollection,
00346         if kaccel() && isAutoConnectShortcuts() exists
00347 
00348 On Plug: [via plug() -> plugShortcut()]
00349     insert into KAccel of m_parentCollection, if exists and not already inserted into
00350 
00351 On Read XML: [via setShortcut()]
00352     set in all current KAccels
00353     insert into KAccel of m_parentCollection, if exists and not already inserted into
00354 */
00355 
00356 KAccel* KAction::kaccelCurrent()
00357 {
00358   if( m_parentCollection && m_parentCollection->builderKAccel() )
00359     return m_parentCollection->builderKAccel();
00360   else if( m_parentCollection && m_parentCollection->kaccel() )
00361     return m_parentCollection->kaccel();
00362   else
00363     return 0L;
00364 }
00365 
00366 // Only to be called from initPrivate()
00367 bool KAction::initShortcut( const KShortcut& cut )
00368 {
00369     d->m_cut = cut;
00370 
00371     // Only insert action into KAccel if it has a valid name,
00372     if( qstrcmp( name(), "unnamed" ) &&
00373         m_parentCollection &&
00374         m_parentCollection->isAutoConnectShortcuts() &&
00375         m_parentCollection->kaccel() )
00376     {
00377         insertKAccel( m_parentCollection->kaccel() );
00378         return true;
00379     }
00380     return false;
00381  }
00382 
00383 // Only to be called from plug()
00384 void KAction::plugShortcut()
00385 {
00386   KAccel* const kaccel = kaccelCurrent();
00387 
00388   //kdDebug(129) << "KAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl;
00389   if( kaccel && qstrcmp( name(), "unnamed" ) ) {
00390     // Check if already plugged into current KAccel object
00391     const QValueList<KAccel*> & accelList = d->m_kaccelList;
00392     QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
00393     const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
00394 
00395     for( ; itr != itrEnd; ++itr) {
00396       if( (*itr) == kaccel )
00397         return;
00398     }
00399 
00400     insertKAccel( kaccel );
00401   }
00402 }
00403 
00404 bool KAction::setShortcut( const KShortcut& cut )
00405 {
00406   bool bChanged = (d->m_cut != cut);
00407   d->m_cut = cut;
00408 
00409   KAccel* const kaccel = kaccelCurrent();
00410   bool bInsertRequired = true;
00411   // Apply new shortcut to all existing KAccel objects
00412 
00413   const QValueList<KAccel*> & accelList = d->m_kaccelList;
00414   QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
00415   const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
00416 
00417   for( ; itr != itrEnd; ++itr) {
00418     // Check whether shortcut has already been plugged into
00419     //  the current kaccel object.
00420     if( (*itr) == kaccel )
00421       bInsertRequired = false;
00422     if( bChanged )
00423       updateKAccelShortcut( *itr );
00424   }
00425 
00426   // Only insert action into KAccel if it has a valid name,
00427   if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) )
00428     insertKAccel( kaccel );
00429 
00430   if( bChanged ) {
00431 #ifndef KDE_NO_COMPAT    // KDE 4: remove
00432     if ( d->m_kaccel )
00433       d->m_kaccel->setShortcut( name(), cut );
00434 #endif    // KDE 4: remove end
00435       int len = containerCount();
00436       for( int i = 0; i < len; ++i )
00437           updateShortcut( i );
00438   }
00439   return true;
00440 }
00441 
00442 bool KAction::updateKAccelShortcut( KAccel* kaccel )
00443 {
00444   // Check if action is permitted
00445   if (kapp && !kapp->authorizeKAction(name()))
00446     return false;
00447 
00448   bool b = true;
00449 
00450   if ( !kaccel->actions().actionPtr( name() ) ) {
00451     if(!d->m_cut.isNull() ) {
00452       kdDebug(129) << "Inserting " << name() << ", " << d->text() << ", " << d->plainText() << endl;
00453       b = kaccel->insert( name(), d->plainText(), QString::null,
00454           d->m_cut,
00455           this, SLOT(slotActivated()),
00456           isShortcutConfigurable(), isEnabled() );
00457     }
00458   }
00459   else
00460     b = kaccel->setShortcut( name(), d->m_cut );
00461 
00462   return b;
00463 }
00464 
00465 void KAction::insertKAccel( KAccel* kaccel )
00466 {
00467   //kdDebug(129) << "KAction::insertKAccel( " << kaccel << " ): this = " << this << endl;
00468   if ( !kaccel->actions().actionPtr( name() ) ) {
00469     if( updateKAccelShortcut( kaccel ) ) {
00470       d->m_kaccelList.append( kaccel );
00471       connect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
00472     }
00473   }
00474   else
00475     kdWarning(129) << "KAction::insertKAccel( kaccel = " << kaccel << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis
00476 }
00477 
00478 void KAction::removeKAccel( KAccel* kaccel )
00479 {
00480   //kdDebug(129) << "KAction::removeKAccel( " << i << " ): this = " << this << endl;
00481   QValueList<KAccel*> & accelList = d->m_kaccelList;
00482   QValueList<KAccel*>::iterator itr = accelList.begin();
00483   const QValueList<KAccel*>::iterator itrEnd = accelList.end();
00484 
00485   for( ; itr != itrEnd; ++itr) {
00486     if( (*itr) == kaccel ) {
00487       kaccel->remove( name() );
00488       accelList.remove( itr );
00489       disconnect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
00490       break;
00491     }
00492   }
00493 }
00494 
00495 #ifndef KDE_NO_COMPAT
00496 // KDE 4: remove
00497 void KAction::setAccel( int keyQt )
00498 {
00499   setShortcut( KShortcut(keyQt) );
00500 }
00501 #endif // KDE 4: remove end
00502 
00503 void KAction::updateShortcut( int i )
00504 {
00505   int id = itemId( i );
00506 
00507   QWidget* w = container( i );
00508   if ( ::qt_cast<QPopupMenu *>( w ) ) {
00509     QPopupMenu* menu = static_cast<QPopupMenu*>(w);
00510     updateShortcut( menu, id );
00511   }
00512   else if ( ::qt_cast<QMenuBar *>( w ) )
00513     static_cast<QMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id );
00514 }
00515 
00516 void KAction::updateShortcut( QPopupMenu* menu, int id )
00517 {
00518   //kdDebug(129) << "KAction::updateShortcut(): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl;
00519   // If the action has a KAccel object,
00520   //  show the string representation of its shortcut.
00521   if ( d->m_kaccel || d->m_kaccelList.count() ) {
00522     QString s = menu->text( id );
00523     int i = s.find( '\t' );
00524     if ( i >= 0 )
00525       s.replace( i+1, s.length()-i, d->m_cut.seq(0).toString() );
00526     else
00527       s += "\t" + d->m_cut.seq(0).toString();
00528 
00529     menu->changeItem( id, s );
00530   }
00531   // Otherwise insert the shortcut itself into the popup menu.
00532   else {
00533     // This is a fall-hack in case the KAction is missing a proper parent collection.
00534     //  It should be removed eventually. --ellis
00535     menu->setAccel( d->m_cut.keyCodeQt(), id );
00536     kdDebug(129) << "KAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No KAccel, probably missing a parent collection." << endl;
00537   }
00538 }
00539 
00540 const KShortcut& KAction::shortcut() const
00541 {
00542   return d->m_cut;
00543 }
00544 
00545 const KShortcut& KAction::shortcutDefault() const
00546 {
00547   return d->m_cutDefault;
00548 }
00549 
00550 QString KAction::shortcutText() const
00551 {
00552   return d->m_cut.toStringInternal();
00553 }
00554 
00555 void KAction::setShortcutText( const QString& s )
00556 {
00557   setShortcut( KShortcut(s) );
00558 }
00559 
00560 #ifndef KDE_NO_COMPAT // Remove in KDE 4
00561 int KAction::accel() const
00562 {
00563   return d->m_cut.keyCodeQt();
00564 }
00565 #endif
00566 
00567 void KAction::setGroup( const QString& grp )
00568 {
00569   d->m_group = grp;
00570 
00571   int len = containerCount();
00572   for( int i = 0; i < len; ++i )
00573     updateGroup( i );
00574 }
00575 
00576 void KAction::updateGroup( int )
00577 {
00578   // DO SOMETHING
00579 }
00580 
00581 QString KAction::group() const
00582 {
00583   return d->m_group;
00584 }
00585 
00586 bool KAction::isEnabled() const
00587 {
00588   return d->isEnabled();
00589 }
00590 
00591 bool KAction::isShortcutConfigurable() const
00592 {
00593   return d->m_configurable;
00594 }
00595 
00596 void KAction::setToolTip( const QString& tt )
00597 {
00598   d->setToolTip( tt );
00599 
00600   int len = containerCount();
00601   for( int i = 0; i < len; ++i )
00602     updateToolTip( i );
00603 }
00604 
00605 void KAction::updateToolTip( int i )
00606 {
00607   QWidget *w = container( i );
00608 
00609   if ( ::qt_cast<KToolBar *>( w ) )
00610     QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() );
00611 }
00612 
00613 QString KAction::toolTip() const
00614 {
00615   return d->toolTip();
00616 }
00617 
00618 int KAction::plug( QWidget *w, int index )
00619 {
00620   //kdDebug(129) << "KAction::plug( " << w << ", " << index << " )" << endl;
00621   if (!w ) {
00622     kdWarning(129) << "KAction::plug called with 0 argument\n";
00623     return -1;
00624   }
00625 
00626   // Ellis: print warning if there is a shortcut, but no KAccel available (often due to no widget available in the actioncollection)
00627   // David: Well, it doesn't matter much, things still work (e.g. Undo in koffice) via QAccel.
00628   // We should probably re-enable the warning for things that only KAccel can do, though - e.g. WIN key (mapped to Meta).
00629 #if 0 //ndef NDEBUG
00630   KAccel* kaccel = kaccelCurrent();
00631   if( !d->m_cut.isNull() && !kaccel ) {
00632     kdDebug(129) << "KAction::plug(): has no KAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis
00633   }
00634 #endif
00635 
00636   // Check if action is permitted
00637   if (kapp && !kapp->authorizeKAction(name()))
00638     return -1;
00639 
00640   plugShortcut();
00641 
00642   if ( ::qt_cast<QPopupMenu *>( w ) )
00643   {
00644     QPopupMenu* menu = static_cast<QPopupMenu*>( w );
00645     int id;
00646     // Don't insert shortcut into menu if it's already in a KAccel object.
00647     int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt();
00648 
00649     if ( d->hasIcon() )
00650     {
00651         KInstance *instance;
00652         if ( m_parentCollection )
00653           instance = m_parentCollection->instance();
00654         else
00655           instance = KGlobal::instance();
00656         id = menu->insertItem( d->iconSet( KIcon::Small, 0, instance ), d->text(), this,//dsweet
00657                                  SLOT( slotPopupActivated() ), keyQt,
00658                                  -1, index );
00659     }
00660     else
00661         id = menu->insertItem( d->text(), this,
00662                                SLOT( slotPopupActivated() ),
00663                                keyQt, -1, index );
00664 
00665     // If the shortcut is already in a KAccel object, then
00666     //  we need to set the menu item's shortcut text.
00667     if ( d->m_kaccelList.count() || d->m_kaccel )
00668         updateShortcut( menu, id );
00669 
00670     // call setItemEnabled only if the item really should be disabled,
00671     // because that method is slow and the item is per default enabled
00672     if ( !d->isEnabled() )
00673         menu->setItemEnabled( id, false );
00674 
00675     if ( !d->whatsThis().isEmpty() )
00676         menu->setWhatsThis( id, whatsThisWithIcon() );
00677 
00678     addContainer( menu, id );
00679     connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
00680 
00681     if ( m_parentCollection )
00682       m_parentCollection->connectHighlight( menu, this );
00683 
00684     return d->m_containers.count() - 1;
00685   }
00686   else if ( ::qt_cast<KToolBar *>( w ) )
00687   {
00688     KToolBar *bar = static_cast<KToolBar *>( w );
00689 
00690     int id_ = getToolButtonID();
00691     KInstance *instance;
00692     if ( m_parentCollection )
00693       instance = m_parentCollection->instance();
00694     else
00695       instance = KGlobal::instance();
00696 
00697     if ( icon().isEmpty() && !iconSet().pixmap().isNull() ) // old code using QIconSet directly
00698     {
00699         bar->insertButton( iconSet().pixmap(), id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
00700                            SLOT( slotButtonClicked(int, Qt::ButtonState) ),
00701                            d->isEnabled(), d->plainText(), index );
00702     }
00703     else
00704     {
00705         QString icon = d->iconName();
00706         if ( icon.isEmpty() )
00707             icon = "unknown";
00708         bar->insertButton( icon, id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
00709                            SLOT( slotButtonClicked(int, Qt::ButtonState) ),
00710                            d->isEnabled(), d->plainText(), index, instance );
00711     }
00712 
00713     KToolBarButton* ktb = bar->getButton(id_);
00714     ktb->setName( QCString("toolbutton_")+name() );
00715 
00716     if ( !d->whatsThis().isEmpty() )
00717         QWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() );
00718 
00719     if ( !d->toolTip().isEmpty() )
00720       QToolTip::add( bar->getButton(id_), d->toolTip() );
00721 
00722     addContainer( bar, id_ );
00723 
00724     connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
00725 
00726     if ( m_parentCollection )
00727       m_parentCollection->connectHighlight( bar, this );
00728 
00729     return containerCount() - 1;
00730   }
00731 
00732   return -1;
00733 }
00734 
00735 void KAction::unplug( QWidget *w )
00736 {
00737   int i = findContainer( w );
00738   if ( i == -1 )
00739     return;
00740   int id = itemId( i );
00741 
00742   if ( ::qt_cast<QPopupMenu *>( w ) )
00743   {
00744     QPopupMenu *menu = static_cast<QPopupMenu *>( w );
00745     menu->removeItem( id );
00746   }
00747   else if ( ::qt_cast<KToolBar *>( w ) )
00748   {
00749     KToolBar *bar = static_cast<KToolBar *>( w );
00750     bar->removeItemDelayed( id );
00751   }
00752   else if ( ::qt_cast<QMenuBar *>( w ) )
00753   {
00754     QMenuBar *bar = static_cast<QMenuBar *>( w );
00755     bar->removeItem( id );
00756   }
00757 
00758   removeContainer( i );
00759   if ( m_parentCollection )
00760     m_parentCollection->disconnectHighlight( w, this );
00761 }
00762 
00763 void KAction::plugAccel(KAccel *kacc, bool configurable)
00764 {
00765   kdWarning(129) << "KAction::plugAccel(): call to deprecated action." << endl;
00766   kdDebug(129) << kdBacktrace() << endl;
00767   //kdDebug(129) << "KAction::plugAccel( kacc = " << kacc << " ): name \"" << name() << "\"" << endl;
00768   if ( d->m_kaccel )
00769     unplugAccel();
00770 
00771   // If the parent collection's accel ptr isn't set yet
00772   //if ( m_parentCollection && !m_parentCollection->accel() )
00773   //  m_parentCollection->setAccel( kacc );
00774 
00775   // We can only plug this action into the given KAccel object
00776   //  if it does not already contain an action with the same name.
00777   if ( !kacc->actions().actionPtr(name()) )
00778   {
00779     d->m_kaccel = kacc;
00780     d->m_kaccel->insert(name(), d->plainText(), QString::null,
00781         KShortcut(d->m_cut),
00782         this, SLOT(slotActivated()),
00783         configurable, isEnabled());
00784     connect(d->m_kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()));
00785     //connect(d->m_kaccel, SIGNAL(keycodeChanged()), this, SLOT(slotKeycodeChanged()));
00786   }
00787   else
00788     kdWarning(129) << "KAction::plugAccel( kacc = " << kacc << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis
00789 }
00790 
00791 void KAction::unplugAccel()
00792 {
00793   //kdDebug(129) << "KAction::unplugAccel() " << this << " " << name() << endl;
00794   if ( d->m_kaccel )
00795   {
00796     d->m_kaccel->remove(name());
00797     d->m_kaccel = 0;
00798   }
00799 }
00800 
00801 void KAction::plugMainWindowAccel( QWidget *w )
00802 {
00803   // Note: topLevelWidget() stops too early, we can't use it.
00804   QWidget * tl = w;
00805   QWidget * n;
00806   while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store
00807     tl = n;
00808 
00809   KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow
00810   if (mw)
00811     plugAccel( mw->accel() );
00812   else
00813     kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl;
00814 }
00815 
00816 void KAction::setEnabled(bool enable)
00817 {
00818   //kdDebug(129) << "KAction::setEnabled( " << enable << " ): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl;
00819   if ( enable == d->isEnabled() )
00820     return;
00821 
00822 #ifndef KDE_NO_COMPAT
00823   // KDE 4: remove
00824   if (d->m_kaccel)
00825     d->m_kaccel->setEnabled(name(), enable);
00826 #endif  // KDE 4: remove end
00827 
00828   const QValueList<KAccel*> & accelList = d->m_kaccelList;
00829   QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
00830   const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
00831 
00832   const char * const namePtr = name();
00833 
00834   for ( ; itr != itrEnd; ++itr )
00835     (*itr)->setEnabled( namePtr, enable );
00836 
00837   d->setEnabled( enable );
00838 
00839   int len = containerCount();
00840   for( int i = 0; i < len; ++i )
00841     updateEnabled( i );
00842 
00843   emit enabled( d->isEnabled() );
00844 }
00845 
00846 void KAction::updateEnabled( int i )
00847 {
00848     QWidget *w = container( i );
00849 
00850     if ( ::qt_cast<QPopupMenu *>( w ) )
00851       static_cast<QPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
00852     else if ( ::qt_cast<QMenuBar *>( w ) )
00853       static_cast<QMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
00854     else if ( ::qt_cast<KToolBar *>( w ) )
00855       static_cast<KToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
00856 }
00857 
00858 void KAction::setShortcutConfigurable( bool b )
00859 {
00860     d->m_configurable = b;
00861 }
00862 
00863 void KAction::setText( const QString& text )
00864 {
00865 #ifndef KDE_NO_COMPAT
00866   // KDE 4: remove
00867   if (d->m_kaccel) {
00868     KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name());
00869     if (pAction)
00870       pAction->setLabel( text );
00871   }
00872 #endif  // KDE 4: remove end
00873   const QValueList<KAccel*> & accelList = d->m_kaccelList;
00874   QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
00875   const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
00876 
00877   const char * const namePtr = name();
00878 
00879   for( ; itr != itrEnd; ++itr ) {
00880     KAccelAction* const pAction = (*itr)->actions().actionPtr(namePtr);
00881     if (pAction)
00882       pAction->setLabel( text );
00883   }
00884 
00885   d->setText( text );
00886 
00887   int len = containerCount();
00888   for( int i = 0; i < len; ++i )
00889     updateText( i );
00890 }
00891 
00892 void KAction::updateText( int i )
00893 {
00894   QWidget *w = container( i );
00895 
00896   if ( ::qt_cast<QPopupMenu *>( w ) ) {
00897     int id = itemId( i );
00898     static_cast<QPopupMenu*>(w)->changeItem( id, d->text() );
00899     if (!d->m_cut.isNull())
00900       updateShortcut( static_cast<QPopupMenu*>(w), id );
00901   }
00902   else if ( ::qt_cast<QMenuBar *>( w ) )
00903     static_cast<QMenuBar*>(w)->changeItem( itemId( i ), d->text() );
00904   else if ( ::qt_cast<KToolBar *>( w ) )
00905   {
00906     QWidget *button = static_cast<KToolBar *>(w)->getWidget( itemId( i ) );
00907     if ( ::qt_cast<KToolBarButton *>( button ) )
00908       static_cast<KToolBarButton *>(button)->setText( d->plainText() );
00909   }
00910 }
00911 
00912 QString KAction::text() const
00913 {
00914   return d->text();
00915 }
00916 
00917 QString KAction::plainText() const
00918 {
00919   return d->plainText( );
00920 }
00921 
00922 void KAction::setIcon( const QString &icon )
00923 {
00924   d->setIconName( icon );
00925 
00926   // now handle any toolbars
00927   int len = containerCount();
00928   for ( int i = 0; i < len; ++i )
00929     updateIcon( i );
00930 }
00931 
00932 void KAction::updateIcon( int id )
00933 {
00934   QWidget* w = container( id );
00935 
00936   if ( ::qt_cast<QPopupMenu *>( w ) ) {
00937     int itemId_ = itemId( id );
00938     static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() );
00939     if (!d->m_cut.isNull())
00940       updateShortcut( static_cast<QPopupMenu*>(w), itemId_ );
00941   }
00942   else if ( ::qt_cast<QMenuBar *>( w ) )
00943     static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() );
00944   else if ( ::qt_cast<KToolBar *>( w ) )
00945     static_cast<KToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() );
00946 }
00947 
00948 QString KAction::icon() const
00949 {
00950   return d->iconName( );
00951 }
00952 
00953 void KAction::setIconSet( const QIconSet &iconset )
00954 {
00955   d->setIconSet( iconset );
00956 
00957   int len = containerCount();
00958   for( int i = 0; i < len; ++i )
00959     updateIconSet( i );
00960 }
00961 
00962 
00963 void KAction::updateIconSet( int id )
00964 {
00965   QWidget *w = container( id );
00966 
00967   if ( ::qt_cast<QPopupMenu *>( w ) )
00968   {
00969     int itemId_ = itemId( id );
00970     static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() );
00971     if (!d->m_cut.isNull())
00972       updateShortcut( static_cast<QPopupMenu*>(w), itemId_ );
00973   }
00974   else if ( ::qt_cast<QMenuBar *>( w ) )
00975     static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() );
00976   else if ( ::qt_cast<KToolBar *>( w ) )
00977   {
00978     if ( icon().isEmpty() && d->hasIcon() ) // only if there is no named icon ( scales better )
00979       static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet() );
00980     else
00981       static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet( KIcon::Small ) );
00982   }
00983 }
00984 
00985 QIconSet KAction::iconSet( KIcon::Group group, int size ) const
00986 {
00987     return d->iconSet( group, size );
00988 }
00989 
00990 bool KAction::hasIcon() const
00991 {
00992   return d->hasIcon();
00993 }
00994 
00995 void KAction::setWhatsThis( const QString& text )
00996 {
00997   d->setWhatsThis(  text );
00998 
00999   int len = containerCount();
01000   for( int i = 0; i < len; ++i )
01001     updateWhatsThis( i );
01002 }
01003 
01004 void KAction::updateWhatsThis( int i )
01005 {
01006   QPopupMenu* pm = popupMenu( i );
01007   if ( pm )
01008   {
01009     pm->setWhatsThis( itemId( i ), d->whatsThis() );
01010     return;
01011   }
01012 
01013   KToolBar *tb = toolBar( i );
01014   if ( tb )
01015   {
01016     QWidget *w = tb->getButton( itemId( i ) );
01017     QWhatsThis::remove( w );
01018     QWhatsThis::add( w, d->whatsThis() );
01019     return;
01020   }
01021 }
01022 
01023 QString KAction::whatsThis() const
01024 {
01025   return d->whatsThis();
01026 }
01027 
01028 QString KAction::whatsThisWithIcon() const
01029 {
01030     QString text = whatsThis();
01031     if (!d->iconName().isEmpty())
01032       return QString::fromLatin1("<img source=\"small|%1\"> %2").arg(d->iconName() ).arg(text);
01033     return text;
01034 }
01035 
01036 QWidget* KAction::container( int index ) const
01037 {
01038   assert( index < containerCount() );
01039   return d->m_containers[ index ].m_container;
01040 }
01041 
01042 KToolBar* KAction::toolBar( int index ) const
01043 {
01044     return dynamic_cast<KToolBar *>( d->m_containers[ index ].m_container );
01045 }
01046 
01047 QPopupMenu* KAction::popupMenu( int index ) const
01048 {
01049     return dynamic_cast<QPopupMenu *>( d->m_containers[ index ].m_container );
01050 }
01051 
01052 QWidget* KAction::representative( int index ) const
01053 {
01054   return d->m_containers[ index ].m_representative;
01055 }
01056 
01057 int KAction::itemId( int index ) const
01058 {
01059   return d->m_containers[ index ].m_id;
01060 }
01061 
01062 int KAction::containerCount() const
01063 {
01064   return d->m_containers.count();
01065 }
01066 
01067 uint KAction::kaccelCount() const
01068 {
01069   return d->m_kaccelList.count();
01070 }
01071 
01072 void KAction::addContainer( QWidget* c, int id )
01073 {
01074   KActionPrivate::Container p;
01075   p.m_container = c;
01076   p.m_id = id;
01077   d->m_containers.append( p );
01078 }
01079 
01080 void KAction::addContainer( QWidget* c, QWidget* w )
01081 {
01082   KActionPrivate::Container p;
01083   p.m_container = c;
01084   p.m_representative = w;
01085   d->m_containers.append( p );
01086 }
01087 
01088 void KAction::activate()
01089 {
01090   emit activated( KAction::EmulatedActivation, Qt::NoButton );
01091   slotActivated();
01092 }
01093 
01094 void KAction::slotActivated()
01095 {
01096   const QObject *senderObj = sender();
01097   if ( senderObj )
01098   {
01099     if ( ::qt_cast<KAccelPrivate *>( senderObj ) )
01100         emit activated( KAction::AccelActivation, Qt::NoButton );
01101   }
01102   emit activated();
01103 }
01104 
01105 // This catches signals emitted by KActions inserted into QPopupMenu
01106 // We do crude things inside it, because we need to know which
01107 // QPopupMenu emitted the signal. We need to be sure that it is
01108 // only called by QPopupMenus, we plugged us in.
01109 void KAction::slotPopupActivated()
01110 {
01111   if( ::qt_cast<QSignal *>(sender()))
01112   {
01113     int id = dynamic_cast<const QSignal *>(sender())->value().toInt();
01114     int pos = findContainer(id);
01115     if(pos != -1)
01116     {
01117       QPopupMenu* qpm = dynamic_cast<QPopupMenu *>( container(pos) );
01118       if(qpm)
01119       {
01120         KPopupMenu* kpm = dynamic_cast<KPopupMenu *>( qpm );
01121         Qt::ButtonState state;
01122         if ( kpm ) // KPopupMenu? Nice, it stores the state.
01123             state = kpm->state();
01124         else { // just a QPopupMenu? We'll ask for the state now then (small race condition?)
01125             kdDebug(129) << "KAction::slotPopupActivated not a KPopupMenu -> using keyboardMouseState()" << endl;
01126             state = KApplication::keyboardMouseState();
01127         }
01128         emit activated( KAction::PopupMenuActivation, state );
01129         slotActivated();
01130         return;
01131       }
01132     }
01133   }
01134 
01135   kdWarning(129)<<"Don't connect KAction::slotPopupActivated() to anything, expect into QPopupMenus which are in containers. Use slotActivated instead."<<endl;
01136   emit activated( KAction::PopupMenuActivation, Qt::NoButton );
01137   slotActivated();
01138 }
01139 
01140 void KAction::slotButtonClicked( int, Qt::ButtonState state )
01141 {
01142   kdDebug(129) << "slotButtonClicked() state=" << state << endl;
01143   emit activated( KAction::ToolBarActivation, state );
01144 
01145   // RightButton isn't really an activation
01146   if ( ( state & LeftButton ) || ( state & MidButton ) )
01147     slotActivated();
01148 }
01149 
01150 
01151 void KAction::slotDestroyed()
01152 {
01153   kdDebug(129) << "KAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl;
01154   const QObject* const o = sender();
01155 
01156 #ifndef KDE_NO_COMPAT  // KDE 4: remove
01157   if ( o == d->m_kaccel )
01158   {
01159     d->m_kaccel = 0;
01160     return;
01161   }
01162 #endif  // KDE 4: remove end
01163   QValueList<KAccel*> & accelList = d->m_kaccelList;
01164   QValueList<KAccel*>::iterator itr = accelList.begin();
01165   const QValueList<KAccel*>::iterator itrEnd = accelList.end();
01166 
01167   for( ; itr != itrEnd; ++itr)
01168   {
01169     if ( o == *itr )
01170     {
01171       disconnect( *itr, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
01172       accelList.remove(itr);
01173       return;
01174     }
01175   }
01176 
01177   int i;
01178   do
01179   {
01180     i = findContainer( static_cast<const QWidget*>( o ) );
01181     if ( i != -1 )
01182       removeContainer( i );
01183   } while ( i != -1 );
01184 }
01185 
01186 int KAction::findContainer( const QWidget* widget ) const
01187 {
01188   int pos = 0;
01189 
01190   const QValueList<KActionPrivate::Container> & containers = d->m_containers;
01191 
01192   QValueList<KActionPrivate::Container>::ConstIterator it = containers.constBegin();
01193   const QValueList<KActionPrivate::Container>::ConstIterator itEnd = containers.constEnd();
01194 
01195   while( it != itEnd )
01196   {
01197     if ( (*it).m_representative == widget || (*it).m_container == widget )
01198       return pos;
01199     ++it;
01200     ++pos;
01201   }
01202 
01203   return -1;
01204 }
01205 
01206 int KAction::findContainer( const int id ) const
01207 {
01208   int pos = 0;
01209 
01210   const QValueList<KActionPrivate::Container> & containers = d->m_containers;
01211 
01212   QValueList<KActionPrivate::Container>::ConstIterator it = containers.constBegin();
01213   const QValueList<KActionPrivate::Container>::ConstIterator itEnd = containers.constEnd();
01214 
01215   while( it != itEnd )
01216   {
01217     if ( (*it).m_id == id )
01218       return pos;
01219     ++it;
01220     ++pos;
01221   }
01222 
01223   return -1;
01224 }
01225 
01226 void KAction::removeContainer( int index )
01227 {
01228   int i = 0;
01229 
01230   QValueList<KActionPrivate::Container> & containers = d->m_containers;
01231 
01232   QValueList<KActionPrivate::Container>::Iterator it = containers.begin();
01233   const QValueList<KActionPrivate::Container>::Iterator itEnd = containers.end();
01234 
01235   while( it != itEnd )
01236   {
01237     if ( i == index )
01238     {
01239       containers.remove( it );
01240       return;
01241     }
01242     ++it;
01243     ++i;
01244   }
01245 }
01246 
01247 // FIXME: Remove this (ellis)
01248 void KAction::slotKeycodeChanged()
01249 {
01250   kdDebug(129) << "KAction::slotKeycodeChanged()" << endl; // -- ellis
01251   KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name());
01252   if( pAction )
01253     setShortcut(pAction->shortcut());
01254 }
01255 
01256 KActionCollection *KAction::parentCollection() const
01257 {
01258     return m_parentCollection;
01259 }
01260 
01261 void KAction::unplugAll()
01262 {
01263   while ( containerCount() != 0 )
01264     unplug( container( 0 ) );
01265 }
01266 
01267 const KGuiItem& KAction::guiItem() const
01268 {
01269     return *d;
01270 }
01271 
01272 void KAction::virtual_hook( int, void* )
01273 { /*BASE::virtual_hook( id, data );*/ }
01274 
01275 /* vim: et sw=2 ts=2
01276  */
01277 
01278 #include "kaction.moc"

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal