diff options
Diffstat (limited to 'tdeui/tdeaction.cpp')
-rw-r--r-- | tdeui/tdeaction.cpp | 1288 |
1 files changed, 1288 insertions, 0 deletions
diff --git a/tdeui/tdeaction.cpp b/tdeui/tdeaction.cpp new file mode 100644 index 000000000..24a940c2f --- /dev/null +++ b/tdeui/tdeaction.cpp @@ -0,0 +1,1288 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kaction.h" + +#include <assert.h> + +#include <tqtooltip.h> +#include <tqwhatsthis.h> + +#include <kaccel.h> +#include <kaccelbase.h> +#include <kaccelprivate.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kguiitem.h> +#include <kmainwindow.h> +#include <kmenubar.h> +#include <kpopupmenu.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> + +#include <ft2build.h> +#include <X11/Xdefs.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> + +#include <X11/Xft/Xft.h> + +/** +* How it works. +* TDEActionCollection is an organizing container for TDEActions. +* TDEActionCollection keeps track of the information necessary to handle +* configuration and shortcuts. +* +* Focus Widget pointer: +* This is the widget which is the focus for action shortcuts. +* It is set either by passing a TQWidget* to the TDEActionCollection constructor +* or by calling setWidget() if the widget wasn't known when the object was +* initially constructed (as in KXMLGUIClient and KParts::PartBase) +* +* Shortcuts: +* An action's shortcut will not not be connected unless a focus widget has +* been specified in TDEActionCollection. +* +* XML Filename: +* This is used to save user-modified settings back to the *ui.rc file. +* It is set by KXMLGUIFactory. +*/ + +int TDEAction::getToolButtonID() +{ + static int toolbutton_no = -2; + return toolbutton_no--; +} + +//--------------------------------------------------------------------- +// TDEAction::TDEActionPrivate +//--------------------------------------------------------------------- + +class TDEAction::TDEActionPrivate : public KGuiItem +{ +public: + TDEActionPrivate() : KGuiItem() + { + m_kaccel = 0; + m_configurable = true; + } + + TDEAccel *m_kaccel; + TQValueList<TDEAccel*> m_kaccelList; + + TQString m_groupText; + TQString m_group; + + TDEShortcut m_cut; + TDEShortcut m_cutDefault; + + bool m_configurable; + + struct Container + { + Container() { m_container = 0; m_representative = 0; m_id = 0; } + Container( const Container& s ) { m_container = s.m_container; + m_id = s.m_id; m_representative = s.m_representative; } + TQWidget* m_container; + int m_id; + TQWidget* m_representative; + }; + + TQValueList<Container> m_containers; +}; + +//--------------------------------------------------------------------- +// TDEAction +//--------------------------------------------------------------------- + +TDEAction::TDEAction( const TQString& text, const TDEShortcut& cut, + const TQObject* receiver, const char* slot, + TDEActionCollection* parent, const char* name ) +: TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, receiver, slot ); +} + +TDEAction::TDEAction( const TQString& text, const TQString& sIconName, const TDEShortcut& cut, + const TQObject* receiver, const char* slot, + TDEActionCollection* parent, const char* name ) +: TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName( sIconName ); +} + +TDEAction::TDEAction( const TQString& text, const TQIconSet& pix, const TDEShortcut& cut, + const TQObject* receiver, const char* slot, + TDEActionCollection* parent, const char* name ) +: TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconSet( pix ); +} + +TDEAction::TDEAction( const KGuiItem& item, const TDEShortcut& cut, + const TQObject* receiver, const char* slot, + TDEActionCollection* parent, const char* name ) +: TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( item.text(), cut, receiver, slot ); + if( item.hasIcon() ) + setIcon( item.iconName() ); + setToolTip( item.toolTip() ); + setWhatsThis( item.whatsThis() ); +} + +#ifndef KDE_NO_COMPAT // KDE 4: remove +TDEAction::TDEAction( const TQString& text, const TDEShortcut& cut, + TQObject* parent, const char* name ) + : TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, 0, 0 ); +} + +TDEAction::TDEAction( const TQString& text, const TDEShortcut& cut, + const TQObject* receiver, + const char* slot, TQObject* parent, const char* name ) + : TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, receiver, slot ); +} + +TDEAction::TDEAction( const TQString& text, const TQIconSet& pix, + const TDEShortcut& cut, + TQObject* parent, const char* name ) + : TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, 0, 0 ); + setIconSet( pix ); +} + +TDEAction::TDEAction( const TQString& text, const TQString& pix, + const TDEShortcut& cut, + TQObject* parent, const char* name ) +: TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, 0, 0 ); + d->setIconName( pix ); +} + +TDEAction::TDEAction( const TQString& text, const TQIconSet& pix, + const TDEShortcut& cut, + const TQObject* receiver, const char* slot, TQObject* parent, + const char* name ) + : TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, receiver, slot ); + setIconSet( pix ); +} + +TDEAction::TDEAction( const TQString& text, const TQString& pix, + const TDEShortcut& cut, + const TQObject* receiver, const char* slot, TQObject* parent, + const char* name ) + : TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName(pix); +} + +TDEAction::TDEAction( TQObject* parent, const char* name ) + : TQObject( parent, name ), d(new TDEActionPrivate) +{ + initPrivate( TQString::null, TDEShortcut(), 0, 0 ); +} +#endif // KDE 4: remove end + +TDEAction::~TDEAction() +{ + kdDebug(129) << "TDEAction::~TDEAction( this = \"" << name() << "\" )" << endl; // -- ellis +#ifndef KDE_NO_COMPAT + if (d->m_kaccel) + unplugAccel(); +#endif + + // If actionCollection hasn't already been destructed, + if ( m_parentCollection ) { + m_parentCollection->take( this ); + + const TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::const_iterator itr = accelList.constBegin(); + const TQValueList<TDEAccel*>::const_iterator itrEnd = accelList.constEnd(); + + const char * const namePtr = name(); + for (; itr != itrEnd; ++itr ) + (*itr)->remove(namePtr); + + } + + // Do not call unplugAll from here, as tempting as it sounds. + // TDEAction is designed around the idea that you need to plug + // _and_ to unplug it "manually". Unplugging leads to an important + // slowdown when e.g. closing the window, in which case we simply + // want to destroy everything asap, not to remove actions one by one + // from the GUI. + + delete d; +} + +void TDEAction::initPrivate( const TQString& text, const TDEShortcut& cut, + const TQObject* receiver, const char* slot ) +{ + d->m_cutDefault = cut; + + m_parentCollection = tqt_dynamic_cast<TDEActionCollection *>( parent() ); + kdDebug(129) << "TDEAction::initPrivate(): this = " << this << " name = \"" << name() << "\" cut = " << cut.toStringInternal() << " m_parentCollection = " << m_parentCollection << endl; + if ( m_parentCollection ) + m_parentCollection->insert( this ); + + if ( receiver && slot ) + connect( this, TQT_SIGNAL( activated() ), receiver, slot ); + + if( !cut.isNull() && !qstrcmp( name(), "unnamed" ) ) + kdWarning(129) << "TDEAction::initPrivate(): trying to assign a shortcut (" << cut.toStringInternal() << ") to an unnamed action." << endl; + d->setText( text ); + initShortcut( cut ); +} + +bool TDEAction::isPlugged() const +{ + return (!d->m_containers.empty()) || d->m_kaccel; +} + +bool TDEAction::isPlugged( const TQWidget *container ) const +{ + return findContainer( container ) > -1; +} + +bool TDEAction::isPlugged( const TQWidget *container, int id ) const +{ + int i = findContainer( container ); + return ( i > -1 && itemId( i ) == id ); +} + +bool TDEAction::isPlugged( const TQWidget *container, const TQWidget *_representative ) const +{ + int i = findContainer( container ); + return ( i > -1 && representative( i ) == _representative ); +} + + +/* +Three actionCollection conditions: + 1) Scope is known on creation and TDEAccel object is created (e.g. TDEMainWindow) + 2) Scope is unknown and no TDEAccel object is available (e.g. KXMLGUIClient) + a) addClient() will be called on object + b) we just want to add the actions to another KXMLGUIClient object + +The question is how to do we incorporate #2b into the XMLGUI framework? + + +We have a KCommandHistory object with undo and redo actions in a passed actionCollection +We have a KoDoc object which holds a KCommandHistory object and the actionCollection +We have two KoView objects which both point to the same KoDoc object +Undo and Redo should be available in both KoView objects, and + calling the undo->setEnabled() should affect both KoViews + +When addClient is called, it needs to be able to find the undo and redo actions +When it calls plug() on them, they need to be inserted into the TDEAccel object of the appropriate KoView + +In this case, the actionCollection belongs to KoDoc and we need to let it know that its shortcuts +have the same scope as the KoView actionCollection + +KXMLGUIClient::addSubActionCollection + +Document: + create document actions + +View + create view actions + add document actionCollection as sub-collection + +A parentCollection is created +Scenario 1: parentCollection has a focus widget set (e.g. via TDEMainWindow) + A TDEAccel object is created in the parentCollection + A TDEAction is created with parent=parentCollection + The shortcut is inserted into this actionCollection + Scenario 1a: xml isn't used + done + Scenario 1b: KXMLGUIBuilder::addClient() called + setWidget is called -- ignore + shortcuts are set +Scenario 2: parentCollection has no focus widget (e.g., KParts) + A TDEAction is created with parent=parentCollection + Scenario 2a: xml isn't used + no shortcuts + Scenario 2b: KXMLGUIBuilder::addClient() called + setWidget is called + shortcuts are inserted into current TDEAccel + shortcuts are set in all other TDEAccels, if the action is present in the other TDEAccels +*/ + +/* +shortcut may be set: + - on construction + - on plug + - on reading XML + - on plugAccel (deprecated) + +On Construction: [via initShortcut()] + insert into TDEAccel of m_parentCollection, + if kaccel() && isAutoConnectShortcuts() exists + +On Plug: [via plug() -> plugShortcut()] + insert into TDEAccel of m_parentCollection, if exists and not already inserted into + +On Read XML: [via setShortcut()] + set in all current TDEAccels + insert into TDEAccel of m_parentCollection, if exists and not already inserted into +*/ + +TDEAccel* TDEAction::kaccelCurrent() +{ + if( m_parentCollection && m_parentCollection->builderTDEAccel() ) + return m_parentCollection->builderTDEAccel(); + else if( m_parentCollection && m_parentCollection->kaccel() ) + return m_parentCollection->kaccel(); + else + return 0L; +} + +// Only to be called from initPrivate() +bool TDEAction::initShortcut( const TDEShortcut& cut ) +{ + d->m_cut = cut; + + // Only insert action into TDEAccel if it has a valid name, + if( qstrcmp( name(), "unnamed" ) && + m_parentCollection && + m_parentCollection->isAutoConnectShortcuts() && + m_parentCollection->kaccel() ) + { + insertTDEAccel( m_parentCollection->kaccel() ); + return true; + } + return false; + } + +// Only to be called from plug() +void TDEAction::plugShortcut() +{ + TDEAccel* const kaccel = kaccelCurrent(); + + //kdDebug(129) << "TDEAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl; + if( kaccel && qstrcmp( name(), "unnamed" ) ) { + // Check if already plugged into current TDEAccel object + const TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::const_iterator itr = accelList.constBegin(); + const TQValueList<TDEAccel*>::const_iterator itrEnd = accelList.constEnd(); + + for( ; itr != itrEnd; ++itr) { + if( (*itr) == kaccel ) + return; + } + + insertTDEAccel( kaccel ); + } +} + +bool TDEAction::setShortcut( const TDEShortcut& cut ) +{ + bool bChanged = (d->m_cut != cut); + d->m_cut = cut; + + TDEAccel* const kaccel = kaccelCurrent(); + bool bInsertRequired = true; + // Apply new shortcut to all existing TDEAccel objects + + const TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::const_iterator itr = accelList.constBegin(); + const TQValueList<TDEAccel*>::const_iterator itrEnd = accelList.constEnd(); + + for( ; itr != itrEnd; ++itr) { + // Check whether shortcut has already been plugged into + // the current kaccel object. + if( (*itr) == kaccel ) + bInsertRequired = false; + if( bChanged ) + updateTDEAccelShortcut( *itr ); + } + + // Only insert action into TDEAccel if it has a valid name, + if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) ) + insertTDEAccel( kaccel ); + + if( bChanged ) { +#ifndef KDE_NO_COMPAT // KDE 4: remove + if ( d->m_kaccel ) + d->m_kaccel->setShortcut( name(), cut ); +#endif // KDE 4: remove end + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateShortcut( i ); + } + return true; +} + +bool TDEAction::updateTDEAccelShortcut( TDEAccel* kaccel ) +{ + // Check if action is permitted + if (kapp && !kapp->authorizeTDEAction(name())) + return false; + + bool b = true; + + if ( !kaccel->actions().actionPtr( name() ) ) { + if(!d->m_cut.isNull() ) { + kdDebug(129) << "Inserting " << name() << ", " << d->text() << ", " << d->plainText() << endl; + b = kaccel->insert( name(), d->plainText(), TQString::null, + d->m_cut, + this, TQT_SLOT(slotActivated()), + isShortcutConfigurable(), isEnabled() ); + } + } + else + b = kaccel->setShortcut( name(), d->m_cut ); + + return b; +} + +void TDEAction::insertTDEAccel( TDEAccel* kaccel ) +{ + //kdDebug(129) << "TDEAction::insertTDEAccel( " << kaccel << " ): this = " << this << endl; + if ( !kaccel->actions().actionPtr( name() ) ) { + if( updateTDEAccelShortcut( kaccel ) ) { + d->m_kaccelList.append( kaccel ); + connect( kaccel, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotDestroyed()) ); + } + } + else + kdWarning(129) << "TDEAction::insertTDEAccel( kaccel = " << kaccel << " ): TDEAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis +} + +void TDEAction::removeTDEAccel( TDEAccel* kaccel ) +{ + //kdDebug(129) << "TDEAction::removeTDEAccel( " << i << " ): this = " << this << endl; + TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::iterator itr = accelList.begin(); + const TQValueList<TDEAccel*>::iterator itrEnd = accelList.end(); + + for( ; itr != itrEnd; ++itr) { + if( (*itr) == kaccel ) { + kaccel->remove( name() ); + accelList.remove( itr ); + disconnect( kaccel, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotDestroyed()) ); + break; + } + } +} + +#ifndef KDE_NO_COMPAT +// KDE 4: remove +void TDEAction::setAccel( int keyQt ) +{ + setShortcut( TDEShortcut(keyQt) ); +} +#endif // KDE 4: remove end + +void TDEAction::updateShortcut( int i ) +{ + int id = itemId( i ); + + TQWidget* w = container( i ); + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) { + TQPopupMenu* menu = static_cast<TQPopupMenu*>(w); + updateShortcut( menu, id ); + } + else if ( ::tqqt_cast<TQMenuBar *>( w ) ) + static_cast<TQMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id ); +} + +void TDEAction::updateShortcut( TQPopupMenu* menu, int id ) +{ + //kdDebug(129) << "TDEAction::updateShortcut(): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl; + // If the action has a TDEAccel object, + // show the string representation of its shortcut. + if ( d->m_kaccel || d->m_kaccelList.count() ) { + TQString s = menu->text( id ); + int i = s.find( '\t' ); + if ( i >= 0 ) + s.replace( i+1, s.length()-i, d->m_cut.seq(0).toString() ); + else + s += "\t" + d->m_cut.seq(0).toString(); + + menu->changeItem( id, s ); + } + // Otherwise insert the shortcut itself into the popup menu. + else { + // This is a fall-hack in case the TDEAction is missing a proper parent collection. + // It should be removed eventually. --ellis + menu->setAccel( d->m_cut.keyCodeQt(), id ); + kdDebug(129) << "TDEAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No TDEAccel, probably missing a parent collection." << endl; + } +} + +const TDEShortcut& TDEAction::shortcut() const +{ + return d->m_cut; +} + +const TDEShortcut& TDEAction::shortcutDefault() const +{ + return d->m_cutDefault; +} + +TQString TDEAction::shortcutText() const +{ + return d->m_cut.toStringInternal(); +} + +void TDEAction::setShortcutText( const TQString& s ) +{ + setShortcut( TDEShortcut(s) ); +} + +#ifndef KDE_NO_COMPAT // Remove in KDE 4 +int TDEAction::accel() const +{ + return d->m_cut.keyCodeQt(); +} +#endif + +void TDEAction::setGroup( const TQString& grp ) +{ + d->m_group = grp; + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateGroup( i ); +} + +void TDEAction::updateGroup( int ) +{ + // DO SOMETHING +} + +TQString TDEAction::group() const +{ + return d->m_group; +} + +bool TDEAction::isEnabled() const +{ + return d->isEnabled(); +} + +bool TDEAction::isShortcutConfigurable() const +{ + return d->m_configurable; +} + +void TDEAction::setToolTip( const TQString& tt ) +{ + d->setToolTip( tt ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateToolTip( i ); +} + +void TDEAction::updateToolTip( int i ) +{ + TQWidget *w = container( i ); + + if ( ::tqqt_cast<TDEToolBar *>( w ) ) + TQToolTip::add( static_cast<TDEToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() ); +} + +TQString TDEAction::toolTip() const +{ + return d->toolTip(); +} + +int TDEAction::plug( TQWidget *w, int index ) +{ + //kdDebug(129) << "TDEAction::plug( " << w << ", " << index << " )" << endl; + if (!w ) { + kdWarning(129) << "TDEAction::plug called with 0 argument\n"; + return -1; + } + + // Ellis: print warning if there is a shortcut, but no TDEAccel available (often due to no widget available in the actioncollection) + // David: Well, it doesn't matter much, things still work (e.g. Undo in koffice) via TQAccel. + // We should probably re-enable the warning for things that only TDEAccel can do, though - e.g. WIN key (mapped to Meta). +#if 0 //ndef NDEBUG + TDEAccel* kaccel = kaccelCurrent(); + if( !d->m_cut.isNull() && !kaccel ) { + kdDebug(129) << "TDEAction::plug(): has no TDEAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis + } +#endif + + // Check if action is permitted + if (kapp && !kapp->authorizeTDEAction(name())) + return -1; + + plugShortcut(); + + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) + { + TQPopupMenu* menu = static_cast<TQPopupMenu*>( w ); + int id; + // Don't insert shortcut into menu if it's already in a TDEAccel object. + int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt(); + + if ( d->hasIcon() ) + { + TDEInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = TDEGlobal::instance(); + id = menu->insertItem( d->iconSet( KIcon::Small, 0, instance ), d->text(), this,//dsweet + TQT_SLOT( slotPopupActivated() ), keyQt, + -1, index ); + } + else + id = menu->insertItem( d->text(), this, + TQT_SLOT( slotPopupActivated() ), + keyQt, -1, index ); + + // If the shortcut is already in a TDEAccel object, then + // we need to set the menu item's shortcut text. + if ( d->m_kaccelList.count() || d->m_kaccel ) + updateShortcut( menu, id ); + + // call setItemEnabled only if the item really should be disabled, + // because that method is slow and the item is per default enabled + if ( !d->isEnabled() ) + menu->setItemEnabled( id, false ); + + if ( !d->whatsThis().isEmpty() ) + menu->TQMenuData::setWhatsThis( id, whatsThisWithIcon() ); + + addContainer( menu, id ); + connect( menu, TQT_SIGNAL( destroyed() ), this, TQT_SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( menu, this ); + + return d->m_containers.count() - 1; + } + else if ( ::tqqt_cast<TDEToolBar *>( w ) ) + { + TDEToolBar *bar = static_cast<TDEToolBar *>( w ); + + int id_ = getToolButtonID(); + TDEInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = TDEGlobal::instance(); + + if ( icon().isEmpty() && !iconSet().pixmap().isNull() ) // old code using TQIconSet directly + { + bar->insertButton( iconSet().pixmap(), id_, TQT_SIGNAL( buttonClicked(int, TQt::ButtonState) ), this, + TQT_SLOT( slotButtonClicked(int, TQt::ButtonState) ), + d->isEnabled(), d->plainText(), index ); + } + else + { + TQString icon = d->iconName(); + if ( icon.isEmpty() ) + icon = "unknown"; + bar->insertButton( icon, id_, TQT_SIGNAL( buttonClicked(int, TQt::ButtonState) ), this, + TQT_SLOT( slotButtonClicked(int, TQt::ButtonState) ), + d->isEnabled(), d->plainText(), index, instance ); + } + + TDEToolBarButton* ktb = bar->getButton(id_); + ktb->setName( TQCString("toolbutton_")+name() ); + + if ( !d->whatsThis().isEmpty() ) + TQWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() ); + + if ( !d->toolTip().isEmpty() ) + TQToolTip::add( bar->getButton(id_), d->toolTip() ); + + addContainer( bar, id_ ); + + connect( bar, TQT_SIGNAL( destroyed() ), this, TQT_SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( bar, this ); + + return containerCount() - 1; + } + + return -1; +} + +void TDEAction::unplug( TQWidget *w ) +{ + int i = findContainer( w ); + if ( i == -1 ) + return; + int id = itemId( i ); + + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) + { + TQPopupMenu *menu = static_cast<TQPopupMenu *>( w ); + menu->removeItem( id ); + } + else if ( ::tqqt_cast<TDEToolBar *>( w ) ) + { + TDEToolBar *bar = static_cast<TDEToolBar *>( w ); + bar->removeItemDelayed( id ); + } + else if ( ::tqqt_cast<TQMenuBar *>( w ) ) + { + TQMenuBar *bar = static_cast<TQMenuBar *>( w ); + bar->removeItem( id ); + } + + removeContainer( i ); + if ( m_parentCollection ) + m_parentCollection->disconnectHighlight( w, this ); +} + +void TDEAction::plugAccel(TDEAccel *kacc, bool configurable) +{ + kdWarning(129) << "TDEAction::plugAccel(): call to deprecated action." << endl; + kdDebug(129) << kdBacktrace() << endl; + //kdDebug(129) << "TDEAction::plugAccel( kacc = " << kacc << " ): name \"" << name() << "\"" << endl; + if ( d->m_kaccel ) + unplugAccel(); + + // If the parent collection's accel ptr isn't set yet + //if ( m_parentCollection && !m_parentCollection->accel() ) + // m_parentCollection->setAccel( kacc ); + + // We can only plug this action into the given TDEAccel object + // if it does not already contain an action with the same name. + if ( !kacc->actions().actionPtr(name()) ) + { + d->m_kaccel = kacc; + d->m_kaccel->insert(name(), d->plainText(), TQString::null, + TDEShortcut(d->m_cut), + this, TQT_SLOT(slotActivated()), + configurable, isEnabled()); + connect(d->m_kaccel, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotDestroyed())); + //connect(d->m_kaccel, TQT_SIGNAL(keycodeChanged()), this, TQT_SLOT(slotKeycodeChanged())); + } + else + kdWarning(129) << "TDEAction::plugAccel( kacc = " << kacc << " ): TDEAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis +} + +void TDEAction::unplugAccel() +{ + //kdDebug(129) << "TDEAction::unplugAccel() " << this << " " << name() << endl; + if ( d->m_kaccel ) + { + d->m_kaccel->remove(name()); + d->m_kaccel = 0; + } +} + +void TDEAction::plugMainWindowAccel( TQWidget *w ) +{ + // Note: topLevelWidget() stops too early, we can't use it. + TQWidget * tl = w; + TQWidget * n; + while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store + tl = n; + + TDEMainWindow * mw = tqt_dynamic_cast<TDEMainWindow *>(tl); // try to see if it's a kmainwindow + if (mw) + plugAccel( mw->accel() ); + else + kdDebug(129) << "TDEAction::plugMainWindowAccel: Toplevel widget isn't a TDEMainWindow, can't plug accel. " << tl << endl; +} + +void TDEAction::setEnabled(bool enable) +{ + //kdDebug(129) << "TDEAction::setEnabled( " << enable << " ): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl; + if ( enable == d->isEnabled() ) + return; + +#ifndef KDE_NO_COMPAT + // KDE 4: remove + if (d->m_kaccel) + d->m_kaccel->setEnabled(name(), enable); +#endif // KDE 4: remove end + + const TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::const_iterator itr = accelList.constBegin(); + const TQValueList<TDEAccel*>::const_iterator itrEnd = accelList.constEnd(); + + const char * const namePtr = name(); + + for ( ; itr != itrEnd; ++itr ) + (*itr)->setEnabled( namePtr, enable ); + + d->setEnabled( enable ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateEnabled( i ); + + emit enabled( d->isEnabled() ); +} + +void TDEAction::updateEnabled( int i ) +{ + TQWidget *w = container( i ); + + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) + static_cast<TQPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( ::tqqt_cast<TQMenuBar *>( w ) ) + static_cast<TQMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( ::tqqt_cast<TDEToolBar *>( w ) ) + static_cast<TDEToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); +} + +void TDEAction::setShortcutConfigurable( bool b ) +{ + d->m_configurable = b; +} + +void TDEAction::setText( const TQString& text ) +{ +#ifndef KDE_NO_COMPAT + // KDE 4: remove + if (d->m_kaccel) { + TDEAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if (pAction) + pAction->setLabel( text ); + } +#endif // KDE 4: remove end + const TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::const_iterator itr = accelList.constBegin(); + const TQValueList<TDEAccel*>::const_iterator itrEnd = accelList.constEnd(); + + const char * const namePtr = name(); + + for( ; itr != itrEnd; ++itr ) { + TDEAccelAction* const pAction = (*itr)->actions().actionPtr(namePtr); + if (pAction) + pAction->setLabel( text ); + } + + d->setText( text ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateText( i ); +} + +void TDEAction::updateText( int i ) +{ + TQWidget *w = container( i ); + + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) { + int id = itemId( i ); + static_cast<TQPopupMenu*>(w)->changeItem( id, d->text() ); + if (!d->m_cut.isNull()) + updateShortcut( static_cast<TQPopupMenu*>(w), id ); + } + else if ( ::tqqt_cast<TQMenuBar *>( w ) ) + static_cast<TQMenuBar*>(w)->changeItem( itemId( i ), d->text() ); + else if ( ::tqqt_cast<TDEToolBar *>( w ) ) + { + TQWidget *button = static_cast<TDEToolBar *>(w)->getWidget( itemId( i ) ); + if ( ::tqqt_cast<TDEToolBarButton *>( button ) ) + static_cast<TDEToolBarButton *>(button)->setText( d->plainText() ); + } +} + +TQString TDEAction::text() const +{ + return d->text(); +} + +TQString TDEAction::plainText() const +{ + return d->plainText( ); +} + +void TDEAction::setIcon( const TQString &icon ) +{ + d->setIconName( icon ); + + // now handle any toolbars + int len = containerCount(); + for ( int i = 0; i < len; ++i ) + updateIcon( i ); +} + +void TDEAction::updateIcon( int id ) +{ + TQWidget* w = container( id ); + + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) { + int itemId_ = itemId( id ); + static_cast<TQPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() ); + if (!d->m_cut.isNull()) + updateShortcut( static_cast<TQPopupMenu*>(w), itemId_ ); + } + else if ( ::tqqt_cast<TQMenuBar *>( w ) ) + static_cast<TQMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() ); + else if ( ::tqqt_cast<TDEToolBar *>( w ) ) + static_cast<TDEToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() ); +} + +TQString TDEAction::icon() const +{ + return d->iconName( ); +} + +void TDEAction::setIconSet( const TQIconSet &iconset ) +{ + d->setIconSet( iconset ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateIconSet( i ); +} + + +void TDEAction::updateIconSet( int id ) +{ + TQWidget *w = container( id ); + + if ( ::tqqt_cast<TQPopupMenu *>( w ) ) + { + int itemId_ = itemId( id ); + static_cast<TQPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() ); + if (!d->m_cut.isNull()) + updateShortcut( static_cast<TQPopupMenu*>(w), itemId_ ); + } + else if ( ::tqqt_cast<TQMenuBar *>( w ) ) + static_cast<TQMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() ); + else if ( ::tqqt_cast<TDEToolBar *>( w ) ) + { + if ( icon().isEmpty() && d->hasIcon() ) // only if there is no named icon ( scales better ) + static_cast<TDEToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet() ); + else + static_cast<TDEToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet( KIcon::Small ) ); + } +} + +TQIconSet TDEAction::iconSet( KIcon::Group group, int size ) const +{ + return d->iconSet( group, size ); +} + +bool TDEAction::hasIcon() const +{ + return d->hasIcon(); +} + +void TDEAction::setWhatsThis( const TQString& text ) +{ + d->setWhatsThis( text ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateWhatsThis( i ); +} + +void TDEAction::updateWhatsThis( int i ) +{ + TQPopupMenu* pm = popupMenu( i ); + if ( pm ) + { + pm->TQMenuData::setWhatsThis( itemId( i ), d->whatsThis() ); + return; + } + + TDEToolBar *tb = toolBar( i ); + if ( tb ) + { + TQWidget *w = tb->getButton( itemId( i ) ); + TQWhatsThis::remove( w ); + TQWhatsThis::add( w, d->whatsThis() ); + return; + } +} + +TQString TDEAction::whatsThis() const +{ + return d->whatsThis(); +} + +TQString TDEAction::whatsThisWithIcon() const +{ + TQString text = whatsThis(); + if (!d->iconName().isEmpty()) + return TQString::fromLatin1("<img source=\"small|%1\"> %2").arg(d->iconName() ).arg(text); + return text; +} + +TQWidget* TDEAction::container( int index ) const +{ + assert( index < containerCount() ); + return d->m_containers[ index ].m_container; +} + +TDEToolBar* TDEAction::toolBar( int index ) const +{ + return tqt_dynamic_cast<TDEToolBar *>( d->m_containers[ index ].m_container ); +} + +TQPopupMenu* TDEAction::popupMenu( int index ) const +{ + return tqt_dynamic_cast<TQPopupMenu *>( d->m_containers[ index ].m_container ); +} + +TQWidget* TDEAction::representative( int index ) const +{ + return d->m_containers[ index ].m_representative; +} + +int TDEAction::itemId( int index ) const +{ + return d->m_containers[ index ].m_id; +} + +int TDEAction::containerCount() const +{ + return d->m_containers.count(); +} + +uint TDEAction::kaccelCount() const +{ + return d->m_kaccelList.count(); +} + +void TDEAction::addContainer( TQWidget* c, int id ) +{ + TDEActionPrivate::Container p; + p.m_container = c; + p.m_id = id; + d->m_containers.append( p ); +} + +void TDEAction::addContainer( TQWidget* c, TQWidget* w ) +{ + TDEActionPrivate::Container p; + p.m_container = c; + p.m_representative = w; + d->m_containers.append( p ); +} + +void TDEAction::activate() +{ + emit activated( TDEAction::EmulatedActivation, Qt::NoButton ); + slotActivated(); +} + +void TDEAction::slotActivated() +{ + const TQObject *senderObj = TQT_TQOBJECT_CONST(sender()); + if ( senderObj ) + { + if ( ::tqqt_cast<TDEAccelPrivate *>( senderObj ) ) + emit activated( TDEAction::AccelActivation, Qt::NoButton ); + } + emit activated(); +} + +// This catches signals emitted by TDEActions inserted into QPopupMenu +// We do crude things inside it, because we need to know which +// TQPopupMenu emitted the signal. We need to be sure that it is +// only called by QPopupMenus, we plugged us in. +void TDEAction::slotPopupActivated() +{ + if( ::tqqt_cast<TQSignal *>(sender())) + { + int id = tqt_dynamic_cast<const TQSignal *>(sender())->value().toInt(); + int pos = findContainer(id); + if(pos != -1) + { + TQPopupMenu* qpm = tqt_dynamic_cast<TQPopupMenu *>( container(pos) ); + if(qpm) + { + TDEPopupMenu* kpm = tqt_dynamic_cast<TDEPopupMenu *>( qpm ); + TQt::ButtonState state; + if ( kpm ) // TDEPopupMenu? Nice, it stores the state. + state = kpm->state(); + else { // just a QPopupMenu? We'll ask for the state now then (small race condition?) + kdDebug(129) << "TDEAction::slotPopupActivated not a TDEPopupMenu -> using keyboardMouseState()" << endl; + state = TDEApplication::keyboardMouseState(); + } + emit activated( TDEAction::PopupMenuActivation, state ); + slotActivated(); + return; + } + } + } + + kdWarning(129)<<"Don't connect TDEAction::slotPopupActivated() to anything, expect into QPopupMenus which are in containers. Use slotActivated instead."<<endl; + emit activated( TDEAction::PopupMenuActivation, Qt::NoButton ); + slotActivated(); +} + +void TDEAction::slotButtonClicked( int, TQt::ButtonState state ) +{ + kdDebug(129) << "slotButtonClicked() state=" << state << endl; + emit activated( TDEAction::ToolBarActivation, state ); + + // RightButton isn't really an activation + if ( ( state & Qt::LeftButton ) || ( state & Qt::MidButton ) ) + slotActivated(); +} + + +void TDEAction::slotDestroyed() +{ + kdDebug(129) << "TDEAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl; + const TQObject* const o = TQT_TQOBJECT_CONST(sender()); + +#ifndef KDE_NO_COMPAT // KDE 4: remove + if ( o == d->m_kaccel ) + { + d->m_kaccel = 0; + return; + } +#endif // KDE 4: remove end + TQValueList<TDEAccel*> & accelList = d->m_kaccelList; + TQValueList<TDEAccel*>::iterator itr = accelList.begin(); + const TQValueList<TDEAccel*>::iterator itrEnd = accelList.end(); + + for( ; itr != itrEnd; ++itr) + { + if ( o == *itr ) + { + disconnect( *itr, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotDestroyed()) ); + accelList.remove(itr); + return; + } + } + + int i; + do + { + i = findContainer( TQT_TQWIDGET_CONST( static_cast<const QObject*>(o) ) ); + if ( i != -1 ) + removeContainer( i ); + } while ( i != -1 ); +} + +int TDEAction::findContainer( const TQWidget* widget ) const +{ + int pos = 0; + + const TQValueList<TDEActionPrivate::Container> & containers = d->m_containers; + + TQValueList<TDEActionPrivate::Container>::ConstIterator it = containers.constBegin(); + const TQValueList<TDEActionPrivate::Container>::ConstIterator itEnd = containers.constEnd(); + + while( it != itEnd ) + { + if ( (*it).m_representative == widget || (*it).m_container == widget ) + return pos; + ++it; + ++pos; + } + + return -1; +} + +int TDEAction::findContainer( const int id ) const +{ + int pos = 0; + + const TQValueList<TDEActionPrivate::Container> & containers = d->m_containers; + + TQValueList<TDEActionPrivate::Container>::ConstIterator it = containers.constBegin(); + const TQValueList<TDEActionPrivate::Container>::ConstIterator itEnd = containers.constEnd(); + + while( it != itEnd ) + { + if ( (*it).m_id == id ) + return pos; + ++it; + ++pos; + } + + return -1; +} + +void TDEAction::removeContainer( int index ) +{ + int i = 0; + + TQValueList<TDEActionPrivate::Container> & containers = d->m_containers; + + TQValueList<TDEActionPrivate::Container>::Iterator it = containers.begin(); + const TQValueList<TDEActionPrivate::Container>::Iterator itEnd = containers.end(); + + while( it != itEnd ) + { + if ( i == index ) + { + containers.remove( it ); + return; + } + ++it; + ++i; + } +} + +// FIXME: Remove this (ellis) +void TDEAction::slotKeycodeChanged() +{ + kdDebug(129) << "TDEAction::slotKeycodeChanged()" << endl; // -- ellis + TDEAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if( pAction ) + setShortcut(pAction->shortcut()); +} + +TDEActionCollection *TDEAction::parentCollection() const +{ + return m_parentCollection; +} + +void TDEAction::unplugAll() +{ + while ( containerCount() != 0 ) + unplug( container( 0 ) ); +} + +const KGuiItem& TDEAction::guiItem() const +{ + return *d; +} + +void TDEAction::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +#include "kaction.moc" |