kaction.cpp
/* 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 <qtooltip.h>
#include <qwhatsthis.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>
int KAction::getToolButtonID()
{
static int toolbutton_no = -2;
return toolbutton_no--;
}
//---------------------------------------------------------------------
// KAction::KActionPrivate
//---------------------------------------------------------------------
class KAction::KActionPrivate : public KGuiItem
{
public:
KActionPrivate() : KGuiItem()
{
m_kaccel = 0;
m_configurable = true;
}
KAccel *m_kaccel;
QValueList<KAccel*> m_kaccelList;
QString m_groupText;
QString m_group;
KShortcut m_cut;
KShortcut 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; }
QWidget* m_container;
int m_id;
QWidget* m_representative;
};
QValueList<Container> m_containers;
};
//---------------------------------------------------------------------
// KAction
//---------------------------------------------------------------------
KAction::KAction( const QString& text, const KShortcut& cut,
const QObject* receiver, const char* slot,
KActionCollection* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, receiver, slot );
}
KAction::KAction( const QString& text, const QString& sIconName, const KShortcut& cut,
const QObject* receiver, const char* slot,
KActionCollection* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, receiver, slot );
d->setIconName( sIconName );
}
KAction::KAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
const QObject* receiver, const char* slot,
KActionCollection* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, receiver, slot );
d->setIconSet( pix );
}
KAction::KAction( const KGuiItem& item, const KShortcut& cut,
const QObject* receiver, const char* slot,
KActionCollection* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
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
KAction::KAction( const QString& text, const KShortcut& cut,
QObject* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, 0, 0 );
}
KAction::KAction( const QString& text, const KShortcut& cut,
const QObject* receiver,
const char* slot, QObject* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, receiver, slot );
}
KAction::KAction( const QString& text, const QIconSet& pix,
const KShortcut& cut,
QObject* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, 0, 0 );
setIconSet( pix );
}
KAction::KAction( const QString& text, const QString& pix,
const KShortcut& cut,
QObject* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, 0, 0 );
d->setIconName( pix );
}
KAction::KAction( const QString& text, const QIconSet& pix,
const KShortcut& cut,
const QObject* receiver, const char* slot, QObject* parent,
const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, receiver, slot );
setIconSet( pix );
}
KAction::KAction( const QString& text, const QString& pix,
const KShortcut& cut,
const QObject* receiver, const char* slot, QObject* parent,
const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( text, cut, receiver, slot );
d->setIconName(pix);
}
KAction::KAction( QObject* parent, const char* name )
: QObject( parent, name ), d(new KActionPrivate)
{
initPrivate( QString::null, KShortcut(), 0, 0 );
}
#endif // KDE 4: remove end
KAction::~KAction()
{
kdDebug(129) << "KAction::~KAction( 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 QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
const QValueList<KAccel*>::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.
// KAction 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 KAction::initPrivate( const QString& text, const KShortcut& cut,
const QObject* receiver, const char* slot )
{
d->m_cutDefault = cut;
m_parentCollection = dynamic_cast<KActionCollection *>( parent() );
kdDebug(129) << "KAction::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, SIGNAL( activated() ), receiver, slot );
if( !cut.isNull() && !qstrcmp( name(), "unnamed" ) )
kdWarning(129) << "KAction::initPrivate(): trying to assign a shortcut (" << cut.toStringInternal() << ") to an unnamed action." << endl;
d->setText( text );
initShortcut( cut );
}
bool KAction::isPlugged() const
{
return (!d->m_containers.empty()) || d->m_kaccel;
}
bool KAction::isPlugged( const QWidget *container ) const
{
return findContainer( container ) > -1;
}
bool KAction::isPlugged( const QWidget *container, int id ) const
{
int i = findContainer( container );
return ( i > -1 && itemId( i ) == id );
}
bool KAction::isPlugged( const QWidget *container, const QWidget *_representative ) const
{
int i = findContainer( container );
return ( i > -1 && representative( i ) == _representative );
}
/*
Three actionCollection conditions:
1) Scope is known on creation and KAccel object is created (e.g. KMainWindow)
2) Scope is unknown and no KAccel 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 KAccel 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 KMainWindow)
A KAccel object is created in the parentCollection
A KAction 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 KAction 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 KAccel
shortcuts are set in all other KAccels, if the action is present in the other KAccels
*/
/*
shortcut may be set:
- on construction
- on plug
- on reading XML
- on plugAccel (deprecated)
On Construction: [via initShortcut()]
insert into KAccel of m_parentCollection,
if kaccel() && isAutoConnectShortcuts() exists
On Plug: [via plug() -> plugShortcut()]
insert into KAccel of m_parentCollection, if exists and not already inserted into
On Read XML: [via setShortcut()]
set in all current KAccels
insert into KAccel of m_parentCollection, if exists and not already inserted into
*/
KAccel* KAction::kaccelCurrent()
{
if( m_parentCollection && m_parentCollection->builderKAccel() )
return m_parentCollection->builderKAccel();
else if( m_parentCollection && m_parentCollection->kaccel() )
return m_parentCollection->kaccel();
else
return 0L;
}
// Only to be called from initPrivate()
bool KAction::initShortcut( const KShortcut& cut )
{
d->m_cut = cut;
// Only insert action into KAccel if it has a valid name,
if( qstrcmp( name(), "unnamed" ) &&
m_parentCollection &&
m_parentCollection->isAutoConnectShortcuts() &&
m_parentCollection->kaccel() )
{
insertKAccel( m_parentCollection->kaccel() );
return true;
}
return false;
}
// Only to be called from plug()
void KAction::plugShortcut()
{
KAccel* const kaccel = kaccelCurrent();
//kdDebug(129) << "KAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl;
if( kaccel && qstrcmp( name(), "unnamed" ) ) {
// Check if already plugged into current KAccel object
const QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
for( ; itr != itrEnd; ++itr) {
if( (*itr) == kaccel )
return;
}
insertKAccel( kaccel );
}
}
bool KAction::setShortcut( const KShortcut& cut )
{
bool bChanged = (d->m_cut != cut);
d->m_cut = cut;
KAccel* const kaccel = kaccelCurrent();
bool bInsertRequired = true;
// Apply new shortcut to all existing KAccel objects
const QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
const QValueList<KAccel*>::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 )
updateKAccelShortcut( *itr );
}
// Only insert action into KAccel if it has a valid name,
if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) )
insertKAccel( 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 KAction::updateKAccelShortcut( KAccel* kaccel )
{
// Check if action is permitted
if (kapp && !kapp->authorizeKAction(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(), QString::null,
d->m_cut,
this, SLOT(slotActivated()),
isShortcutConfigurable(), isEnabled() );
}
}
else
b = kaccel->setShortcut( name(), d->m_cut );
return b;
}
void KAction::insertKAccel( KAccel* kaccel )
{
//kdDebug(129) << "KAction::insertKAccel( " << kaccel << " ): this = " << this << endl;
if ( !kaccel->actions().actionPtr( name() ) ) {
if( updateKAccelShortcut( kaccel ) ) {
d->m_kaccelList.append( kaccel );
connect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
}
}
else
kdWarning(129) << "KAction::insertKAccel( kaccel = " << kaccel << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis
}
void KAction::removeKAccel( KAccel* kaccel )
{
//kdDebug(129) << "KAction::removeKAccel( " << i << " ): this = " << this << endl;
QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::iterator itr = accelList.begin();
const QValueList<KAccel*>::iterator itrEnd = accelList.end();
for( ; itr != itrEnd; ++itr) {
if( (*itr) == kaccel ) {
kaccel->remove( name() );
accelList.remove( itr );
disconnect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
break;
}
}
}
#ifndef KDE_NO_COMPAT
// KDE 4: remove
void KAction::setAccel( int keyQt )
{
setShortcut( KShortcut(keyQt) );
}
#endif // KDE 4: remove end
void KAction::updateShortcut( int i )
{
int id = itemId( i );
QWidget* w = container( i );
if ( ::qt_cast<QPopupMenu *>( w ) ) {
QPopupMenu* menu = static_cast<QPopupMenu*>(w);
updateShortcut( menu, id );
}
else if ( ::qt_cast<QMenuBar *>( w ) )
static_cast<QMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id );
}
void KAction::updateShortcut( QPopupMenu* menu, int id )
{
//kdDebug(129) << "KAction::updateShortcut(): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl;
// If the action has a KAccel object,
// show the string representation of its shortcut.
if ( d->m_kaccel || d->m_kaccelList.count() ) {
QString 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 KAction is missing a proper parent collection.
// It should be removed eventually. --ellis
menu->setAccel( d->m_cut.keyCodeQt(), id );
kdDebug(129) << "KAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No KAccel, probably missing a parent collection." << endl;
}
}
const KShortcut& KAction::shortcut() const
{
return d->m_cut;
}
const KShortcut& KAction::shortcutDefault() const
{
return d->m_cutDefault;
}
QString KAction::shortcutText() const
{
return d->m_cut.toStringInternal();
}
void KAction::setShortcutText( const QString& s )
{
setShortcut( KShortcut(s) );
}
#ifndef KDE_NO_COMPAT // Remove in KDE 4
int KAction::accel() const
{
return d->m_cut.keyCodeQt();
}
#endif
void KAction::setGroup( const QString& grp )
{
d->m_group = grp;
int len = containerCount();
for( int i = 0; i < len; ++i )
updateGroup( i );
}
void KAction::updateGroup( int )
{
// DO SOMETHING
}
QString KAction::group() const
{
return d->m_group;
}
bool KAction::isEnabled() const
{
return d->isEnabled();
}
bool KAction::isShortcutConfigurable() const
{
return d->m_configurable;
}
void KAction::setToolTip( const QString& tt )
{
d->setToolTip( tt );
int len = containerCount();
for( int i = 0; i < len; ++i )
updateToolTip( i );
}
void KAction::updateToolTip( int i )
{
QWidget *w = container( i );
if ( ::qt_cast<KToolBar *>( w ) )
QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() );
}
QString KAction::toolTip() const
{
return d->toolTip();
}
int KAction::plug( QWidget *w, int index )
{
//kdDebug(129) << "KAction::plug( " << w << ", " << index << " )" << endl;
if (!w ) {
kdWarning(129) << "KAction::plug called with 0 argument\n";
return -1;
}
// Ellis: print warning if there is a shortcut, but no KAccel 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 QAccel.
// We should probably re-enable the warning for things that only KAccel can do, though - e.g. WIN key (mapped to Meta).
#if 0 //ndef NDEBUG
KAccel* kaccel = kaccelCurrent();
if( !d->m_cut.isNull() && !kaccel ) {
kdDebug(129) << "KAction::plug(): has no KAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis
}
#endif
// Check if action is permitted
if (kapp && !kapp->authorizeKAction(name()))
return -1;
plugShortcut();
if ( ::qt_cast<QPopupMenu *>( w ) )
{
QPopupMenu* menu = static_cast<QPopupMenu*>( w );
int id;
// Don't insert shortcut into menu if it's already in a KAccel object.
int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt();
if ( d->hasIcon() )
{
KInstance *instance;
if ( m_parentCollection )
instance = m_parentCollection->instance();
else
instance = KGlobal::instance();
id = menu->insertItem( d->iconSet( KIcon::Small, 0, instance ), d->text(), this,//dsweet
SLOT( slotPopupActivated() ), keyQt,
-1, index );
}
else
id = menu->insertItem( d->text(), this,
SLOT( slotPopupActivated() ),
keyQt, -1, index );
// If the shortcut is already in a KAccel 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->setWhatsThis( id, whatsThisWithIcon() );
addContainer( menu, id );
connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
if ( m_parentCollection )
m_parentCollection->connectHighlight( menu, this );
return d->m_containers.count() - 1;
}
else if ( ::qt_cast<KToolBar *>( w ) )
{
KToolBar *bar = static_cast<KToolBar *>( w );
int id_ = getToolButtonID();
KInstance *instance;
if ( m_parentCollection )
instance = m_parentCollection->instance();
else
instance = KGlobal::instance();
if ( icon().isEmpty() && !iconSet().pixmap().isNull() ) // old code using QIconSet directly
{
bar->insertButton( iconSet().pixmap(), id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
SLOT( slotButtonClicked(int, Qt::ButtonState) ),
d->isEnabled(), d->plainText(), index );
}
else
{
QString icon = d->iconName();
if ( icon.isEmpty() )
icon = "unknown";
bar->insertButton( icon, id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
SLOT( slotButtonClicked(int, Qt::ButtonState) ),
d->isEnabled(), d->plainText(), index, instance );
}
KToolBarButton* ktb = bar->getButton(id_);
ktb->setName( QCString("toolbutton_")+name() );
if ( !d->whatsThis().isEmpty() )
QWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() );
if ( !d->toolTip().isEmpty() )
QToolTip::add( bar->getButton(id_), d->toolTip() );
addContainer( bar, id_ );
connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
if ( m_parentCollection )
m_parentCollection->connectHighlight( bar, this );
return containerCount() - 1;
}
return -1;
}
void KAction::unplug( QWidget *w )
{
int i = findContainer( w );
if ( i == -1 )
return;
int id = itemId( i );
if ( ::qt_cast<QPopupMenu *>( w ) )
{
QPopupMenu *menu = static_cast<QPopupMenu *>( w );
menu->removeItem( id );
}
else if ( ::qt_cast<KToolBar *>( w ) )
{
KToolBar *bar = static_cast<KToolBar *>( w );
bar->removeItemDelayed( id );
}
else if ( ::qt_cast<QMenuBar *>( w ) )
{
QMenuBar *bar = static_cast<QMenuBar *>( w );
bar->removeItem( id );
}
removeContainer( i );
if ( m_parentCollection )
m_parentCollection->disconnectHighlight( w, this );
}
void KAction::plugAccel(KAccel *kacc, bool configurable)
{
kdWarning(129) << "KAction::plugAccel(): call to deprecated action." << endl;
kdDebug(129) << kdBacktrace() << endl;
//kdDebug(129) << "KAction::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 KAccel 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(), QString::null,
KShortcut(d->m_cut),
this, SLOT(slotActivated()),
configurable, isEnabled());
connect(d->m_kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()));
//connect(d->m_kaccel, SIGNAL(keycodeChanged()), this, SLOT(slotKeycodeChanged()));
}
else
kdWarning(129) << "KAction::plugAccel( kacc = " << kacc << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis
}
void KAction::unplugAccel()
{
//kdDebug(129) << "KAction::unplugAccel() " << this << " " << name() << endl;
if ( d->m_kaccel )
{
d->m_kaccel->remove(name());
d->m_kaccel = 0;
}
}
void KAction::plugMainWindowAccel( QWidget *w )
{
// Note: topLevelWidget() stops too early, we can't use it.
QWidget * tl = w;
QWidget * n;
while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store
tl = n;
KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow
if (mw)
plugAccel( mw->accel() );
else
kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl;
}
void KAction::setEnabled(bool enable)
{
//kdDebug(129) << "KAction::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 QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
const QValueList<KAccel*>::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 KAction::updateEnabled( int i )
{
QWidget *w = container( i );
if ( ::qt_cast<QPopupMenu *>( w ) )
static_cast<QPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
else if ( ::qt_cast<QMenuBar *>( w ) )
static_cast<QMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
else if ( ::qt_cast<KToolBar *>( w ) )
static_cast<KToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
}
void KAction::setShortcutConfigurable( bool b )
{
d->m_configurable = b;
}
void KAction::setText( const QString& text )
{
#ifndef KDE_NO_COMPAT
// KDE 4: remove
if (d->m_kaccel) {
KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name());
if (pAction)
pAction->setLabel( text );
}
#endif // KDE 4: remove end
const QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
const char * const namePtr = name();
for( ; itr != itrEnd; ++itr ) {
KAccelAction* 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 KAction::updateText( int i )
{
QWidget *w = container( i );
if ( ::qt_cast<QPopupMenu *>( w ) ) {
int id = itemId( i );
static_cast<QPopupMenu*>(w)->changeItem( id, d->text() );
if (!d->m_cut.isNull())
updateShortcut( static_cast<QPopupMenu*>(w), id );
}
else if ( ::qt_cast<QMenuBar *>( w ) )
static_cast<QMenuBar*>(w)->changeItem( itemId( i ), d->text() );
else if ( ::qt_cast<KToolBar *>( w ) )
{
QWidget *button = static_cast<KToolBar *>(w)->getWidget( itemId( i ) );
if ( ::qt_cast<KToolBarButton *>( button ) )
static_cast<KToolBarButton *>(button)->setText( d->plainText() );
}
}
QString KAction::text() const
{
return d->text();
}
QString KAction::plainText() const
{
return d->plainText( );
}
void KAction::setIcon( const QString &icon )
{
d->setIconName( icon );
// now handle any toolbars
int len = containerCount();
for ( int i = 0; i < len; ++i )
updateIcon( i );
}
void KAction::updateIcon( int id )
{
QWidget* w = container( id );
if ( ::qt_cast<QPopupMenu *>( w ) ) {
int itemId_ = itemId( id );
static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() );
if (!d->m_cut.isNull())
updateShortcut( static_cast<QPopupMenu*>(w), itemId_ );
}
else if ( ::qt_cast<QMenuBar *>( w ) )
static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() );
else if ( ::qt_cast<KToolBar *>( w ) )
static_cast<KToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() );
}
QString KAction::icon() const
{
return d->iconName( );
}
void KAction::setIconSet( const QIconSet &iconset )
{
d->setIconSet( iconset );
int len = containerCount();
for( int i = 0; i < len; ++i )
updateIconSet( i );
}
void KAction::updateIconSet( int id )
{
QWidget *w = container( id );
if ( ::qt_cast<QPopupMenu *>( w ) )
{
int itemId_ = itemId( id );
static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() );
if (!d->m_cut.isNull())
updateShortcut( static_cast<QPopupMenu*>(w), itemId_ );
}
else if ( ::qt_cast<QMenuBar *>( w ) )
static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() );
else if ( ::qt_cast<KToolBar *>( w ) )
{
if ( icon().isEmpty() && d->hasIcon() ) // only if there is no named icon ( scales better )
static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet() );
else
static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet( KIcon::Small ) );
}
}
QIconSet KAction::iconSet( KIcon::Group group, int size ) const
{
return d->iconSet( group, size );
}
bool KAction::hasIcon() const
{
return d->hasIcon();
}
void KAction::setWhatsThis( const QString& text )
{
d->setWhatsThis( text );
int len = containerCount();
for( int i = 0; i < len; ++i )
updateWhatsThis( i );
}
void KAction::updateWhatsThis( int i )
{
QPopupMenu* pm = popupMenu( i );
if ( pm )
{
pm->setWhatsThis( itemId( i ), d->whatsThis() );
return;
}
KToolBar *tb = toolBar( i );
if ( tb )
{
QWidget *w = tb->getButton( itemId( i ) );
QWhatsThis::remove( w );
QWhatsThis::add( w, d->whatsThis() );
return;
}
}
QString KAction::whatsThis() const
{
return d->whatsThis();
}
QString KAction::whatsThisWithIcon() const
{
QString text = whatsThis();
if (!d->iconName().isEmpty())
return QString::fromLatin1("<img source=\"small|%1\"> %2").arg(d->iconName() ).arg(text);
return text;
}
QWidget* KAction::container( int index ) const
{
assert( index < containerCount() );
return d->m_containers[ index ].m_container;
}
KToolBar* KAction::toolBar( int index ) const
{
return dynamic_cast<KToolBar *>( d->m_containers[ index ].m_container );
}
QPopupMenu* KAction::popupMenu( int index ) const
{
return dynamic_cast<QPopupMenu *>( d->m_containers[ index ].m_container );
}
QWidget* KAction::representative( int index ) const
{
return d->m_containers[ index ].m_representative;
}
int KAction::itemId( int index ) const
{
return d->m_containers[ index ].m_id;
}
int KAction::containerCount() const
{
return d->m_containers.count();
}
uint KAction::kaccelCount() const
{
return d->m_kaccelList.count();
}
void KAction::addContainer( QWidget* c, int id )
{
KActionPrivate::Container p;
p.m_container = c;
p.m_id = id;
d->m_containers.append( p );
}
void KAction::addContainer( QWidget* c, QWidget* w )
{
KActionPrivate::Container p;
p.m_container = c;
p.m_representative = w;
d->m_containers.append( p );
}
void KAction::activate()
{
emit activated( KAction::EmulatedActivation, Qt::NoButton );
slotActivated();
}
void KAction::slotActivated()
{
const QObject *senderObj = sender();
if ( senderObj )
{
if ( ::qt_cast<KAccelPrivate *>( senderObj ) )
emit activated( KAction::AccelActivation, Qt::NoButton );
}
emit activated();
}
// This catches signals emitted by KActions inserted into QPopupMenu
// We do crude things inside it, because we need to know which
// QPopupMenu emitted the signal. We need to be sure that it is
// only called by QPopupMenus, we plugged us in.
void KAction::slotPopupActivated()
{
if( ::qt_cast<QSignal *>(sender()))
{
int id = dynamic_cast<const QSignal *>(sender())->value().toInt();
int pos = findContainer(id);
if(pos != -1)
{
QPopupMenu* qpm = dynamic_cast<QPopupMenu *>( container(pos) );
if(qpm)
{
KPopupMenu* kpm = dynamic_cast<KPopupMenu *>( qpm );
Qt::ButtonState state;
if ( kpm ) // KPopupMenu? 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) << "KAction::slotPopupActivated not a KPopupMenu -> using keyboardMouseState()" << endl;
state = KApplication::keyboardMouseState();
}
emit activated( KAction::PopupMenuActivation, state );
slotActivated();
return;
}
}
}
kdWarning(129)<<"Don't connect KAction::slotPopupActivated() to anything, expect into QPopupMenus which are in containers. Use slotActivated instead."<<endl;
emit activated( KAction::PopupMenuActivation, Qt::NoButton );
slotActivated();
}
void KAction::slotButtonClicked( int, Qt::ButtonState state )
{
kdDebug(129) << "slotButtonClicked() state=" << state << endl;
emit activated( KAction::ToolBarActivation, state );
// RightButton isn't really an activation
if ( ( state & LeftButton ) || ( state & MidButton ) )
slotActivated();
}
void KAction::slotDestroyed()
{
kdDebug(129) << "KAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl;
const QObject* const o = sender();
#ifndef KDE_NO_COMPAT // KDE 4: remove
if ( o == d->m_kaccel )
{
d->m_kaccel = 0;
return;
}
#endif // KDE 4: remove end
QValueList<KAccel*> & accelList = d->m_kaccelList;
QValueList<KAccel*>::iterator itr = accelList.begin();
const QValueList<KAccel*>::iterator itrEnd = accelList.end();
for( ; itr != itrEnd; ++itr)
{
if ( o == *itr )
{
disconnect( *itr, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
accelList.remove(itr);
return;
}
}
int i;
do
{
i = findContainer( static_cast<const QWidget*>( o ) );
if ( i != -1 )
removeContainer( i );
} while ( i != -1 );
}
int KAction::findContainer( const QWidget* widget ) const
{
int pos = 0;
const QValueList<KActionPrivate::Container> & containers = d->m_containers;
QValueList<KActionPrivate::Container>::ConstIterator it = containers.constBegin();
const QValueList<KActionPrivate::Container>::ConstIterator itEnd = containers.constEnd();
while( it != itEnd )
{
if ( (*it).m_representative == widget || (*it).m_container == widget )
return pos;
++it;
++pos;
}
return -1;
}
int KAction::findContainer( const int id ) const
{
int pos = 0;
const QValueList<KActionPrivate::Container> & containers = d->m_containers;
QValueList<KActionPrivate::Container>::ConstIterator it = containers.constBegin();
const QValueList<KActionPrivate::Container>::ConstIterator itEnd = containers.constEnd();
while( it != itEnd )
{
if ( (*it).m_id == id )
return pos;
++it;
++pos;
}
return -1;
}
void KAction::removeContainer( int index )
{
int i = 0;
QValueList<KActionPrivate::Container> & containers = d->m_containers;
QValueList<KActionPrivate::Container>::Iterator it = containers.begin();
const QValueList<KActionPrivate::Container>::Iterator itEnd = containers.end();
while( it != itEnd )
{
if ( i == index )
{
containers.remove( it );
return;
}
++it;
++i;
}
}
// FIXME: Remove this (ellis)
void KAction::slotKeycodeChanged()
{
kdDebug(129) << "KAction::slotKeycodeChanged()" << endl; // -- ellis
KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name());
if( pAction )
setShortcut(pAction->shortcut());
}
KActionCollection *KAction::parentCollection() const
{
return m_parentCollection;
}
void KAction::unplugAll()
{
while ( containerCount() != 0 )
unplug( container( 0 ) );
}
const KGuiItem& KAction::guiItem() const
{
return *d;
}
void KAction::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
/* vim: et sw=2 ts=2
*/
#include "kaction.moc"
KAction::setShortcutConfigurable
virtual void setShortcutConfigurable(bool)
Indicate whether the user may configure the action's shortcut.
Definition: kaction.cpp:858
KToolBar::setText
void setText(const QString &txt)
Assign a (translated) text to this toolbar.
Definition: ktoolbar.cpp:1133
KActionCollection
A managed set of KAction objects.
Definition: kactioncollection.h:78
KAccel
KAction::setAccel
void setAccel(int key) KDE_DEPRECATED
Definition: kaction.cpp:497
KToolBar::insertButton
int insertButton(const QString &icon, int id, bool enabled=true, const QString &text=QString::null, int index=-1, KInstance *_instance=KGlobal::instance())
Insert a button (a KToolBarButton) with a pixmap.
Definition: ktoolbar.cpp:257
KAction::accel
int accel() const KDE_DEPRECATED
Definition: kaction.cpp:561
KGuiItem::hasIcon
bool hasIcon() const
returns whether an icon is defined, doesn't tell if it really exists
Definition: kguiitem.cpp:190
KAction::slotPopupActivated
void slotPopupActivated()
Definition: kaction.cpp:1109
KAction::setShortcut
virtual bool setShortcut(const KShortcut &)
Sets the keyboard shortcut associated with this action.
Definition: kaction.cpp:404
KApplication::keyboardMouseState
static ButtonState keyboardMouseState()
KToolBar::getButton
KToolBarButton * getButton(int id)
Returns a pointer to KToolBarButton.
Definition: ktoolbar.cpp:629
KIcon::Small
KIcon::Group
Group
KActionCollection::disconnectHighlight
void disconnectHighlight(QWidget *container, KAction *action)
Disconnect highlight notifications for a particular pair of contianer and action. ...
Definition: kactioncollection.cpp:526
KActionCollection::connectHighlight
void connectHighlight(QWidget *container, KAction *action)
Call this function if you want to receive a signal whenever a KAction is highlighted in a menu or a t...
Definition: kactioncollection.cpp:493
KAction::unplug
virtual void unplug(QWidget *w)
"Unplug" or remove this action from a given widget.
Definition: kaction.cpp:735
kdDebug
kdbgstream kdDebug(int area=0)
KToolBar::removeItemDelayed
void removeItemDelayed(int id)
Remove item id.
Definition: ktoolbar.cpp:694
KActionCollection::isAutoConnectShortcuts
bool isAutoConnectShortcuts()
This indicates whether new actions which are created in this collection have their keyboard shortcuts...
Definition: kactioncollection.cpp:172
KActionCollection::kaccel
KAccel * kaccel()
Returns the KAccel object of the most recently set widget.
Definition: kactioncollection.cpp:282
KAction::kaccelCount
uint kaccelCount() const
Definition: kaction.cpp:1067
KToolBarButton
A toolbar button.
Definition: ktoolbarbutton.h:44
KShortcut
KAccel::insert
KAccelAction * insert(const QString &sAction, const QString &sLabel, const QString &sWhatsThis, const KShortcut &cutDef, const QObject *pObjSlot, const char *psMethodSlot, bool bConfigurable=true, bool bEnabled=true)
KAction::unplugAccel
virtual void unplugAccel() KDE_DEPRECATED
Definition: kaction.cpp:791
KAction::isPlugged
virtual bool isPlugged() const
returns whether the action is plugged into any container widget or not.
Definition: kaction.cpp:263
KAction::guiItem
const KGuiItem & guiItem() const
Return the underlying KGuiItem.
Definition: kaction.cpp:1267
KMainWindow
KDE top level main window
Definition: kmainwindow.h:98
KActionCollection::instance
KInstance * instance() const
The instance with which this class is associated.
Definition: kactioncollection.cpp:468
KGuiItem
An abstract class for GUI data such as ToolTip and Icon.
Definition: kguiitem.h:38
KAction::plugAccel
virtual void plugAccel(KAccel *accel, bool configurable=true) KDE_DEPRECATED
Definition: kaction.cpp:763
KAction::activate
virtual void activate()
Emulate user's interaction programmatically, by activating the action.
Definition: kaction.cpp:1088
kdWarning
kdbgstream kdWarning(int area=0)
KAction::getToolButtonID
static int getToolButtonID()
How it works.
Definition: kaction.cpp:66
KAction::setToolTip
virtual void setToolTip(const QString &)
Sets the tooltip text for the action.
Definition: kaction.cpp:596
KActionCollection::builderKAccel
KAccel * builderKAccel() const
Definition: kactioncollection.cpp:371
KInstance
KAction::iconSet
QIconSet iconSet() const
Remove in KDE4.
Definition: kaction.h:476
KAction::setText
virtual void setText(const QString &text)
Sets the text associated with this action.
Definition: kaction.cpp:863
KAction::shortcut
virtual const KShortcut & shortcut() const
Get the keyboard shortcut associated with this action.
KAccel::remove
bool remove(const QString &sAction)
KGlobal::instance
static KInstance * instance()
KAction::whatsThis
virtual QString whatsThis() const
Get the What's this text for the action.
KMainWindow::accel
KAccel * accel()
Definition: kmainwindow.cpp:1171
KAction::KAction
KAction(const QString &text, const KShortcut &cut, const QObject *receiver, const char *slot, KActionCollection *parent, const char *name)
Constructs an action with text, potential keyboard shortcut, and a SLOT to call when this action is i...
Definition: kaction.cpp:113
KAction::setIconSet
virtual void setIconSet(const QIconSet &iconSet)
Sets the QIconSet from which the icons used to display this action will be chosen.
Definition: kaction.cpp:953
KAction::shortcutDefault
virtual const KShortcut & shortcutDefault() const
Get the default shortcut for this action.
Definition: kaction.cpp:545
KAction::~KAction
virtual ~KAction()
Standard destructor.
Definition: kaction.cpp:212
KToolBar
Floatable toolbar with auto resize.
Definition: ktoolbar.h:103
KAction::text
virtual QString text() const
Get the text associated with this action.
KAction::slotButtonClicked
void slotButtonClicked(int, Qt::ButtonState state)
Definition: kaction.cpp:1140
KAction::toolTip
virtual QString toolTip() const
Get the tooltip text for the action.
KAction::isShortcutConfigurable
virtual bool isShortcutConfigurable() const
Returns true if this action's shortcut is configurable.
Definition: kaction.cpp:591
KAction::setWhatsThis
virtual void setWhatsThis(const QString &text)
Sets the What's this text for the action.
Definition: kaction.cpp:995
KAction::activated
void activated()
Emitted when this action is activated.
endl
kndbgstream & endl(kndbgstream &s)
KShortcut::isNull
bool isNull() const
KAccel::setShortcut
bool setShortcut(const QString &sAction, const KShortcut &shortcut)
KAction::setEnabled
virtual void setEnabled(bool enable)
Enables or disables this action.
Definition: kaction.cpp:816
KAction::isEnabled
virtual bool isEnabled() const
Returns true if this action is enabled.
Definition: kaction.cpp:586
KActionCollection::insert
void insert(KAction *action)
Add an action to the collection.
Definition: kactioncollection.cpp:365
KAction::plug
virtual int plug(QWidget *widget, int index=-1)
"Plug" or insert this action into a given widget.
Definition: kaction.cpp:618
KActionCollection::take
KAction * take(KAction *action)
Removes an action from the collection.
Definition: kactioncollection.cpp:367
KStdAccel::name
QString name(StdAccel id)
kdBacktrace
QString kdBacktrace()

KDE Home | KDE Accessibility Home | Description of Access Keys