kdeui Library API Documentation

kaction.cpp

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