author | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
commit | b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (side-by-side diff) | |
tree | 2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /microkde/kdeui | |
download | kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2 |
Initial revision
38 files changed, 24594 insertions, 0 deletions
diff --git a/microkde/kdeui/kaction.cpp b/microkde/kdeui/kaction.cpp new file mode 100644 index 0000000..77d36a5 --- a/dev/null +++ b/microkde/kdeui/kaction.cpp @@ -0,0 +1,1215 @@ +/* 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kaction.h" + +#include <assert.h> + +#include <qtooltip.h> +//US#include <qwhatsthis.h> +//US#include <kaccel.h> +//US#include <kaccelbase.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kguiitem.h> +//US#include <kmainwindow.h> +//US#include <kmenubar.h> +//US#include <kpopupmenu.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> + +//US added this includefiles +#include <qmenubar.h> +#include <qtoolbar.h> +#include <qpopupmenu.h> +#include <qiconset.h> + +/** +* How it works. +* KActionCollection is an organizing container for KActions. +* KActionCollection 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 QWidget* to the KActionCollection 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 KActionCollection. +* +* XML Filename: +* This is used to save user-modified settings back to the *ui.rc file. +* It is set by KXMLGUIFactory. +*/ + +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 ) +{ + 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 ) +{ + 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 ) +{ + 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 ) +{ + initPrivate( item.text(), cut, receiver, slot ); + if( item.hasIconSet() ) + setIcon( item.iconName() ); + setToolTip( item.toolTip() ); + setWhatsThis( item.whatsThis() ); +} + +// KDE 4: remove +KAction::KAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : QObject( parent, name ) +{ + 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 ) +{ + initPrivate( text, cut, receiver, slot ); +} +KAction::KAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : QObject( parent, name ) +{ + 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 ) +{ + 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 ) +{ + 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 ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName(pix); +} + +KAction::KAction( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + + initPrivate( QString::null, KShortcut(), 0, 0 ); +} +// 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 ); + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) +//US d->m_kaccelList[i]->remove( name() ); + qDebug("KAction::KAction~ ...1 has top be fixed"); + } + + // 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; d = 0; +} + +void KAction::initPrivate( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot ) +{ + d = new KActionPrivate; + + d->m_cutDefault = cut; + +//US m_parentCollection = dynamic_cast<KActionCollection *>( parent() ); + m_parentCollection = (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" ) == 0 ) + 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 (containerCount() > 0) || 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" ) != 0 && + 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* kaccel = kaccelCurrent(); + + //kdDebug(129) << "KAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl; + if( kaccel && qstrcmp( name(), "unnamed" ) != 0 ) { + // Check if already plugged into current KAccel object + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + if( d->m_kaccelList[i] == kaccel ) + return; + } + + insertKAccel( kaccel ); + } +} + +bool KAction::setShortcut( const KShortcut& cut ) +{ + qDebug("KAction::setShortcut~ ...1 has top be fixed"); +/*US + bool bChanged = (d->m_cut != cut); + d->m_cut = cut; + + KAccel* kaccel = kaccelCurrent(); + bool bInsertRequired = true; + // Apply new shortcut to all existing KAccel objects + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + // Check whether shortcut has already been plugged into + // the current kaccel object. + if( d->m_kaccelList[i] == kaccel ) + bInsertRequired = false; + if( bChanged ) + updateKAccelShortcut( d->m_kaccelList[i] ); + } + + // Only insert action into KAccel if it has a valid name, + if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) ) + insertKAccel( kaccel ); + + if( bChanged ) { + // KDE 4: remove + if ( d->m_kaccel ) + d->m_kaccel->setShortcut( name(), cut ); + // KDE 4: remove end + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateShortcut( i ); + } +*/ + + return true; +} + +bool KAction::updateKAccelShortcut( KAccel* kaccel ) +{ + qDebug("KAction::updateKAccelShortcut~ ...1 has top be fixed"); + // Check if action is permitted +/*US + 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; +*/ + return true; +} + +void KAction::insertKAccel( KAccel* kaccel ) +{ + qDebug("KAction::updateKAccelShortcut~ ...1 has top be fixed"); +/*US + //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 ) +{ + qDebug("KAction::removeKAccel~ ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::removeKAccel( " << i << " ): this = " << this << endl; + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + if( d->m_kaccelList[i] == kaccel ) { + kaccel->remove( name() ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + disconnect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + break; + } + } +*/ +} + +// KDE 4: remove +void KAction::setAccel( int keyQt ) +{ + setShortcut( KShortcut(keyQt) ); +} +// KDE 4: remove end + +void KAction::updateShortcut( int i ) +{ + int id = itemId( i ); + + QWidget* w = container( i ); + if ( w->inherits( "QPopupMenu" ) ) { + QPopupMenu* menu = static_cast<QPopupMenu*>(w); + updateShortcut( menu, id ); + } + else if ( w->inherits( "QMenuBar" ) ) +//US static_cast<QMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id ); +//US (QMenuBar*)(w)->setAccel( d->m_cut.keyCodeQt(), id ); + qDebug("KAction::updateShortcut( int i ) ...1 has top be fixed"); + +} + +void KAction::updateShortcut( QPopupMenu* menu, int id ) +{ +/*US + //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 ); + kdWarning(129) << "KAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No KAccel, probably missing a parent collection." << endl; + } +*/ + qDebug("KAction::updateShortcut( QPopupMenu* menu, int id ) ...1 has top be fixed"); + +} + +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) ); +} + +int KAction::accel() const +{ + qDebug("KAction::accel() ...1 has top be fixed"); +//US return d->m_cut.keyCodeQt(); + return 0; +} + +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 ) +{ + qDebug("KAction::setToolTip ...1 has top be fixed"); + d->setToolTip( tt ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateToolTip( i ); +} + +void KAction::updateToolTip( int i ) +{ + qDebug("KAction::updateToolTip ...1 has top be fixed"); + QWidget *w = container( i ); + + if ( w->inherits( "KToolBar" ) ) + QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() ); + else if ( w->inherits( "QToolBar" ) ) + 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 == 0) { + kdWarning(129) << "KAction::plug called with 0 argument\n"; + return -1; + } + +#ifndef NDEBUG + KAccel* kaccel = kaccelCurrent(); + // If there is a shortcut, but no KAccel available + if( !d->m_cut.isNull() && kaccel == 0 ) { + kdWarning(129) << "KAction::plug(): has no KAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis +//US kdDebug(129) << kdBacktrace() << endl; + } +#endif + + // Check if action is permitted +//US if (kapp && !kapp->authorizeKAction(name())) +//US return -1; + + plugShortcut(); + + if ( w->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( w ); + int id; + // Don't insert shortcut into menu if it's already in a KAccel object. + //qDebug("KAction::plug warning: real shortcuts not available yet. "); +//US int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt(); + int keyQt = 0; + + if ( d->hasIcon() ) + { +/*US + KInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + id = menu->insertItem( d->iconSet( KIcon::Small, 0/*US , instance */), d->text(), this,//dsweet + SLOT( slotActivated() ), keyQt, + -1, index ); + } + else + id = menu->insertItem( d->text(), this, + SLOT( slotActivated() ), //dsweet + keyQt, -1, index ); + + // If the shortcut is already in a KAccel object, then + // we need to set the menu item's shortcut text. +/*US 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 ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + + int id_ = getToolButtonID(); +/*US + 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( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index ); + } + else + { + QString icon = d->iconName(); + if ( icon.isEmpty() ) + icon = "unknown"; + bar->insertButton( icon, id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index/*US, instance*/ ); + } + bar->getButton( id_ )->setName( QCString("toolbutton_")+name() ); + +//US if ( !d->whatsThis().isEmpty() ) +//US 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 ( w->inherits( "QPopupMenu" ) ) + { + QPopupMenu *menu = static_cast<QPopupMenu *>( w ); + menu->removeItem( id ); + } + else if ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + bar->removeItemDelayed( id ); + } + else if ( w->inherits( "QMenuBar" ) ) + { + 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) +{ + qDebug("KAction::plugAccel ...1 has top be fixed"); +/*US + 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() +{ + qDebug("KAction::unplugAccel ...1 has top be fixed"); +/*US + //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 ) +{ + qDebug("KAction::plugMainWindowAccel ...1 has top be fixed"); +/*US + // 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; + + // KDE 4: remove +//US if (d->m_kaccel) +//US d->m_kaccel->setEnabled(name(), enable); + // KDE 4: remove end + +//US for ( uint i = 0; i < d->m_kaccelList.count(); i++ ) +//US d->m_kaccelList[i]->setEnabled( name(), 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 ( w->inherits("QPopupMenu") ) + static_cast<QPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( w->inherits("QMenuBar") ) + static_cast<QMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( w->inherits( "KToolBar" ) ) + { + static_cast<KToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + } +} + +void KAction::setShortcutConfigurable( bool b ) +{ + d->m_configurable = b; +} + +void KAction::setText( const QString& text ) +{ +/*US + // KDE 4: remove + if (d->m_kaccel) { + KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if (pAction) + pAction->setLabel( text ); + } + // KDE 4: remove end + + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + KAccelAction* pAction = d->m_kaccelList[i]->actions().actionPtr(name()); + 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 ( w->inherits( "QPopupMenu" ) ) { + int id = itemId( i ); + static_cast<QPopupMenu*>(w)->changeItem( id, d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), id ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( i ), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + { + qDebug("KAction::updateText ...3 has top be fixed"); + QWidget *button = static_cast<KToolBar *>(w)->getWidget( itemId( i ) ); + if ( button->inherits( "KToolBarButton" ) ) + 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 ( w->inherits( "QPopupMenu" ) ) { + int itemId_ = itemId( id ); + static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), itemId_ ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + static_cast<KToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() ); + else if ( w->inherits( "QToolBar" ) ) + { + qDebug("KAction::updateIcon has top be fixed"); +//US static_cast<QToolBar *>(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 ( w->inherits( "QPopupMenu" ) ) + { + int itemId_ = itemId( id ); + static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), itemId_ ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + { + if ( icon().isEmpty() && d->hasIconSet() ) // 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 ) +{ + qDebug("KAction::updateWhatsThis ...1 has top be fixed"); + 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 ) ); +//US QWhatsThis::remove( w ); +//US 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 +{ +//US return dynamic_cast<KToolBar *>( d->m_containers[ index ].m_container ); + return (KToolBar *)( d->m_containers[ index ].m_container ); +} + +QPopupMenu* KAction::popupMenu( int index ) const +{ +//US return dynamic_cast<QPopupMenu *>( d->m_containers[ index ].m_container ); + return (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() +{ + slotActivated(); +} + +void KAction::slotActivated() +{ + emit activated(); +} + +void KAction::slotDestroyed() +{ + kdDebug(129) << "KAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl; + const QObject* o = sender(); + +/* + + + // KDE 4: remove + if ( o == d->m_kaccel ) + { + d->m_kaccel = 0; + return; + } + // KDE 4: remove end + + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) + { + if ( o == d->m_kaccelList[i] ) + { + disconnect( d->m_kaccelList[i], SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + 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; + QValueList<KActionPrivate::Container>::ConstIterator it = d->m_containers.begin(); + while( it != d->m_containers.end() ) + { + if ( (*it).m_representative == widget || (*it).m_container == widget ) + return pos; + ++it; + ++pos; + } + + return -1; +} + +void KAction::removeContainer( int index ) +{ + int i = 0; + QValueList<KActionPrivate::Container>::Iterator it = d->m_containers.begin(); + while( it != d->m_containers.end() ) + { + if ( i == index ) + { + d->m_containers.remove( it ); + return; + } + ++it; + ++i; + } +} + +// FIXME: Remove this (ellis) +void KAction::slotKeycodeChanged() +{ + qDebug("KAction::slotKeycodeChanged() ...44 has top be fixed"); +/*US + 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 ) ); +} + +void KAction::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +//US #include "kaction.moc" diff --git a/microkde/kdeui/kaction.h b/microkde/kdeui/kaction.h new file mode 100644 index 0000000..13e2e1e --- a/dev/null +++ b/microkde/kdeui/kaction.h @@ -0,0 +1,624 @@ +/* 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> + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kaction_h__ +#define __kaction_h__ + + +//US #include <qkeysequence.h> +#include <qobject.h> +#include <qvaluelist.h> +#include <qguardedptr.h> +#include <kguiitem.h> +#include <kshortcut.h> +#include <kstdaction.h> +//US#include <kicontheme.h> + +//US added the following files +#include <kiconloader.h> + +class QMenuBar; +class QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +class QIconSet; +class QString; +class KToolBar; + +class KAccel; +//USclass KAccelActions; +//USclass KConfig; +//USclass KConfigBase; +//USclass KURL; +//USclass KInstance; +//USclass KToolBar; +class KActionCollection; +//USclass KPopupMenu; +class KMainWindow; + +/** + * The KAction class (and derived and super classes) provides a way to + * easily encapsulate a "real" user-selected action or event in your + * program. + * + * For instance, a user may want to @p paste the contents of + * the clipboard or @p scroll @p down a document or @p quit the + * application. These are all @p actions -- events that the + * user causes to happen. The KAction class allows the developer to + * deal with these actions in an easy and intuitive manner. + * + * Specifically, the KAction class encapsulated the various attributes + * to an event/action. For instance, an action might have an icon + * that goes along with it (a clipboard for a "paste" action or + * scissors for a "cut" action). The action might have some text to + * describe the action. It will certainly have a method or function + * that actually @p executes the action! All these attributes + * are contained within the KAction object. + * + * The advantage of dealing with Actions is that you can manipulate + * the Action without regard to the GUI representation of it. For + * instance, in the "normal" way of dealing with actions like "cut", + * you would manually insert a item for Cut into a menu and a button + * into a toolbar. If you want to disable the cut action for a moment + * (maybe nothing is selected), you woud have to hunt down the pointer + * to the menu item and the toolbar button and disable both + * individually. Setting the menu item and toolbar item up uses very + * similar code - but has to be done twice! + * + * With the Action concept, you simply "plug" the Action into whatever + * GUI element you want. The KAction class will then take care of + * correctly defining the menu item (with icons, accelerators, text, + * etc) or toolbar button.. or whatever. From then on, if you + * manipulate the Action at all, the effect will propogate through all + * GUI representations of it. Back to the "cut" example: if you want + * to disable the Cut Action, you would simply do + * 'cutAction->setEnabled(false)' and the menuitem and button would + * instantly be disabled! + * + * This is the biggest advantage to the Action concept -- there is a + * one-to-one relationship between the "real" action and @p all + * GUI representations of it. + * + * KAction emits the activated() signal if the user activated the + * corresponding GUI element ( menu item, toolbar button, etc. ) + * + * If you are in the situation of wanting to map the activated() + * signal of multiple action objects to one slot, with a special + * argument bound to each action, then you might consider using + * @ref QSignalMapper . A tiny example: + * + * <PRE> + * QSignalMapper *desktopNumberMapper = new QSignalMapper( this ); + * connect( desktopNumberMapper, SIGNAL( mapped( int ) ), + * this, SLOT( moveWindowToDesktop( int ) ) ); + * + * for ( uint i = 0; i < numberOfDesktops; ++i ) { + * KAction *desktopAction = new KAction( i18n( "Move Window to Desktop %i" ).arg( i ), ... ); + * connect( desktopAction, SIGNAL( activated() ), desktopNumberMapper, SLOT( map() ) ); + * desktopNumberMapper->setMapping( desktopAction, i ); + * } + * </PRE> + * + * @sect General Usage: + * + * The steps to using actions are roughly as follows + * + * @li Decide which attributes you want to associate with a given + * action (icons, text, keyboard shortcut, etc) + * @li Create the action using KAction (or derived or super class). + * @li "Plug" the Action into whatever GUI element you want. Typically, + * this will be a menu or toolbar. + * + * @sect Detailed Example: + * + * Here is an example of enabling a "New [document]" action + * <PRE> + * KAction *newAct = new KAction(i18n("&New"), "filenew", + * KStdAccel::shortcut(KStdAccel::New), + * this, SLOT(fileNew()), + * actionCollection(), "new"); + * </PRE> + * This line creates our action. It says that wherever this action is + * displayed, it will use "&New" as the text, the standard icon, and + * the standard shortcut. It further says that whenever this action + * is invoked, it will use the fileNew() slot to execute it. + * + * <PRE> + * QPopupMenu *file = new QPopupMenu; + * newAct->plug(file); + * </PRE> + * That just inserted the action into the File menu. The point is, it's not + * important in which menu it is: all manipulation of the item is + * done through the newAct object. + * + * <PRE> + * newAct->plug(toolBar()); + * </PRE> + * And this inserted the Action into the main toolbar as a button. + * + * That's it! + * + * If you want to disable that action sometime later, you can do so + * with + * <PRE> + * newAct->setEnabled(false) + * </PRE> + * and both the menuitem in File and the toolbar button will instantly + * be disabled. + * + * Do not delete a KAction object without unplugging it from all its + * containers. The simplest way to do that is to use the unplugAll() + * as in the following example: + * <PRE> + * newAct->unplugAll(); + * delete newAct; + * </PRE> + * Normally you will not need to do this as KActionCollection manages + * everything for you. + * + * Note: if you are using a "standard" action like "new", "paste", + * "quit", or any other action described in the KDE UI Standards, + * please use the methods in the @ref KStdAction class rather than + * defining your own. + * + * @sect Usage Within the XML Framework: + * + * If you are using KAction within the context of the XML menu and + * toolbar building framework, then there are a few tiny changes. The + * first is that you must insert your new action into an action + * collection. The action collection (a @ref KActionCollection) is, + * logically enough, a central collection of all of the actions + * defined in your application. The XML UI framework code in KXMLGUI + * classes needs access to this collection in order to build up the + * GUI (it's how the builder code knows which actions are valid and + * which aren't). + * + * Also, if you use the XML builder framework, then you do not ever + * have to plug your actions into containers manually. The framework + * does that for you. + * + * @see KStdAction + * @short Class to encapsulate user-driven action or event + */ +class KAction : public QObject +{ + friend class KActionCollection; + Q_OBJECT + Q_PROPERTY( int containerCount READ containerCount ) + Q_PROPERTY( QString plainText READ plainText ) + Q_PROPERTY( QString text READ text WRITE setText ) + Q_PROPERTY( QString shortcut READ shortcutText WRITE setShortcutText ) + Q_PROPERTY( bool enabled READ isEnabled WRITE setEnabled ) + Q_PROPERTY( QString group READ group WRITE setGroup ) + Q_PROPERTY( QString whatsThis READ whatsThis WRITE setWhatsThis ) + Q_PROPERTY( QString toolTip READ toolTip WRITE setToolTip ) + Q_PROPERTY( QString icon READ icon WRITE setIcon ) +public: + /** + * Constructs an action with text, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. + * + * If you do not want or have a keyboard shortcut, + * set the @p cut param to 0. + * + * This is the most common KAction used when you do not have a + * corresponding icon (note that it won't appear in the current version + * of the "Edit ToolBar" dialog, because an action needs an icon to be + * plugged in a toolbar...). + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard shortcut. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + /** + * Constructs an action with text, icon, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. + * + * If you do not want or have a keyboard shortcut, set the + * @p cut param to 0. + * + * This is the other common KAction used. Use it when you + * @p do have a corresponding icon. + * + * @param text The text that will be displayed. + * @param pix The icon to display. + * @param cut The corresponding keyboard shortcut. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + /** + * Constructs an action with text, icon, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. The icon is loaded on demand later based on where it + * is plugged in. + * + * If you do not want or have a keyboard shortcut, set the + * @p cut param to 0. + * + * This is the other common KAction used. Use it when you + * @p do have a corresponding icon. + * + * @param text The text that will be displayed. + * @param pix The icon to display. + * @param cut The corresponding keyboard shortcut (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + /** + * The same as the above constructor, but with a KGuiItem providing + * the text and icon. + * + * @param item The KGuiItem with the label and (optional) icon. + */ + KAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + /** + * @obsolete + */ + KAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + /** + * @obsolete + */ + KAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Standard destructor + */ + virtual ~KAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will + * typically be a menu or a toolbar. From this point on, you will + * never need to directly manipulate the item in the menu or + * toolbar. You do all enabling/disabling/manipulation directly + * with your KAction object. + * + * @param w The GUI element to display this action + */ + virtual int plug( QWidget *w, int index = -1 ); + + /** + * @deprecated. Shouldn't be used. No substitute available. + * + * "Plug" or insert this action into a given KAccel. + * + * @param accel The KAccel collection which holds this accel + * @param configurable If the shortcut is configurable via + * the KAccel configuration dialog (this is somehow deprecated since + * there is now a KAction key configuration dialog). + */ + virtual void plugAccel(KAccel *accel, bool configurable = true); + + /** + * "Unplug" or remove this action from a given widget. + * + * This will typically be a menu or a toolbar. This is rarely + * used in "normal" application. Typically, it would be used if + * your application has several views or modes, each with a + * completely different menu structure. If you simply want to + * disable an action for a given period, use @ref setEnabled() + * instead. + * + * @param w Remove the action from this GUI element. + */ + virtual void unplug( QWidget *w ); + + /** + * @deprecated. Complement method to plugAccel(). + * Disconnect this action from the KAccel. + */ + virtual void unplugAccel(); + + /** + * returns whether the action is plugged into any container widget or not. + * @since 3.1 + */ + virtual bool isPlugged() const; + + /** + * returns whether the action is plugged into the given container + */ + bool isPlugged( const QWidget *container ) const; + + /** + * returns whether the action is plugged into the given container with the given, container specific, id (often + * menu or toolbar id ) . + */ + virtual bool isPlugged( const QWidget *container, int id ) const; + + /** + * returns whether the action is plugged into the given container with the given, container specific, representative + * container widget item. + */ + virtual bool isPlugged( const QWidget *container, const QWidget *_representative ) const; + + QWidget* container( int index ) const; + int itemId( int index ) const; + QWidget* representative( int index ) const; + int containerCount() const; + /// @since 3.1 + uint kaccelCount() const; + + virtual bool hasIcon() const; +#ifndef KDE_NO_COMPAT + bool hasIconSet() const { return hasIcon(); } +#endif + virtual QString plainText() const; + + /** + * Get the text associated with this action. + */ + virtual QString text() const; + + /** + * Get the keyboard shortcut associated with this action. + */ + virtual const KShortcut& shortcut() const; + /** + * Get the default shortcut for this action. + */ + virtual const KShortcut& shortcutDefault() const; + + // These two methods are for Q_PROPERTY + QString shortcutText() const; + void setShortcutText( const QString& ); + + /** + * Returns true if this action is enabled. + */ + virtual bool isEnabled() const; + + /** + * Returns true if this action's shortcut is configurable. + */ + virtual bool isShortcutConfigurable() const; + + virtual QString group() const; + + /** + * Get the What's this text for the action. + */ + virtual QString whatsThis() const; + + /** + * Get the tooltip text for the action. + */ + virtual QString toolTip() const; + + /** + * Get the QIconSet from which the icons used to display this action will + * be chosen. + */ + virtual QIconSet iconSet( KIcon::Group group, int size=0 ) const; + +#ifndef KDE_NO_COMPAT + QIconSet iconSet() const + { + return iconSet( KIcon::Small ); + } +#endif + + virtual QString icon() const; + + KActionCollection *parentCollection() const; + + /** + * @internal + * Generate a toolbar button id. Made public for reimplementations. + */ + static int getToolButtonID(); + + + void unplugAll(); + +public slots: + /** + * Sets the text associated with this action. The text is used for menu + * and toolbar labels etc. + */ + virtual void setText(const QString &text); + + /** + * Sets the keyboard shortcut associated with this action. + */ + virtual bool setShortcut( const KShortcut& ); + + virtual void setGroup( const QString& ); + + /** + * Sets the What's this text for the action. This text will be displayed when + * a widget that has been created by plugging this action into a container + * is clicked on in What's this mode. + * + * The What's this text can include QML markup as well as raw text. + */ + virtual void setWhatsThis( const QString& text ); + + /** + * Sets the tooltip text for the action. + * This will be used as a tooltip for a toolbar button, as a + * statusbar help-text for a menu item, and it also appears + * in the toolbar editor, to describe the action. + */ + virtual void setToolTip( const QString& ); + + /** + * Sets the QIconSet from which the icons used to display this action will + * be chosen. + */ + virtual void setIconSet( const QIconSet &iconSet ); + + virtual void setIcon( const QString& icon ); + + /** + * Enables or disables this action. All uses of this action (eg. in menus + * or toolbars) will be updated to reflect the state of the action. + */ + virtual void setEnabled(bool enable); + + /** + * Indicate whether the user may configure the action's shortcut. + */ + virtual void setShortcutConfigurable( bool ); + + /** + * Emulate user's interaction programmatically, by activating the action. + * The implementation simply emits activated(). + */ + virtual void activate(); + +protected slots: + virtual void slotDestroyed(); + virtual void slotKeycodeChanged(); + virtual void slotActivated(); + +protected: + KToolBar* toolBar( int index ) const; + QPopupMenu* popupMenu( int index ) const; + void removeContainer( int index ); + int findContainer( const QWidget* widget ) const; + void plugMainWindowAccel( QWidget *w ); + + void addContainer( QWidget* parent, int id ); + void addContainer( QWidget* parent, QWidget* representative ); + + virtual void updateShortcut( int i ); + virtual void updateShortcut( QPopupMenu* menu, int id ); + virtual void updateGroup( int id ); + virtual void updateText(int i ); + virtual void updateEnabled(int i); + virtual void updateIconSet(int i); + virtual void updateIcon( int i); + virtual void updateToolTip( int id ); + virtual void updateWhatsThis( int i ); + + KActionCollection *m_parentCollection; + QString whatsThisWithIcon() const; + +signals: + void activated(); + void enabled( bool ); + +private: + void initPrivate( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot ); + KAccel* kaccelCurrent(); + bool initShortcut( const KShortcut& ); + void plugShortcut(); + bool updateKAccelShortcut( KAccel* kaccel ); + void insertKAccel( KAccel* ); + /** @internal To be used exclusively by KActionCollection::removeWidget(). */ + void removeKAccel( KAccel* ); + +#ifndef KDE_NO_COMPAT +public: + /** + * @deprecated. Use shortcut(). + * Get the keyboard accelerator associated with this action. + */ + int accel() const; + + QString statusText() const + { return toolTip(); } + + /** + * @deprecated. Use setShortcut(). + * Sets the keyboard accelerator associated with this action. + */ + void setAccel( int key ); + + /** + * @deprecated. Use setToolTip instead (they do the same thing now). + */ + void setStatusText( const QString &text ) + { setToolTip( text ); } + + /** + * @deprecated. for backwards compatibility. + */ + int menuId( int i ) { return itemId( i ); } +#endif // !KDE_NO_COMPAT + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionPrivate; + KActionPrivate *d; +}; + +#include <kactioncollection.h> +#include <kactionclasses.h> + +#endif diff --git a/microkde/kdeui/kactionclasses.cpp b/microkde/kdeui/kactionclasses.cpp new file mode 100644 index 0000000..82e6c8b --- a/dev/null +++ b/microkde/kdeui/kactionclasses.cpp @@ -0,0 +1,2058 @@ +/* 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kactionclasses.h" + +#include <assert.h> + +#include <qfontdatabase.h> +#include <qobjectlist.h> +//US#include <qwhatsthis.h> +#include <qtimer.h> + +//US#include <kaccel.h> +//US#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +//US#include <kfontcombo.h> +//US#include <kmainwindow.h> +//US#include <kmenubar.h> +//US#include <kpopupmenu.h> +#include <kcombobox.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> +#include <kurl.h> + +//US added the following includefiles +#include <kconfigbase.h> +#include <qwidget.h> +#include <qpopupmenu.h> +#include <qmenubar.h> +#include <qmainwindow.h> +#include <qtoolbar.h> +#include <qcombobox.h> +#include <qmainwindow.h> + + +static QFontDatabase *fontDataBase = 0; + +static void cleanupFontDatabase() +{ + delete fontDataBase; + fontDataBase = 0; +} + +static void get_fonts( QStringList &lst ) +{ + if ( !fontDataBase ) { + fontDataBase = new QFontDatabase(); + qAddPostRoutine( cleanupFontDatabase ); + } + lst.clear(); + QStringList families = fontDataBase->families(); + for ( QStringList::Iterator it = families.begin(); it != families.end(); ++it ) + { + QString family = *it; + if ( family. contains('-') ) // remove foundry + family = family.right( family.length() - family.find('-' ) - 1); + if ( !lst.contains( family ) ) + lst.append( family ); + } + lst.sort(); +} + +static QValueList<int> get_standard_font_sizes() +{ + if ( !fontDataBase ) { + fontDataBase = new QFontDatabase(); + qAddPostRoutine( cleanupFontDatabase ); + } + return fontDataBase->standardSizes(); +} + +class KToggleAction::KToggleActionPrivate +{ +public: + KToggleActionPrivate() + { + m_checked = false; + } + + bool m_checked; + QString m_exclusiveGroup; +}; + +KToggleAction::KToggleAction( const QString& text, const KShortcut& cut, + QObject* parent, + const char* name ) + : KAction( text, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::~KToggleAction() +{ + delete d; +} + +int KToggleAction::plug( QWidget* widget, int index ) +{ + if ( !widget->inherits("QPopupMenu") && !widget->inherits("KToolBar") ) + { + kdWarning() << "Can not plug KToggleAction in " << widget->className() << endl; + return -1; + } + +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + + int _index = KAction::plug( widget, index ); + if ( _index == -1 ) + return _index; + + if ( widget->inherits("QPopupMenu") ) + { + int id = itemId( _index ); + + static_cast<QPopupMenu*>(widget)->setItemChecked( id, d->m_checked ); + } else if ( widget->inherits( "KToolBar" ) ) { + + KToolBar *bar = static_cast<KToolBar *>( widget ); + + bar->setToggle( itemId( _index ), true ); + bar->setButton( itemId( _index ), isChecked() ); + } + + return _index; +} + +void KToggleAction::setChecked( bool c ) +{ + if ( c == d->m_checked ) + return; + //kdDebug(129) << "KToggleAction::setChecked(" << c << ") " << this << " " << name() << endl; + + d->m_checked = c; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateChecked( i ); + + if ( c && parent() && !exclusiveGroup().isEmpty() ) { + const QObjectList *list = parent()->children(); + if ( list ) { + QObjectListIt it( *list ); + for( ; it.current(); ++it ) { + if ( it.current()->inherits( "KToggleAction" ) && it.current() != this && + static_cast<KToggleAction*>(it.current())->exclusiveGroup() == exclusiveGroup() ) { + KToggleAction *a = static_cast<KToggleAction*>(it.current()); + if( a->isChecked() ) { + a->setChecked( false ); + emit a->toggled( false ); + } + } + } + } + } +} + +void KToggleAction::updateChecked( int id ) +{ + QWidget *w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) + static_cast<QPopupMenu*>(w)->setItemChecked( itemId( id ), d->m_checked ); + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->setItemChecked( itemId( id ), d->m_checked ); + else if ( w->inherits( "KToolBar" ) ) + { + QWidget* r = static_cast<KToolBar*>( w )->getButton( itemId( id ) ); + if ( r && r->inherits( "KToolBarButton" ) ) + static_cast<KToolBar*>( w )->setButton( itemId( id ), d->m_checked ); + } +} + +void KToggleAction::slotActivated() +{ + setChecked( !isChecked() ); + emit activated(); + emit toggled( isChecked() ); +} + +bool KToggleAction::isChecked() const +{ + return d->m_checked; +} + +void KToggleAction::setExclusiveGroup( const QString& name ) +{ + d->m_exclusiveGroup = name; +} + +QString KToggleAction::exclusiveGroup() const +{ + return d->m_exclusiveGroup; +} + + +KRadioAction::KRadioAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( QObject* parent, const char* name ) +: KToggleAction( parent, name ) +{ +} + +void KRadioAction::slotActivated() +{ + if ( isChecked() ) + { + const QObject *senderObj = sender(); + + if ( !senderObj || !senderObj->inherits( "KToolBarButton" ) ) + return; + + qDebug("KRadioAction::slotActivated has to be fixed"); + const_cast<KToolBarButton *>( static_cast<const KToolBarButton *>( senderObj ) )->on( true ); + + return; + } + + KToggleAction::slotActivated(); +} + +class KSelectAction::KSelectActionPrivate +{ +public: + KSelectActionPrivate() + { + m_edit = false; + m_menuAccelsEnabled = true; + m_menu = 0; + m_current = -1; + m_comboWidth = -1; + } + bool m_edit; + bool m_menuAccelsEnabled; + QPopupMenu *m_menu; + int m_current; + int m_comboWidth; + QStringList m_list; + + QString makeMenuText( const QString &_text ) + { + if ( m_menuAccelsEnabled ) + return _text; + QString text = _text; + uint i = 0; + while ( i < text.length() ) { + if ( text.at( i ) == '&' ) { + text.insert( i, '&' ); + i += 2; + } + else + ++i; + } + return text; + } +}; + +KSelectAction::KSelectAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::~KSelectAction() +{ + assert(d); + delete d->m_menu; + delete d; d = 0; +} + +void KSelectAction::setCurrentItem( int id ) +{ + if ( id >= (int)d->m_list.count() ) { + ASSERT(id < (int)d->m_list.count()); + return; + } + + if ( d->m_menu ) + { + if ( d->m_current >= 0 ) + d->m_menu->setItemChecked( d->m_current, false ); + if ( id >= 0 ) + { + //US qDebug("KSelectAction::setCurrentItem %i", id); + d->m_menu->setItemChecked( id, true ); + } + } + + d->m_current = id; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateCurrentItem( i ); + + // emit KAction::activated(); + // emit activated( currentItem() ); + // emit activated( currentText() ); +} + +void KSelectAction::setComboWidth( int width ) +{ + if ( width < 0 ) + return; + + d->m_comboWidth=width; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateComboWidth( i ); + +} +QPopupMenu* KSelectAction::popupMenu() const +{ + kdDebug(129) << "KSelectAction::popupMenu()" << endl; // remove -- ellis + if ( !d->m_menu ) + { +//US d->m_menu = new KPopupMenu(0L, "KSelectAction::popupMenu()"); + d->m_menu = new QPopupMenu(0L, "QSelectAction::popupMenu()"); + setupMenu(); + if ( d->m_current >= 0 ) + d->m_menu->setItemChecked( d->m_current, true ); + } + + return d->m_menu; +} + +void KSelectAction::setupMenu() const +{ + if ( !d->m_menu ) + return; + d->m_menu->clear(); + + QStringList::ConstIterator it = d->m_list.begin(); + for( uint id = 0; it != d->m_list.end(); ++it, ++id ) { + QString text = *it; + if ( !text.isEmpty() ) + d->m_menu->insertItem( d->makeMenuText( text ), this, SLOT( slotActivated( int ) ), 0, id ); + else + d->m_menu->insertSeparator(); + } +} + +void KSelectAction::changeItem( int index, const QString& text ) +{ + if ( index < 0 || index >= (int)d->m_list.count() ) + { + kdWarning() << "KSelectAction::changeItem Index out of scope" << endl; + return; + } + + d->m_list[ index ] = text; + + if ( d->m_menu ) + d->m_menu->changeItem( index, d->makeMenuText( text ) ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + changeItem( i, index, text ); +} + +void KSelectAction::changeItem( int id, int index, const QString& text) +{ + if ( index < 0 ) + return; + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) + { + QWidget* r = (static_cast<KToolBar*>( w ))->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) + { + QComboBox *b = static_cast<QComboBox*>( r ); + b->changeItem(text, index ); + } + } + +} + +void KSelectAction::setItems( const QStringList &lst ) +{ + kdDebug(129) << "KAction::setItems()" << endl; // remove -- ellis + d->m_list = lst; + d->m_current = -1; + + setupMenu(); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateItems( i ); + + // Disable if empty and not editable + setEnabled ( lst.count() > 0 || d->m_edit ); +} + +QStringList KSelectAction::items() const +{ + return d->m_list; +} + +QString KSelectAction::currentText() const +{ + if ( currentItem() < 0 ) + return QString::null; + + return d->m_list[ currentItem() ]; +} + +int KSelectAction::currentItem() const +{ + return d->m_current; +} + +void KSelectAction::updateCurrentItem( int id ) +{ + if ( d->m_current < 0 ) + return; + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *b = static_cast<QComboBox*>( r ); + b->setCurrentItem( d->m_current ); + } + } +} + +int KSelectAction::comboWidth() const +{ + return d->m_comboWidth; +} + +void KSelectAction::updateComboWidth( int id ) +{ + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *cb = static_cast<QComboBox*>( r ); + cb->setMinimumWidth( d->m_comboWidth ); + cb->setMaximumWidth( d->m_comboWidth ); + } + } +} + +void KSelectAction::updateItems( int id ) +{ + kdDebug(129) << "KAction::updateItems( " << id << ", lst )" << endl; // remove -- ellis + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *cb = static_cast<QComboBox*>( r ); + cb->clear(); + QStringList lst = comboItems(); + QStringList::ConstIterator it = lst.begin(); + for( ; it != lst.end(); ++it ) + cb->insertItem( *it ); + // Ok, this currently doesn't work due to a bug in QComboBox + // (the sizehint is cached for ever and never recalculated) + // Bug reported (against Qt 2.3.1). + cb->setMinimumWidth( cb->sizeHint().width() ); + } + } + +} + +int KSelectAction::plug( QWidget *widget, int index ) +{ +//US if (kapp && !kapp->authorizeKAction(name())) +//US return -1; + + kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis + if ( widget->inherits("QPopupMenu") ) + { + // Create the PopupMenu and store it in m_menu + (void)popupMenu(); + + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + int id; + + if ( hasIconSet() ) + id = menu->insertItem( iconSet(), text(), d->m_menu, -1, index ); + else + id = menu->insertItem( text(), d->m_menu, -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + QString wth = whatsThis(); + if ( !wth.isEmpty() ) + menu->setWhatsThis( id, wth ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits("KToolBar") ) + { + + KToolBar* bar = static_cast<KToolBar*>( widget ); + int id_ = KAction::getToolButtonID(); + bar->insertCombo( comboItems(), id_, isEditable(), + SIGNAL( activated( const QString & ) ), this, + SLOT( slotActivated( const QString & ) ), isEnabled(), + toolTip(), -1, index ); + + KComboBox *cb = bar->getCombo( id_ ); + if ( cb ) + { + cb->setMaximumHeight( 34 ); + if (!isEditable()) cb->setFocusPolicy(QWidget::NoFocus); + cb->setMinimumWidth( cb->sizeHint().width() ); + if ( d->m_comboWidth > 0 ) + { + cb->setMinimumWidth( d->m_comboWidth ); + cb->setMaximumWidth( d->m_comboWidth ); + } + cb->setInsertionPolicy( QComboBox::NoInsertion ); +//US QWhatsThis::add( cb, whatsThis() ); + } + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + updateCurrentItem( containerCount() - 1 ); + + return containerCount() - 1; + + } + kdWarning() << "Can not plug KAction in " << widget->className() << endl; + return -1; +} + +QStringList KSelectAction::comboItems() const +{ + //qDebug("KSelectAction::comboItems has to be fixed"); + if( d->m_menuAccelsEnabled ) + { + QStringList lst; + QStringList::ConstIterator it = d->m_list.begin(); + for( ; it != d->m_list.end(); ++it ) + { + QString item = *it; + int i = item.find( '&' ); + if ( i > -1 ) + item = item.remove( i, 1 ); + lst.append( item ); + } + return lst; + } + else + { + return d->m_list; + } +} + +void KSelectAction::clear() +{ + if ( d->m_menu ) + d->m_menu->clear(); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateClear( i ); +} + +void KSelectAction::updateClear( int id ) +{ + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *b = static_cast<QComboBox*>( r ); + b->clear(); + } + } +} + +void KSelectAction::slotActivated( int id ) +{ + if ( d->m_current == id ) + return; + + setCurrentItem( id ); + // Delay this. Especially useful when the slot connected to activated() will re-create + // the menu, e.g. in the recent files action. This prevents a crash. + + QTimer::singleShot( 0, this, SLOT( slotActivated() ) ); +} + +void KSelectAction::slotActivated( const QString &text ) +{ + if ( isEditable() ) + { + QStringList lst = items(); + if(lst.contains(text)==0) + { + lst.append( text ); + setItems( lst ); + } + } + + int i = items().findIndex( text ); + if ( i > -1 ) + setCurrentItem( i ); + else + setCurrentItem( comboItems().findIndex( text ) ); + // Delay this. Especially useful when the slot connected to activated() will re-create + // the menu, e.g. in the recent files action. This prevents a crash. + + QTimer::singleShot( 0, this, SLOT( slotActivated() ) ); +} + +void KSelectAction::slotActivated() +{ + KAction::slotActivated(); + kdDebug(129) << "KSelectAction::slotActivated currentItem=" << currentItem() << " currentText=" << currentText() << endl; + emit activated( currentItem() ); + emit activated( currentText() ); +} + +void KSelectAction::setEditable( bool edit ) +{ + d->m_edit = edit; +} + +bool KSelectAction::isEditable() const +{ + return d->m_edit; +} + +void KSelectAction::setRemoveAmpersandsInCombo( bool b ) +{ + setMenuAccelsEnabled( b ); +} + +bool KSelectAction::removeAmpersandsInCombo() const +{ + return menuAccelsEnabled( ); +} + +void KSelectAction::setMenuAccelsEnabled( bool b ) +{ + d->m_menuAccelsEnabled = b; +} + +bool KSelectAction::menuAccelsEnabled() const +{ + return d->m_menuAccelsEnabled; +} + +class KListAction::KListActionPrivate +{ +public: + KListActionPrivate() + { + m_current = 0; + } + int m_current; +}; + +KListAction::KListAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( const QString& text, const QString& pix, + const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::~KListAction() +{ + delete d; d = 0; +} + +void KListAction::setCurrentItem( int index ) +{ + KSelectAction::setCurrentItem( index ); + d->m_current = index; + + // emit KAction::activated(); + // emit activated( currentItem() ); + // emit activated( currentText() ); +} + +QString KListAction::currentText() const +{ + if ( currentItem() < 0 ) + return QString::null; + + return items()[ currentItem() ]; +} + +int KListAction::currentItem() const +{ + return d->m_current; +} + +class KRecentFilesAction::KRecentFilesActionPrivate +{ +public: + KRecentFilesActionPrivate() + { + m_maxItems = 0; + } + uint m_maxItems; +}; + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( QObject* parent, const char* name, + uint maxItems ) + : KListAction( parent, name ) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +void KRecentFilesAction::init() +{ + connect( this, SIGNAL( activated( const QString& ) ), + this, SLOT( itemSelected( const QString& ) ) ); + + setMenuAccelsEnabled( false ); +} + +KRecentFilesAction::~KRecentFilesAction() +{ + delete d; d = 0; +} + +uint KRecentFilesAction::maxItems() const +{ + return d->m_maxItems; +} + +void KRecentFilesAction::setMaxItems( uint maxItems ) +{ + QStringList lst = items(); + uint oldCount = lst.count(); + + // set new maxItems + d->m_maxItems = maxItems; + + // remove all items that are too much + while( lst.count() > maxItems ) + { + // remove last item + lst.remove( lst.last() ); + } + + // set new list if changed + if( lst.count() != oldCount ) + setItems( lst ); +} + +void KRecentFilesAction::addURL( const KURL& url ) +{ + QString file = url.prettyURL(); + QStringList lst = items(); + + // remove file if already in list + lst.remove( file ); + + // remove las item if already maxitems in list + if( lst.count() == d->m_maxItems ) + { + // remove last item + lst.remove( lst.last() ); + } + + // add file to list + lst.prepend( file ); + setItems( lst ); +} + +void KRecentFilesAction::removeURL( const KURL& url ) +{ + QStringList lst = items(); + QString file = url.prettyURL(); + + // remove url + if( lst.count() > 0 ) + { + lst.remove( file ); + setItems( lst ); + } +} + +void KRecentFilesAction::clearURLList() +{ + clear(); +} + +void KRecentFilesAction::loadEntries( KConfig* config, QString groupname) +{ + QString key; + QString value; + QString oldGroup; + QStringList lst; + + oldGroup = config->group(); + + if (groupname.isEmpty()) + groupname = "RecentFiles"; + config->setGroup( groupname ); + + // read file list + for( unsigned int i = 1 ; i <= d->m_maxItems ; i++ ) + { + key = QString( "File%1" ).arg( i ); + value = config->readEntry( key, QString::null ); + + if (!value.isNull()) + lst.append( value ); + } + + // set file + setItems( lst ); + + config->setGroup( oldGroup ); +} + +void KRecentFilesAction::saveEntries( KConfig* config, QString groupname ) +{ + QString key; + QString value; + QStringList lst = items(); + + if (groupname.isEmpty()) + groupname = "RecentFiles"; + + config->deleteGroup( groupname); + + KConfigGroupSaver( config, groupname ); + + // write file list + for( unsigned int i = 1 ; i <= lst.count() ; i++ ) + { + key = QString( "File%1" ).arg( i ); + value = lst[ i - 1 ]; + config->writeEntry( key, value ); + } +} + +void KRecentFilesAction::itemSelected( const QString& text ) +{ + emit urlSelected( KURL( text ) ); +} + +class KFontAction::KFontActionPrivate +{ +public: + KFontActionPrivate() + { + } + QStringList m_fonts; +}; + +KFontAction::KFontAction( const QString& text, + const KShortcut& cut, QObject* parent, + const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + + +KFontAction::KFontAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::~KFontAction() +{ + delete d; + d = 0; +} + +/* + * Maintenance note: Keep in sync with KFontCombo::setCurrentFont() + */ +void KFontAction::setFont( const QString &family ) +{ + QString lowerName = family.lower(); + int i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower() == lowerName) + { + setCurrentItem(i); + return; + } + } + i = lowerName.find(" ["); + if (i>-1) + { + lowerName = lowerName.left(i); + i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower() == lowerName) + { + setCurrentItem(i); + return; + } + } + } + + lowerName += " ["; + i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower().startsWith(lowerName)) + { + setCurrentItem(i); + return; + } + } + kdDebug(129) << "Font not found " << family.lower() << endl; +} + +int KFontAction::plug( QWidget *w, int index ) +{ + qDebug("KFontAction::plug ha to be fixed"); +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; + if ( w->inherits("KToolBar") ) + { + KToolBar* bar = static_cast<KToolBar*>( w ); + int id_ = KAction::getToolButtonID(); + KFontCombo *cb = new KFontCombo( items(), bar ); + connect( cb, SIGNAL( activated( const QString & ) ), + SLOT( slotActivated( const QString & ) ) ); + cb->setEnabled( isEnabled() ); + bar->insertWidget( id_, comboWidth(), cb, index ); + cb->setMinimumWidth( cb->sizeHint().width() ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + updateCurrentItem( containerCount() - 1 ); + + return containerCount() - 1; + } + else return KSelectAction::plug( w, index ); +*/ + return 3; +} + +class KFontSizeAction::KFontSizeActionPrivate +{ +public: + KFontSizeActionPrivate() + { + } +}; + +KFontSizeAction::KFontSizeAction( const QString& text, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + init(); +} + +KFontSizeAction::~KFontSizeAction() +{ + delete d; + d = 0; +} + +void KFontSizeAction::init() +{ + d = new KFontSizeActionPrivate; + + setEditable( true ); + QValueList<int> sizes = get_standard_font_sizes(); + QStringList lst; + for ( QValueList<int>::Iterator it = sizes.begin(); it != sizes.end(); ++it ) + lst.append( QString::number( *it ) ); + + setItems( lst ); +} + +void KFontSizeAction::setFontSize( int size ) +{ + if ( size == fontSize() ) { + setCurrentItem( items().findIndex( QString::number( size ) ) ); + return; + } + + if ( size < 1 ) { + kdWarning() << "KFontSizeAction: Size " << size << " is out of range" << endl; + return; + } + + int index = items().findIndex( QString::number( size ) ); + if ( index == -1 ) { + // Insert at the correct position in the list (to keep sorting) + QValueList<int> lst; + // Convert to list of ints + QStringList itemsList = items(); + for (QStringList::Iterator it = itemsList.begin() ; it != itemsList.end() ; ++it) + lst.append( (*it).toInt() ); + // New size + lst.append( size ); + // Sort the list +qDebug("KFontSizeAction::setFontSize heapsort not found."); +//US has to be fixed +//US qHeapSort( lst ); + // Convert back to string list + QStringList strLst; + for (QValueList<int>::Iterator it = lst.begin() ; it != lst.end() ; ++it) + strLst.append( QString::number(*it) ); + KSelectAction::setItems( strLst ); + // Find new current item + index = lst.findIndex( size ); + setCurrentItem( index ); + } + else + setCurrentItem( index ); + + + //emit KAction::activated(); + //emit activated( index ); + //emit activated( QString::number( size ) ); + //emit fontSizeChanged( size ); +} + +int KFontSizeAction::fontSize() const +{ + return currentText().toInt(); +} + +void KFontSizeAction::slotActivated( int index ) +{ + KSelectAction::slotActivated( index ); + + emit fontSizeChanged( items()[ index ].toInt() ); +} + +void KFontSizeAction::slotActivated( const QString& size ) +{ + setFontSize( size.toInt() ); // insert sorted first + KSelectAction::slotActivated( size ); + emit fontSizeChanged( size.toInt() ); +} + +class KActionMenu::KActionMenuPrivate +{ +public: + KActionMenuPrivate() + { +//US m_popup = new KPopupMenu(0L,"KActionMenu::KActionMenuPrivate"); + m_popup = new QPopupMenu(0L,"KActionMenu::KActionMenuPrivate"); + m_delayed = true; + m_stickyMenu = true; + } + ~KActionMenuPrivate() + { + delete m_popup; m_popup = 0; + } + +//US KPopupMenu *m_popup; + QPopupMenu *m_popup; + bool m_delayed; + bool m_stickyMenu; +}; + +KActionMenu::KActionMenu( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, QObject* parent, + const char* name ) + : KAction( text, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, const QIconSet& icon, + QObject* parent, const char* name ) + : KAction( text, icon, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, const QString& icon, + QObject* parent, const char* name ) + : KAction( text, icon, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::~KActionMenu() +{ + unplugAll(); + kdDebug(129) << "KActionMenu::~KActionMenu()" << endl; // ellis + delete d; d = 0; +} + +void KActionMenu::popup( const QPoint& global ) +{ + popupMenu()->popup( global ); +} + + +//US KPopupMenu* KActionMenu::popupMenu() const +QPopupMenu* KActionMenu::popupMenu() const +{ + return d->m_popup; +} + +void KActionMenu::insert( KAction* cmd, int index ) +{ + if ( cmd ) + cmd->plug( d->m_popup, index ); +} + +void KActionMenu::remove( KAction* cmd ) +{ + if ( cmd ) + cmd->unplug( d->m_popup ); +} + +bool KActionMenu::delayed() const { + return d->m_delayed; +} + +void KActionMenu::setDelayed(bool _delayed) { + d->m_delayed = _delayed; +} + +bool KActionMenu::stickyMenu() const { + return d->m_stickyMenu; +} + +void KActionMenu::setStickyMenu(bool sticky) { + d->m_stickyMenu = sticky; +} + +int KActionMenu::plug( QWidget* widget, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis + if ( widget->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + int id; + if ( hasIconSet() ) + id = menu->insertItem( iconSet(), text(), d->m_popup, -1, index ); + else + id = menu->insertItem( text(), d->m_popup, -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( menu, this ); + + return containerCount() - 1; + } + else if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( widget ); + + int id_ = KAction::getToolButtonID(); + + if ( icon().isEmpty() && !iconSet().isNull() ) + bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index ); + else + { + /*US + KInstance *instance; + + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index/*US, instance */); + } + + addContainer( bar, id_ ); +/*US + if (!whatsThis().isEmpty()) + QWhatsThis::add( bar->getButton(id_), whatsThis() ); +*/ + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if (delayed()) { + bar->setDelayedPopup( id_, popupMenu(), stickyMenu() ); + } else { + bar->getButton(id_)->setPopup(popupMenu(), stickyMenu() ); + } + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( bar, this ); + + return containerCount() - 1; + } + else if ( widget->inherits( "QMenuBar" ) ) + { + QMenuBar *bar = static_cast<QMenuBar *>( widget ); + + int id; + + id = bar->insertItem( text(), popupMenu(), -1, index ); + + if ( !isEnabled() ) + bar->setItemEnabled( id, false ); + + addContainer( bar, id ); + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + + return -1; +} + +//////// + +KToolBarPopupAction::KToolBarPopupAction( const QString& text, + const QString& icon, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, icon, cut, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + +KToolBarPopupAction::KToolBarPopupAction( const QString& text, + const QString& icon, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, icon, cut, receiver, slot, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + +KToolBarPopupAction::KToolBarPopupAction( const KGuiItem& item, + const KShortcut& cut, + const QObject* receiver, + const char* slot, KActionCollection* parent, + const char* name ) + : KAction( item, cut, receiver, slot, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + + +KToolBarPopupAction::~KToolBarPopupAction() +{ + if ( m_popup ) + delete m_popup; +} + +bool KToolBarPopupAction::delayed() const { + return m_delayed; +} + +void KToolBarPopupAction::setDelayed(bool delayed) { + m_delayed = delayed; +} + +bool KToolBarPopupAction::stickyMenu() const { + return m_stickyMenu; +} + +void KToolBarPopupAction::setStickyMenu(bool sticky) { + m_stickyMenu = sticky; +} + +int KToolBarPopupAction::plug( QWidget *widget, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + // This is very related to KActionMenu::plug. + // In fact this class could be an interesting base class for KActionMenu + if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *bar = (KToolBar *)widget; + + int id_ = KAction::getToolButtonID(); +/*US + KInstance * instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index/*US, instance*/ ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if (delayed()) { + bar->setDelayedPopup( id_, popupMenu(), stickyMenu() ); + } else { + bar->getButton(id_)->setPopup(popupMenu(), stickyMenu()); + } +/*US + if ( !whatsThis().isEmpty() ) + QWhatsThis::add( bar->getButton( id_ ), whatsThisWithIcon() ); +*/ + return containerCount() - 1; + } + + + return KAction::plug( widget, index ); +} + +//US KPopupMenu *KToolBarPopupAction::popupMenu() const +QPopupMenu *KToolBarPopupAction::popupMenu() const +{ + if ( !m_popup ) { + KToolBarPopupAction *that = const_cast<KToolBarPopupAction*>(this); +//US that->m_popup = new KPopupMenu; + that->m_popup = new QPopupMenu; + } + return m_popup; +} + +//////// + +KToggleToolBarAction::KToggleToolBarAction( const char* toolBarName, + const QString& text, KActionCollection* parent, const char* name ) + : KToggleAction( text, KShortcut(), parent, name ) + , m_toolBarName( toolBarName ) + , m_toolBar( 0L ) +{ +} + +KToggleToolBarAction::KToggleToolBarAction( KToolBar *toolBar, const QString &text, + KActionCollection *parent, const char *name ) + : KToggleAction( text, KShortcut(), parent, name ) + , m_toolBarName( 0 ) + , m_toolBar( toolBar ) +{ +} + +KToggleToolBarAction::~KToggleToolBarAction() +{ +} + +int KToggleToolBarAction::plug( QWidget* w, int index ) +{ + qDebug("KToggleToolBarAction::plug has to be fixed"); +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; + + if ( !m_toolBar ) { + // 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; + +//US KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + QMainWindow * mw = 0; + if ( tl->inherits("QMainWindow") ) + mw = (QMainWindow *)(tl); // try to see if it's a kmainwindow + + if ( mw ) + m_toolBar = mw->toolBar( m_toolBarName ); + } + + if( m_toolBar ) { + setChecked( m_toolBar->isVisible() ); + connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(setChecked(bool)) ); + // Also emit toggled when the toolbar's visibility changes (see comment in header) + connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SIGNAL(toggled(bool)) ); + } else { + setEnabled( false ); + } +*/ + return KToggleAction::plug( w, index ); +} + +void KToggleToolBarAction::setChecked( bool c ) +{ + if( m_toolBar && c != m_toolBar->isVisible() ) { + if( c ) { + m_toolBar->show(); + } else { + m_toolBar->hide(); + } + qDebug("KToggleToolBarAction::setChecked has to be fixed"); +/*US + QMainWindow* mw = m_toolBar->mainWindow(); + if ( mw && mw->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>( mw )->setSettingsDirty(); +*/ + } + KToggleAction::setChecked( c ); + +} + +//////// + +KWidgetAction::KWidgetAction( QWidget* widget, + const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) + , m_widget( widget ) + , m_autoSized( false ) +{ +} + +KWidgetAction::~KWidgetAction() +{ +} + +void KWidgetAction::setAutoSized( bool autoSized ) +{ + if( m_autoSized == autoSized ) + return; + + m_autoSized = autoSized; + + if( !m_widget || !isPlugged() ) + return; + + KToolBar* toolBar = (KToolBar*)m_widget->parent(); + int i = findContainer( toolBar ); + if ( i == -1 ) + return; + int id = itemId( i ); + + toolBar->setItemAutoSized( id, m_autoSized ); + +} + +int KWidgetAction::plug( QWidget* w, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + if ( !w->inherits( "KToolBar" ) ) { + kdError() << "KWidgetAction::plug: KWidgetAction must be plugged into KToolBar." << endl; + return -1; + } + if ( !m_widget ) { + kdError() << "KWidgetAction::plug: Widget was deleted or null!" << endl; + return -1; + } + + KToolBar* toolBar = static_cast<KToolBar*>( w ); + + int id = KAction::getToolButtonID(); + + m_widget->reparent( toolBar, QPoint() ); + toolBar->insertWidget( id, 0, m_widget, index ); + toolBar->setItemAutoSized( id, m_autoSized ); + +//US QWhatsThis::add( m_widget, whatsThis() ); + addContainer( toolBar, id ); + + connect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) ); + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; +} + +void KWidgetAction::unplug( QWidget *w ) +{ + if( !m_widget || !isPlugged() ) + return; + + KToolBar* toolBar = (KToolBar*)m_widget->parent(); + if ( toolBar == w ) + { + disconnect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) ); + m_widget->reparent( 0L, QPoint(), false ); // false = showit + } + KAction::unplug( w ); +} + +void KWidgetAction::slotToolbarDestroyed() +{ + //Q_ASSERT( m_widget ); // When exiting the app the widget could be destroyed before the toolbar. + + ASSERT( isPlugged() ); + if( !m_widget || !isPlugged() ) + return; + + // Don't let a toolbar being destroyed, delete my widget. + m_widget->reparent( 0L, QPoint(), false /*showIt*/ ); +} + +//////// + +KActionSeparator::KActionSeparator( QObject *parent, const char *name ) + : KAction( parent, name ) +{ +} + +KActionSeparator::~KActionSeparator() +{ +} + +int KActionSeparator::plug( QWidget *widget, int index ) +{ + if ( widget->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + + int id = menu->insertSeparator( index ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits( "QMenuBar" ) ) + { + QMenuBar *menuBar = static_cast<QMenuBar *>( widget ); + + int id = menuBar->insertSeparator( index ); + + addContainer( menuBar, id ); + + connect( menuBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *toolBar = static_cast<KToolBar *>( widget ); + + int id = toolBar->insertSeparator( index ); +// toolBar->addSeparator(); + + addContainer( toolBar, id ); + + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + + return -1; +} + +void KToggleAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KRadioAction::virtual_hook( int id, void* data ) +{ KToggleAction::virtual_hook( id, data ); } + +void KSelectAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KListAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KRecentFilesAction::virtual_hook( int id, void* data ) +{ KListAction::virtual_hook( id, data ); } + +void KFontAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KFontSizeAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KActionMenu::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KToolBarPopupAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KToggleToolBarAction::virtual_hook( int id, void* data ) +{ KToggleAction::virtual_hook( id, data ); } + +void KWidgetAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KActionSeparator::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +/* vim: et sw=2 ts=2 + */ + +/*US +#include "kactionclasses.moc" +*/ diff --git a/microkde/kdeui/kactionclasses.h b/microkde/kdeui/kactionclasses.h new file mode 100644 index 0000000..f6e7a0f --- a/dev/null +++ b/microkde/kdeui/kactionclasses.h @@ -0,0 +1,1223 @@ +/* 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> + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kactionclasses_h__ +#define __kactionclasses_h__ + +#include <kaction.h> + +//US#include <qkeysequence.h> +//US#include <qobject.h> +//US#include <qvaluelist.h> +//US#include <qguardedptr.h> +//US#include <kguiitem.h> +#include <kshortcut.h> +//US#include <kstdaction.h> +//US#include <kicontheme.h> + +class QMenuBar; +class QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +//USclass QIconSet; +//USclass QString; +//USclass KToolBar; + +//USclass KAccel; +//USclass KAccelActions; +class KConfig; +//USclass KConfigBase; +class KURL; +//USclass KInstance; + + +//US class KToolBar needs to be replaced +class KToolBar; +class KActionCollection; + +//US class KPopupMenu needs to be replaced +//US class KPopupMenu; +//USclass KMainWindow; + +/** + * Checkbox like action. + * + * This action provides two states: checked or not. + * + * @short Checkbox like action. + */ +class KToggleAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool checked READ isChecked WRITE setChecked ) + Q_PROPERTY( QString exclusiveGroup READ exclusiveGroup WRITE setExclusiveGroup ) +public: + + /** + * Constructs a toggle action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KToggleAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will typically be a menu or a toolbar. From this point + * on, you will never need to directly manipulate the item in the + * menu or toolbar. You do all enabling/disabling/manipulation + * directly with your KToggleAction object. + * + * @param widget The GUI element to display this action. + * @param index The index of the item. + */ + virtual int plug( QWidget* widget, int index = -1 ); + + /** + * Returns the actual state of the action. + */ + bool isChecked() const; + + /** + * @return which "exclusive group" this action is part of. + * @see setExclusiveGroup + */ + QString exclusiveGroup() const; + + /** + * Defines which "exclusive group" this action is part of. + * In a given exclusive group, only one toggle action can be checked + * at a any moment. Checking an action unchecks the other actions + * of the group. + */ + virtual void setExclusiveGroup( const QString& name ); + +public slots: + /** + * Sets the state of the action. + */ + virtual void setChecked( bool ); + +protected slots: + virtual void slotActivated(); + +protected: + virtual void updateChecked( int id ); + +signals: + void toggled( bool ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToggleActionPrivate; + KToggleActionPrivate *d; +}; + +/** + * An action that operates like a radio button. At any given time + * only a single action from the group will be active. + */ +class KRadioAction : public KToggleAction +{ + Q_OBJECT +public: + /** + * Constructs a radio action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( QObject* parent = 0, const char* name = 0 ); + +protected: + virtual void slotActivated(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KRadioActionPrivate; + KRadioActionPrivate *d; +}; + +/** + * Action for selecting one of several items. + * + * This action shows up a submenu with a list of items. + * One of them can be checked. If the user clicks on an item + * this item will automatically be checked, + * the formerly checked item becomes unchecked. + * There can be only one item checked at a time. + * + * @short Action for selecting one of several items + */ +class KSelectAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( int currentItem READ currentItem WRITE setCurrentItem ) + Q_PROPERTY( QStringList items READ items WRITE setItems ) + Q_PROPERTY( bool editable READ isEditable WRITE setEditable ) + Q_PROPERTY( int comboWidth READ comboWidth WRITE setComboWidth ) + Q_PROPERTY( QString currentText READ currentText ) + Q_PROPERTY( bool menuAccelsEnabled READ menuAccelsEnabled WRITE setMenuAccelsEnabled ) +public: + + /** + * Constructs a select action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KSelectAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will typically be a menu or a toolbar. + * From this point on, you will never need to directly + * manipulate the item in the menu or toolbar. + * You do all enabling/disabling/manipulation directly with your KSelectAction object. + * + * @param widget The GUI element to display this action. + * @param index The index of the item. + */ + virtual int plug( QWidget* widget, int index = -1 ); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * @return true if the combo editable. + */ + virtual bool isEditable() const; + + /** + * @return the items that can be selected with this action. + * Use setItems to set them. + */ + virtual QStringList items() const; + + virtual void changeItem( int index, const QString& text ); + + virtual QString currentText() const; + + virtual int currentItem() const; + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This returns the maximum width set by setComboWidth + */ + virtual int comboWidth() const; + + QPopupMenu* popupMenu() const; + + /** + * Deprecated. See @ref setMenuAccelsEnabled . + * @since 3.1 + */ + void setRemoveAmpersandsInCombo( bool b ); + /// @since 3.1 + bool removeAmpersandsInCombo() const; + + /** + * Sets whether any occurence of the ampersand character ( & ) in items + * should be interpreted as keyboard accelerator for items displayed in a + * menu or not. + * @since 3.1 + */ + void setMenuAccelsEnabled( bool b ); + /// @since 3.1 + bool menuAccelsEnabled() const; + +public slots: + /** + * Sets the currently checked item. + * + * @param index Index of the item (remember the first item is zero). + */ + virtual void setCurrentItem( int index ); + + /** + * Sets the items to be displayed in this action + * You need to call this. + */ + virtual void setItems( const QStringList &lst ); + + /** + * Clears up all the items in this action + */ + virtual void clear(); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This makes the combo editable or read-only. + */ + virtual void setEditable( bool ); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This gives a _maximum_ size to the combobox. + * The minimum size is automatically given by the contents (the items). + */ + virtual void setComboWidth( int width ); + +protected: + virtual void changeItem( int id, int index, const QString& text ); + + /** + * Depending on the menuAccelsEnabled property this method will return the + * actions items in a way for inclusion in a combobox with the ampersand + * character removed from all items or not. + * @since 3.1 + */ + QStringList comboItems() const; + +protected slots: + virtual void slotActivated( int id ); + virtual void slotActivated( const QString &text ); + virtual void slotActivated(); + +signals: + void activated( int index ); + void activated( const QString& text ); + +protected: + virtual void updateCurrentItem( int id ); + + virtual void updateComboWidth( int id ); + + virtual void updateItems( int id ); + + virtual void updateClear( int id ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void setupMenu() const; + class KSelectActionPrivate; + KSelectActionPrivate *d; + +}; + +/// Remove this class in KDE-4.0. It doesn't add _anything_ to KSelectAction +/** + * @deprecated Use KSelectAction instead. + */ +class KListAction : public KSelectAction +{ + Q_OBJECT +public: + /** + * Constructs a list action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KListAction(); + + + virtual QString currentText() const; + virtual int currentItem() const; + + +public slots: + /** + * Sets the currently checked item. + * + * @param index Index of the item (remember the first item is zero). + */ + virtual void setCurrentItem( int index ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListActionPrivate; + KListActionPrivate *d; +}; + +/** + * This class is an action to handle a recent files submenu. + * The best way to create the action is to use KStdAction::openRecent. + * Then you simply need to call @ref loadEntries on startup, @ref saveEntries + * on shutdown, @ref addURL when your application loads/saves a file. + * + * @author Michael Koch + * @short Recent files action + */ +class KRecentFilesAction : public KListAction // TODO public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( uint maxItems READ maxItems WRITE setMaxItems ) +public: + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( QObject* parent = 0, const char* name = 0, + uint maxItems = 10 ); + + /** + * Destructor. + */ + virtual ~KRecentFilesAction(); + + /** + * Returns the maximum of items in the recent files list. + */ + uint maxItems() const; + +public slots: + /** + * Sets the maximum of items in the recent files list. + * The default for this value is 10 set in the constructor. + * + * If this value is lesser than the number of items currently + * in the recent files list the last items are deleted until + * the number of items are equal to the new maximum. + */ + void setMaxItems( uint maxItems ); + + /** + * Loads the recent files entries from a given KConfig object. + * You can provide the name of the group used to load the entries. + * If the groupname is empty, entries are load from a group called 'RecentFiles' + * + * This method does not effect the active group of KConfig. + */ + void loadEntries( KConfig* config, QString groupname=QString::null ); + + /** + * Saves the current recent files entries to a given KConfig object. + * You can provide the name of the group used to load the entries. + * If the groupname is empty, entries are saved to a group called 'RecentFiles' + * + * This method does not effect the active group of KConfig. + */ + void saveEntries( KConfig* config, QString groupname=QString::null ); + +public slots: + /** + * Add URL to recent files list. + * + * @param url The URL of the file + */ + void addURL( const KURL& url ); + + /** + * Remove an URL from the recent files list. + * + * @param url The URL of the file + */ + void removeURL( const KURL& url ); + + /** + * Removes all entries from the recent files list. + */ + void clearURLList(); + +signals: + + /** + * This signal gets emited when the user selects an URL. + * + * @param url The URL thats the user selected. + */ + void urlSelected( const KURL& url ); + +protected slots: + /** + * + */ + void itemSelected( const QString& string ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void init(); + + class KRecentFilesActionPrivate; + KRecentFilesActionPrivate *d; +}; + +class KFontAction : public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( QString font READ font WRITE setFont ) +public: + KFontAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + KFontAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + KFontAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + KFontAction( QObject* parent = 0, const char* name = 0 ); + ~KFontAction(); + + QString font() const { + return currentText(); + } + + int plug( QWidget*, int index = -1 ); + +public slots: + void setFont( const QString &family ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KFontActionPrivate; + KFontActionPrivate *d; +}; + +class KFontSizeAction : public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize ) +public: + KFontSizeAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + KFontSizeAction( const QString& text, const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0 ); + KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + KFontSizeAction( QObject* parent = 0, const char* name = 0 ); + + virtual ~KFontSizeAction(); + + virtual int fontSize() const; + +public slots: + virtual void setFontSize( int size ); + +protected slots: + virtual void slotActivated( int ); + virtual void slotActivated( const QString& ); + virtual void slotActivated() { KAction::slotActivated(); } + +signals: + void fontSizeChanged( int ); + +private: + void init(); + + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KFontSizeActionPrivate; + KFontSizeActionPrivate *d; +}; + + +/** + * A KActionMenu is an action that holds a sub-menu of other actions. + * insert() and remove() allow to insert and remove actions into this action-menu. + * Plugged in a popupmenu, it will create a submenu. + * Plugged in a toolbar, it will create a button with a popup menu. + * + * This is the action used by the XMLGUI since it holds other actions. + * If you want a submenu for selecting one tool among many (without icons), see KSelectAction. + * See also setDelayed about the main action. + */ +class KActionMenu : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool delayed READ delayed WRITE setDelayed ) + Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu ) + +public: + KActionMenu( const QString& text, QObject* parent = 0, + const char* name = 0 ); + KActionMenu( const QString& text, const QIconSet& icon, + QObject* parent = 0, const char* name = 0 ); + KActionMenu( const QString& text, const QString& icon, + QObject* parent = 0, const char* name = 0 ); + KActionMenu( QObject* parent = 0, const char* name = 0 ); + virtual ~KActionMenu(); + + virtual void insert( KAction*, int index = -1 ); + virtual void remove( KAction* ); + +//US KPopupMenu* popupMenu() const; + QPopupMenu* popupMenu() const; + void popup( const QPoint& global ); + + /** + * Returns true if this action creates a delayed popup menu + * when plugged in a KToolbar. + */ + bool delayed() const; + /** + * If set to true, this action will create a delayed popup menu + * when plugged in a KToolbar. Otherwise it creates a normal popup. + * Default: delayed + * + * Remember that if the "main" action (the toolbar button itself) + * cannot be clicked, then you should call setDelayed(false). + * + * On the opposite, if the main action can be clicked, it can only happen + * in a toolbar: in a menu, the parent of a submenu can't be activated. + * To get a "normal" menu item when plugged a menu (and no submenu) + * use KToolBarPopupAction. + */ + void setDelayed(bool _delayed); + + /** + * Returns true if this action creates a sticky popup menu. + * See @ref setStickyMenu. + */ + bool stickyMenu() const; + /** + * If set to true, this action will create a sticky popup menu + * when plugged in a KToolbar. + * "Sticky", means it's visible until a selection is made or the mouse is + * clicked elsewhere. This feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * Default: sticky. + */ + void setStickyMenu(bool sticky); + + virtual int plug( QWidget* widget, int index = -1 ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionMenuPrivate; + KActionMenuPrivate *d; +}; + +/** + * This action is a normal action everywhere, except in a toolbar + * where it also has a popupmenu (optionnally delayed). This action is designed + * for history actions (back/forward, undo/redo) and for any other action + * that has more detail in a toolbar than in a menu (e.g. tool chooser + * with "Other" leading to a dialog...). + */ +class KToolBarPopupAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool delayed READ delayed WRITE setDelayed ) + Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu ) + +public: + //Not all constructors - because we need an icon, since this action only makes + // sense when being plugged at least in a toolbar. + /** + * Create a KToolBarPopupAction, with a text, an icon, an optionnal accelerator, + * parent and name. + * + * @param text The text that will be displayed. + * @param icon The icon to display. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * Create a KToolBarPopupAction, with a text, an icon, an accelerator, + * a slot connected to the action, parent and name. + * + * If you do not want or have a keyboard accelerator, set the + * @p cut param to 0. + * + * @param text The text that will be displayed. + * @param icon The icon to display. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's owner. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent = 0, const char* name = 0 ); + + /** + * Create a KToolBarPopupAction, with a KGuiItem, an accelerator, + * a slot connected to the action, parent and name. The text and the + * icon are taken from the KGuiItem. + * + * If you do not want or have a keyboard accelerator, set the + * @p cut param to 0. + * + * @param item The text and icon that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's owner. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + + KToolBarPopupAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + virtual ~KToolBarPopupAction(); + + virtual int plug( QWidget *widget, int index = -1 ); + + /** + * The popup menu that is shown when clicking (some time) on the toolbar + * button. You may want to plug items into it on creation, or connect to + * aboutToShow for a more dynamic menu. + */ +//US KPopupMenu *popupMenu() const; + QPopupMenu *popupMenu() const; + + /** + * Returns true if this action creates a delayed popup menu + * when plugged in a KToolbar. + */ + bool delayed() const; + /** + * If set to true, this action will create a delayed popup menu + * when plugged in a KToolbar. Otherwise it creates a normal popup. + * Default: delayed. + */ + void setDelayed(bool delayed); + /** + * Returns true if this action creates a sticky popup menu. + * See @ref setStickyMenu. + */ + bool stickyMenu() const; + /** + * If set to true, this action will create a sticky popup menu + * when plugged in a KToolbar. + * "Sticky", means it's visible until a selection is made or the mouse is + * clicked elsewhere. This feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * Only available if delayed() is true. + * Default: sticky. + */ + void setStickyMenu(bool sticky); + +private: +//US KPopupMenu *m_popup; + QPopupMenu *m_popup; + bool m_delayed:1; + bool m_stickyMenu:1; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToolBarPopupActionPrivate; + KToolBarPopupActionPrivate *d; +}; + +/** + * An action that takes care of everything associated with + * showing or hiding a toolbar by a menu action. It will + * show or hide the toolbar with the given name when + * activated, and check or uncheck itself if the toolbar + * is manually shown or hidden. + * + * If you need to perfom some additional action when the + * toolbar is shown or hidden, connect to the toggled(bool) + * signal. It will be emitted after the toolbar's + * visibility has changed, whenever it changes. + * @since 3.1 + */ +class KToggleToolBarAction : public KToggleAction +{ + Q_OBJECT +public: + /** + * Create a KToggleToolbarAction that manages the toolbar + * named toolBarName. This can be either the name of a + * toolbar in an xml ui file, or a toolbar programmatically + * created with that name. + */ + KToggleToolBarAction( const char* toolBarName, const QString& text, + KActionCollection* parent, const char* name ); + KToggleToolBarAction( KToolBar *toolBar, const QString &text, + KActionCollection *parent, const char *name ); + virtual ~KToggleToolBarAction(); + + virtual int plug( QWidget*, int index = -1 ); + + KToolBar *toolBar() { + return m_toolBar; + } + +public slots: + virtual void setChecked( bool ); + +private: + QCString m_toolBarName; + QGuardedPtr<KToolBar> m_toolBar; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToggleToolBarActionPrivate; + KToggleToolBarActionPrivate *d; +}; + +/** + * An action that automatically embeds a widget into a + * toolbar. + */ +class KWidgetAction : public KAction +{ + Q_OBJECT +public: + /** + * Create an action that will embed widget into a toolbar + * when plugged. This action may only be plugged into + * a toolbar. + */ + KWidgetAction( QWidget* widget, const QString& text, + const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + virtual ~KWidgetAction(); + + /** + * Returns the widget associated with this action. + */ + QWidget* widget() { return m_widget; } + + void setAutoSized( bool ); + + /** + * Plug the action. The widget passed to the constructor + * will be reparented to w, which must inherit KToolBar. + */ + virtual int plug( QWidget* w, int index = -1 ); + /** + * Unplug the action. Ensures that the action is not + * destroyed. It will be hidden and reparented to 0L instead. + */ + virtual void unplug( QWidget *w ); +protected slots: + void slotToolbarDestroyed(); +private: + QGuardedPtr<QWidget> m_widget; + bool m_autoSized; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KWidgetActionPrivate; + KWidgetActionPrivate *d; +}; + +class KActionSeparator : public KAction +{ + Q_OBJECT +public: + KActionSeparator( QObject* parent = 0, const char* name = 0 ); + virtual ~KActionSeparator(); + + virtual int plug( QWidget*, int index = -1 ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionSeparatorPrivate; + KActionSeparatorPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kactioncollection.cpp b/microkde/kdeui/kactioncollection.cpp new file mode 100644 index 0000000..b819e76 --- a/dev/null +++ b/microkde/kdeui/kactioncollection.cpp @@ -0,0 +1,839 @@ +/* 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kactioncollection.h" +//US#include "kactionshortcutlist.h" + +#include <qptrdict.h> +//US#include <qvariant.h> + +//US#include <kaccel.h> +//US#include <kaccelbase.h> +//US#include <kapplication.h> +#include <kdebug.h> +//US#include <kxmlguifactory.h> + +//US I included the following files +#include <qasciidict.h> +#include <qptrlist.h> +#include "kaction.h" +#include <kglobal.h> +#include <qobject.h> +#include <qwidget.h> + +class KActionCollection::KActionCollectionPrivate +{ +public: + KActionCollectionPrivate() + { +//US m_instance = 0; + //m_bOneKAccelOnly = false; + //m_iWidgetCurrent = 0; + m_bAutoConnectShortcuts = true; + m_widget = 0; + m_kaccel = m_builderKAccel = 0; + m_dctHighlightContainers.setAutoDelete( true ); + m_highlight = false; + m_currentHighlightAction = 0; + m_statusCleared = true; + } + +//US KInstance *m_instance; +//US QString m_sXMLFile; + bool m_bAutoConnectShortcuts; + //bool m_bOneKAccelOnly; + //int m_iWidgetCurrent; + //QValueList<QWidget*> m_widgetList; + //QValueList<KAccel*> m_kaccelList; + QValueList<KActionCollection*> m_docList; + QWidget *m_widget; + KAccel *m_kaccel; + KAccel *m_builderKAccel; + + QAsciiDict<KAction> m_actionDict; + QPtrDict< QPtrList<KAction> > m_dctHighlightContainers; + bool m_highlight; + KAction *m_currentHighlightAction; + bool m_statusCleared; +}; + +KActionCollection::KActionCollection( QWidget *parent, const char *name /*US, + KInstance *instance */) + : QObject( (QObject*)parent, name ) +{ + kdDebug(129) << "KActionCollection::KActionCollection( " << parent << ", " << name << " ): this = " << this << endl; // ellis + d = new KActionCollectionPrivate; + if( parent ) + setWidget( parent ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + + +KActionCollection::KActionCollection( QWidget *watch, QObject* parent, const char *name /*US, + KInstance *instance */) + : QObject( parent, name ) +{ + kdDebug(129) << "KActionCollection::KActionCollection( " << watch << ", " << parent << ", " << name << " ): this = " << this << endl; //ellis + d = new KActionCollectionPrivate; + if( watch ) + setWidget( watch ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + +// KDE 4: remove +KActionCollection::KActionCollection( QObject *parent, const char *name /*US, + KInstance *instance */) + : QObject( parent, name ) +{ + kdWarning(129) << "KActionCollection::KActionCollection( QObject *parent, const char *name, KInstance *instance )" << endl; //ellis +//US kdBacktrace not available +//US kdDebug(129) << kdBacktrace() << endl; + d = new KActionCollectionPrivate; +//US QWidget* w = dynamic_cast<QWidget*>( parent ); + QWidget* w = (QWidget*)( parent ); + if( w ) + setWidget( w ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + +KActionCollection::KActionCollection( const KActionCollection © ) + : QObject() +{ + kdWarning(129) << "KActionCollection::KActionCollection( const KActionCollection & ): function is severely deprecated." << endl; + d = new KActionCollectionPrivate; + *this = copy; +} +// KDE 4: remove end + +KActionCollection::~KActionCollection() +{ + kdDebug(129) << "KActionCollection::~KActionCollection(): this = " << this << endl; + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + if ( pAction->m_parentCollection == this ) + pAction->m_parentCollection = 0L; + } + +//US delete d->m_kaccel; +//US delete d->m_builderKAccel; + delete d; d = 0; +} + +void KActionCollection::setWidget( QWidget* w ) +{ + //if ( d->m_actionDict.count() > 0 ) { + // kdError(129) << "KActionCollection::setWidget(): must be called before any actions are added to collection!" << endl; + // kdDebug(129) << kdBacktrace() << endl; + //} + //else + if ( !d->m_widget ) { + d->m_widget = w; + qDebug("KActionCollection::setWidget: warning: KAccel is never used in microkde"); +//US d->m_kaccel = new KAccel( w, this, "KActionCollection-KAccel" ); + } + else if ( d->m_widget != w ) + kdWarning(129) << "KActionCollection::setWidget(): tried to change widget from " << d->m_widget << " to " << w << endl; +} + +void KActionCollection::setAutoConnectShortcuts( bool b ) +{ + d->m_bAutoConnectShortcuts = b; +} + +bool KActionCollection::isAutoConnectShortcuts() +{ + return d->m_bAutoConnectShortcuts; +} + +bool KActionCollection::addDocCollection( KActionCollection* pDoc ) +{ + d->m_docList.append( pDoc ); + return true; +} + +void KActionCollection::beginXMLPlug( QWidget *widget ) +{ + qDebug("KActionCollection::beginXMLPlug has to be fixed"); +/*US + kdDebug(129) << "KActionCollection::beginXMLPlug( buildWidget = " << widget << " ): this = " << this << " d->m_builderKAccel = " << d->m_builderKAccel << endl; + + if( widget && !d->m_builderKAccel ) { + d->m_builderKAccel = new KAccel( widget, this, "KActionCollection-BuilderKAccel" ); + } +*/ +} + +void KActionCollection::endXMLPlug() +{ + kdDebug(129) << "KActionCollection::endXMLPlug(): this = " << this << endl; + //s_kaccelXML = 0; +} + +void KActionCollection::prepareXMLUnplug() +{ + qDebug("KActionCollection::prepareXMLUnplug has to be fixed"); +/*US + kdDebug(129) << "KActionCollection::prepareXMLUnplug(): this = " << this << endl; + unplugShortcuts( d->m_kaccel ); + + if( d->m_builderKAccel ) { + unplugShortcuts( d->m_builderKAccel ); + delete d->m_builderKAccel; + d->m_builderKAccel = 0; + } +*/ +} + +void KActionCollection::unplugShortcuts( KAccel* kaccel ) +{ + qDebug("KActionCollection::unplugShortcuts has to be fixed"); +/*US + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + pAction->removeKAccel( kaccel ); + } + + for( uint i = 0; i < d->m_docList.count(); i++ ) + d->m_docList[i]->unplugShortcuts( kaccel ); +*/ + +} + +/*void KActionCollection::addWidget( QWidget* w ) +{ + if( !d->m_bOneKAccelOnly ) { + kdDebug(129) << "KActionCollection::addWidget( " << w << " ): this = " << this << endl; + for( uint i = 0; i < d->m_widgetList.count(); i++ ) { + if( d->m_widgetList[i] == w ) { + d->m_iWidgetCurrent = i; + return; + } + } + d->m_iWidgetCurrent = d->m_widgetList.count(); + d->m_widgetList.append( w ); + d->m_kaccelList.append( new KAccel( w, this, "KActionCollection-KAccel" ) ); + } +} + +void KActionCollection::removeWidget( QWidget* w ) +{ + if( !d->m_bOneKAccelOnly ) { + kdDebug(129) << "KActionCollection::removeWidget( " << w << " ): this = " << this << endl; + for( uint i = 0; i < d->m_widgetList.count(); i++ ) { + if( d->m_widgetList[i] == w ) { + // Remove KAccel object from children. + KAccel* pKAccel = d->m_kaccelList[i]; + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + if ( pAction->m_parentCollection == this ) { + pAction->removeKAccel( pKAccel ); + } + } + delete pKAccel; + + d->m_widgetList.remove( d->m_widgetList.at( i ) ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + + if( d->m_iWidgetCurrent == (int)i ) + d->m_iWidgetCurrent = -1; + else if( d->m_iWidgetCurrent > (int)i ) + d->m_iWidgetCurrent--; + return; + } + } + kdWarning(129) << "KActionCollection::removeWidget( " << w << " ): widget not in list." << endl; + } +} + +bool KActionCollection::ownsKAccel() const +{ + return d->m_bOneKAccelOnly; +} + +uint KActionCollection::widgetCount() const +{ + return d->m_widgetList.count(); +} + +const KAccel* KActionCollection::widgetKAccel( uint i ) const +{ + return d->m_kaccelList[i]; +}*/ + +//US we are using no accelerators so far. So just setup an empty implementation. +KAccel* KActionCollection::kaccel() +{ + //if( d->m_kaccelList.count() > 0 ) + // return d->m_kaccelList[d->m_iWidgetCurrent]; + //else + // return 0; +//US return d->m_kaccel; + return 0; +} + +//US we are using no accelerators so far. So just setup an empty implementation. +const KAccel* KActionCollection::kaccel() const +{ + //if( d->m_kaccelList.count() > 0 ) + // return d->m_kaccelList[d->m_iWidgetCurrent]; + //else + // return 0; + //USreturn d->m_kaccel; + return 0; +} + +/*void KActionCollection::findMainWindow( QWidget *w ) +{ + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + while ( tl->parentWidget() ) // lookup parent and store + tl = tl->parentWidget(); + + KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + if (mw) + d->m_mainwindow = mw; + else + kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl; +}*/ + +void KActionCollection::_insert( KAction* action ) +{ + char unnamed_name[100]; + const char *name = action->name(); + if( qstrcmp( name, "unnamed" ) == 0 ) + { + sprintf(unnamed_name, "unnamed-%p", (void *)action); + name = unnamed_name; + } + KAction *a = d->m_actionDict[ name ]; + if ( a == action ) + return; + + d->m_actionDict.insert( name, action ); + + emit inserted( action ); +} + +void KActionCollection::_remove( KAction* action ) +{ + delete _take( action ); +} + +KAction* KActionCollection::_take( KAction* action ) +{ + char unnamed_name[100]; + const char *name = action->name(); + if( qstrcmp( name, "unnamed" ) == 0 ) + { + sprintf(unnamed_name, "unnamed-%p", (void *) action); + name = unnamed_name; + } + + KAction *a = d->m_actionDict.take( name ); + if ( !a || a != action ) + return 0; + + emit removed( action ); + return a; +} + +void KActionCollection::_clear() +{ + QAsciiDictIterator<KAction> it( d->m_actionDict ); + while ( it.current() ) + _remove( it.current() ); +} + +void KActionCollection::insert( KAction* action ) { _insert( action ); } +void KActionCollection::remove( KAction* action ) { _remove( action ); } +KAction* KActionCollection::take( KAction* action ) { return _take( action ); } +void KActionCollection::clear() { _clear(); } +KAccel* KActionCollection::accel() { return kaccel(); } +const KAccel* KActionCollection::accel() const { return kaccel(); } +KAccel* KActionCollection::builderKAccel() const { return d->m_builderKAccel; } + +KAction* KActionCollection::action( const char* name, const char* classname ) const +{ + KAction* pAction = 0; + + if ( !classname && name ) + pAction = d->m_actionDict[ name ]; + + else { + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + { + if ( ( !name || strcmp( it.current()->name(), name ) == 0 ) && + ( !classname || strcmp( it.current()->className(), classname ) == 0 ) ) { + pAction = it.current(); + break; + } + } + } + + if( !pAction ) { + for( uint i = 0; i < d->m_docList.count() && !pAction; i++ ) + pAction = d->m_docList[i]->action( name, classname ); + } + + return pAction; +} + +KAction* KActionCollection::action( int index ) const +{ + QAsciiDictIterator<KAction> it( d->m_actionDict ); + it += index; + return it.current(); +// return d->m_actions.at( index ); +} +/*US +bool KActionCollection::readShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) +{ + return KActionShortcutList(this).readSettings( sConfigGroup, pConfig ); +} + +bool KActionCollection::writeShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) const +{ + return KActionShortcutList((KActionCollection*)this).writeSettings( sConfigGroup, pConfig ); +} +*/ +uint KActionCollection::count() const +{ + return d->m_actionDict.count(); +} + +QStringList KActionCollection::groups() const +{ + QStringList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + if ( !it.current()->group().isEmpty() && !lst.contains( it.current()->group() ) ) + lst.append( it.current()->group() ); + + return lst; +} + +KActionPtrList KActionCollection::actions( const QString& group ) const +{ + KActionPtrList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + if ( it.current()->group() == group ) + lst.append( it.current() ); + else if ( it.current()->group().isEmpty() && group.isEmpty() ) + lst.append( it.current() ); + + return lst; +} + +KActionPtrList KActionCollection::actions() const +{ + KActionPtrList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + lst.append( it.current() ); + + return lst; +} + +/*US we have no instance object. Use KGlobal instead +void KActionCollection::setInstance( KInstance *instance ) +{ + if ( instance ) + d->m_instance = instance; +qDebug("KActionCollection::setInstance has to be fixed"); + else + d->m_instance = KGlobal::instance(); +} + +KInstance *KActionCollection::instance() const +{ + return d->m_instance; +} +*/ + +/*US we have no XML facility in microkde +void KActionCollection::setXMLFile( const QString& sXMLFile ) +{ + d->m_sXMLFile = sXMLFile; +} + +const QString& KActionCollection::xmlFile() const +{ + return d->m_sXMLFile; +} +*/ + +void KActionCollection::setHighlightingEnabled( bool enable ) +{ + d->m_highlight = enable; +} + +bool KActionCollection::highlightingEnabled() const +{ + return d->m_highlight; +} + +void KActionCollection::connectHighlight( QWidget *container, KAction *action ) +{ + if ( !d->m_highlight ) + return; + + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ]; + + if ( !actionList ) + { + actionList = new QPtrList<KAction>; + + if ( container->inherits( "QPopupMenu" ) ) + { + connect( container, SIGNAL( highlighted( int ) ), + this, SLOT( slotMenuItemHighlighted( int ) ) ); + connect( container, SIGNAL( aboutToHide() ), + this, SLOT( slotMenuAboutToHide() ) ); + } +//US else if ( container->inherits( "KToolBar" ) ) + else if ( container->inherits( "QToolBar" ) ) + { + connect( container, SIGNAL( highlighted( int, bool ) ), + this, SLOT( slotToolBarButtonHighlighted( int, bool ) ) ); + } + + connect( container, SIGNAL( destroyed() ), + this, SLOT( slotDestroyed() ) ); + + d->m_dctHighlightContainers.insert( container, actionList ); + } + + actionList->append( action ); +} + +void KActionCollection::disconnectHighlight( QWidget *container, KAction *action ) +{ + if ( !d->m_highlight ) + return; + + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ]; + + if ( !actionList ) + return; + + actionList->removeRef( action ); + + if ( actionList->count() == 0 ) + d->m_dctHighlightContainers.remove( container ); +} + +void KActionCollection::slotMenuItemHighlighted( int id ) +{ + if ( !d->m_highlight ) + return; + + if ( d->m_currentHighlightAction ) + emit actionHighlighted( d->m_currentHighlightAction, false ); + + QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) ); + + d->m_currentHighlightAction = findAction( container, id ); + + if ( !d->m_currentHighlightAction ) + { + if ( !d->m_statusCleared ) + emit clearStatusText(); + d->m_statusCleared = true; + return; + } + + d->m_statusCleared = false; + emit actionHighlighted( d->m_currentHighlightAction ); + emit actionHighlighted( d->m_currentHighlightAction, true ); + emit actionStatusText( d->m_currentHighlightAction->toolTip() ); +} + +void KActionCollection::slotMenuAboutToHide() +{ + if ( d->m_currentHighlightAction ) + emit actionHighlighted( d->m_currentHighlightAction, false ); + d->m_currentHighlightAction = 0; + + if ( !d->m_statusCleared ) + emit clearStatusText(); + d->m_statusCleared = true; +} + +void KActionCollection::slotToolBarButtonHighlighted( int id, bool highlight ) +{ + if ( !d->m_highlight ) + return; + + QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) ); + + KAction *action = findAction( container, id ); + + if ( !action ) + { + d->m_currentHighlightAction = 0; + // use tooltip groups for toolbar status text stuff instead (Simon) +// emit clearStatusText(); + return; + } + + emit actionHighlighted( action, highlight ); + + if ( highlight ) + d->m_currentHighlightAction = action; + else + { + d->m_currentHighlightAction = 0; +// emit clearStatusText(); + } +} + +void KActionCollection::slotDestroyed() +{ + d->m_dctHighlightContainers.remove( reinterpret_cast<void *>( const_cast<QObject *>(sender()) ) ); +} + +KAction *KActionCollection::findAction( QWidget *container, int id ) +{ + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ reinterpret_cast<void *>( container ) ]; + + if ( !actionList ) + return 0; + + QPtrListIterator<KAction> it( *actionList ); + for (; it.current(); ++it ) + if ( it.current()->isPlugged( container, id ) ) + return it.current(); + + return 0; +} + +// KDE 4: remove +KActionCollection KActionCollection::operator+(const KActionCollection &c ) const +{ + kdWarning(129) << "KActionCollection::operator+(): function is severely deprecated." << endl; + KActionCollection ret( *this ); + + QValueList<KAction *> actions = c.actions(); + QValueList<KAction *>::ConstIterator it = actions.begin(); + QValueList<KAction *>::ConstIterator end = actions.end(); + for (; it != end; ++it ) + ret.insert( *it ); + + return ret; +} + +KActionCollection &KActionCollection::operator=( const KActionCollection © ) +{ + kdWarning(129) << "KActionCollection::operator=(): function is severely deprecated." << endl; + //d->m_bOneKAccelOnly = copy.d->m_bOneKAccelOnly; + //d->m_iWidgetCurrent = copy.d->m_iWidgetCurrent; + //d->m_widgetList = copy.d->m_widgetList; + //d->m_kaccelList = copy.d->m_kaccelList; + d->m_widget = copy.d->m_widget; + d->m_kaccel = copy.d->m_kaccel; + d->m_actionDict = copy.d->m_actionDict; +//US setInstance( copy.instance() ); + return *this; +} + +KActionCollection &KActionCollection::operator+=( const KActionCollection &c ) +{ + kdWarning(129) << "KActionCollection::operator+=(): function is severely deprecated." << endl; + QAsciiDictIterator<KAction> it(c.d->m_actionDict); + for ( ; it.current(); ++it ) + insert( it.current() ); + + return *this; +} +// KDE 4: remove end + +//--------------------------------------------------------------------- +// KActionShortcutList +//--------------------------------------------------------------------- +/*US +KActionShortcutList::KActionShortcutList( KActionCollection* pColl ) +: m_actions( *pColl ) + { } +KActionShortcutList::~KActionShortcutList() + { } +uint KActionShortcutList::count() const + { return m_actions.count(); } +QString KActionShortcutList::name( uint i ) const + { return m_actions.action(i)->name(); } +QString KActionShortcutList::label( uint i ) const + { return m_actions.action(i)->text(); } +QString KActionShortcutList::whatsThis( uint i ) const + { return m_actions.action(i)->whatsThis(); } +const KShortcut& KActionShortcutList::shortcut( uint i ) const + { return m_actions.action(i)->shortcut(); } +const KShortcut& KActionShortcutList::shortcutDefault( uint i ) const + { return m_actions.action(i)->shortcutDefault(); } +bool KActionShortcutList::isConfigurable( uint i ) const + { return m_actions.action(i)->isShortcutConfigurable(); } +bool KActionShortcutList::setShortcut( uint i, const KShortcut& cut ) + { return m_actions.action(i)->setShortcut( cut ); } +const KInstance* KActionShortcutList::instance() const + { return m_actions.instance(); } +QVariant KActionShortcutList::getOther( Other, uint ) const + { return QVariant(); } +bool KActionShortcutList::setOther( Other, uint, QVariant ) + { return false; } + +bool KActionShortcutList::save() const +{ + kdDebug(129) << "KActionShortcutList::save(): xmlFile = " << m_actions.xmlFile() << endl; + + if( m_actions.xmlFile().isEmpty() ) + return writeSettings(); + + QString tagActionProp = QString::fromLatin1("ActionProperties"); + QString tagAction = QString::fromLatin1("Action"); + QString attrName = QString::fromLatin1("name"); + QString attrShortcut = QString::fromLatin1("shortcut"); + QString attrAccel = QString::fromLatin1("accel"); // Depricated attribute + + // Read XML file + QString sXml( KXMLGUIFactory::readConfigFile( m_actions.xmlFile(), false, instance() ) ); + QDomDocument doc; + doc.setContent( sXml ); + + // Process XML data + + // first, lets see if we have existing properties + QDomElement elem; + QDomElement it = doc.documentElement(); + // KXMLGUIFactory::removeDOMComments( it ); <-- What was this for? --ellis + it = it.firstChild().toElement(); + for( ; !it.isNull(); it = it.nextSibling().toElement() ) { + if( it.tagName() == tagActionProp ) { + elem = it; + break; + } + } + + // if there was none, create one + if( elem.isNull() ) { + elem = doc.createElement( tagActionProp ); + doc.documentElement().appendChild( elem ); + } + + // now, iterate through our actions + uint nSize = count(); + for( uint i = 0; i < nSize; i++ ) { + const QString& sName = name(i); + + bool bSameAsDefault = (shortcut(i) == shortcutDefault(i)); + //kdDebug(129) << "name = " << sName << " shortcut = " << shortcut(i).toStringInternal() << " def = " << shortcutDefault(i).toStringInternal() << endl; + + // now see if this element already exists + QDomElement act_elem; + for( it = elem.firstChild().toElement(); !it.isNull(); it = it.nextSibling().toElement() ) { + if( it.attribute( attrName ) == sName ) { + act_elem = it; + break; + } + } + + // nope, create a new one + if( act_elem.isNull() ) { + if( bSameAsDefault ) + continue; + //kdDebug(129) << "\tnode doesn't exist." << endl; + act_elem = doc.createElement( tagAction ); + act_elem.setAttribute( attrName, sName ); + } + + act_elem.removeAttribute( attrAccel ); + if( bSameAsDefault ) { + act_elem.removeAttribute( attrShortcut ); + //kdDebug(129) << "act_elem.attributes().count() = " << act_elem.attributes().count() << endl; + if( act_elem.attributes().count() == 1 ) + elem.removeChild( act_elem ); + } else { + act_elem.setAttribute( attrShortcut, shortcut(i).toStringInternal() ); + elem.appendChild( act_elem ); + } + } + + // Write back to XML file + return KXMLGUIFactory::saveConfigFile( doc, m_actions.xmlFile(), instance() ); +} + +//--------------------------------------------------------------------- +// KActionPtrShortcutList +//--------------------------------------------------------------------- + +KActionPtrShortcutList::KActionPtrShortcutList( KActionPtrList& list ) +: m_actions( list ) + { } +KActionPtrShortcutList::~KActionPtrShortcutList() + { } +uint KActionPtrShortcutList::count() const + { return m_actions.count(); } +QString KActionPtrShortcutList::name( uint i ) const + { return m_actions[i]->name(); } +QString KActionPtrShortcutList::label( uint i ) const + { return m_actions[i]->text(); } +QString KActionPtrShortcutList::whatsThis( uint i ) const + { return m_actions[i]->whatsThis(); } +const KShortcut& KActionPtrShortcutList::shortcut( uint i ) const + { return m_actions[i]->shortcut(); } +const KShortcut& KActionPtrShortcutList::shortcutDefault( uint i ) const + { return m_actions[i]->shortcutDefault(); } +bool KActionPtrShortcutList::isConfigurable( uint i ) const + { return m_actions[i]->isShortcutConfigurable(); } +bool KActionPtrShortcutList::setShortcut( uint i, const KShortcut& cut ) + { return m_actions[i]->setShortcut( cut ); } +QVariant KActionPtrShortcutList::getOther( Other, uint ) const + { return QVariant(); } +bool KActionPtrShortcutList::setOther( Other, uint, QVariant ) + { return false; } +bool KActionPtrShortcutList::save() const + { return false; } + +void KActionShortcutList::virtual_hook( int id, void* data ) +{ KShortcutList::virtual_hook( id, data ); } + +void KActionPtrShortcutList::virtual_hook( int id, void* data ) +{ KShortcutList::virtual_hook( id, data ); } +*/ + +void KActionCollection::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +/*US +#include "kactioncollection.moc" +*/ diff --git a/microkde/kdeui/kactioncollection.h b/microkde/kdeui/kactioncollection.h new file mode 100644 index 0000000..b9466d0 --- a/dev/null +++ b/microkde/kdeui/kactioncollection.h @@ -0,0 +1,329 @@ +/* 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> + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kactioncollection_h__ +#define __kactioncollection_h__ + +#include <kaction.h> + +//US #include <qkeysequence.h> +#include <qobject.h> +//US#include <qvaluelist.h> +//US#include <qguardedptr.h> +//US #include <kguiitem.h> +//US#include <kshortcut.h> +//US#include <kstdaction.h> +//US#include <kicontheme.h> + +//USclass QMenuBar; +//USclass QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +//USclass QIconSet; +//USclass QString; +//USclass KToolBar; + +//USclass KAccel; +//USclass KAccelActions; +//USclass KConfig; +//USclass KConfigBase; +//USclass KURL; +//USclass KInstance; +//USclass KToolBar; +//USclass KActionCollection; +//USclass KPopupMenu; +//USclass KMainWindow; + +//US added inclidefiles +class QWidget; + + +typedef QValueList<KAction *> KActionPtrList; + +/** + * A managed set of KAction objects. + */ +class KActionCollection : public QObject +{ + friend class KAction; + friend class KXMLGUIClient; + + Q_OBJECT +public: + KActionCollection( QWidget *parent, const char *name = 0/*US , KInstance *instance = 0 */); + /** + * Use this constructor if you want the collection's actions to restrict + * their accelerator keys to @p watch rather than the @p parent. If + * you don't require shortcuts, you can pass a null to the @p watch parameter. + */ + KActionCollection( QWidget *watch, QObject* parent, const char *name = 0/*US, KInstance *instance = 0 */); + KActionCollection( const KActionCollection © ); + virtual ~KActionCollection(); + + /** + * This sets the widget to which the keyboard shortcuts should be attached. + * You only need to call this if a null pointer was passed in the constructor. + */ + virtual void setWidget( QWidget *widget ); + + /** + * This indicates whether new actions which are created in this collection + * should have their keyboard shortcuts automatically connected on + * construction. Set to 'false' if you will be loading XML-based settings. + * This is automatically done by KParts. The default is 'true'. + * @see isAutoConnectShortcuts() + */ + void setAutoConnectShortcuts( bool ); + + /** + * This indicates whether new actions which are created in this collection + * have their keyboard shortcuts automatically connected on + * construction. + * @see setAutoConnectShortcuts() + */ + bool isAutoConnectShortcuts(); + + /** + * This sets the default shortcut scope for new actions created in this + * collection. The default is ScopeUnspecified. Ideally the default + * would have been ScopeWidget, but that would cause some backwards + * compatibility problems. + */ + //void setDefaultScope( KAction::Scope ); + + /** + * Doc/View model. This lets you add the action collection of a document + * to a view's action collection. + */ + bool addDocCollection( KActionCollection* pDoc ); + + /** Returns the number of widgets which this collection is associated with. */ + //uint widgetCount() const; + + /** + * Returns true if the collection has its own KAccel object. This will be + * the case if it was constructed with a valid widget ptr or if setWidget() + * was called. + */ + //bool ownsKAccel() const; + + /** @deprecated Deprecated because of ambiguous name. Use kaccel() */ + virtual KAccel* accel(); + /** @deprecated Deprecated because of ambiguous name. Use kaccel() */ + virtual const KAccel* accel() const; + + /** Returns the KAccel object of the most recently set widget. */ + KAccel* kaccel(); + /** Returns the KAccel object of the most recently set widget. Const version for convenience. */ + const KAccel* kaccel() const; + + /** @internal, for KAction::kaccelCurrent() */ + KAccel* builderKAccel() const; + /** Returns the KAccel object associated with widget #. */ + //KAccel* widgetKAccel( uint i ); + //const KAccel* widgetKAccel( uint i ) const; + + /** Returns the number of actions in the collection */ + virtual uint count() const; + bool isEmpty() const { return count() == 0; } + /** + * Return the KAction* at position "index" in the action collection. + * @see count() + */ + virtual KAction* action( int index ) const; + /** + * Find an action (optionally, of a given subclass of KAction) in the action collection. + * @param name Name of the KAction. + * @param classname Name of the KAction subclass. + * @return A pointer to the first KAction in the collection which matches the parameters or + * null if nothing matches. + */ + virtual KAction* action( const char* name, const char* classname = 0 ) const; + + /** Returns a list of all the groups of all the KActions in this action collection. + * @see KAction::group() + * @see KAction::setGroup() + */ + virtual QStringList groups() const; + /** + * Returns the list of actions in a particular managed by this action collection. + * @param group The name of the group. + */ + virtual KActionPtrList actions( const QString& group ) const; + /** Returns the list of actions managed by this action collection. */ + virtual KActionPtrList actions() const; + + /** + * Used for reading shortcut configuration from a non-XML rc file. + */ +//US bool readShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ); + /** + * Used for writing shortcut configuration to a non-XML rc file. + */ +//US bool writeShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ) const; + +//US void setInstance( KInstance *instance ); + /** The instance with which this class is associated. */ +//US KInstance *instance() const; + + /** + * Use this to tell the KActionCollection what rc file its configuration + * is stored in. + */ + void setXMLFile( const QString& ); + /** The rc file in which the current configuration is stored. */ + const QString& xmlFile() const; + + /** + * Enable highlighting notification for specific KActions. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see actionHighlighted() + * @see highlightingEnabled() + */ + void setHighlightingEnabled( bool enable ); + /** + * Return whether highlighting notifications are enabled. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see actionHighlighted() + */ + bool highlightingEnabled() const; + + /** + * Call this function if you want to receive a signal whenever a KAction is highlighted in a menu or a toolbar. + * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar) + * @param action The action you are interested in + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + * @see actionHighlighted() + */ + void connectHighlight( QWidget *container, KAction *action ); + /** + * Disconnect highlight notifications for a particular pair of contianer and action. + * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar) + * @param action The action you are interested in + * @see connectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + * @see actionHighlighted() + */ + void disconnectHighlight( QWidget *container, KAction *action ); + +signals: + void inserted( KAction* ); + void removed( KAction* ); + + /** Emitted when "action" is highlighted. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + */ + void actionHighlighted( KAction *action ); + /** Emitted when "action" is highlighed or loses highlighting. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + */ + void actionHighlighted( KAction *action, bool highlight ); + + void actionStatusText( const QString &text ); + void clearStatusText(); + +private: + /** + * @internal Only to be called by KXMLGUIFactory::addClient(). + * When actions are being connected, KAction needs to know what + * widget it should connect widget-scope actions to, and what + * main window it should connect + */ + void beginXMLPlug( QWidget *widget ); + void endXMLPlug(); + /** @internal. Only to be called by KXMLGUIFactory::removeClient() */ + void prepareXMLUnplug(); + void unplugShortcuts( KAccel* kaccel ); + + void _clear(); + void _insert( KAction* ); + void _remove( KAction* ); + KAction* _take( KAction* ); + +private slots: + void slotMenuItemHighlighted( int id ); + void slotToolBarButtonHighlighted( int id, bool highlight ); + void slotMenuAboutToHide(); + void slotDestroyed(); + +private: + KAction *findAction( QWidget *container, int id ); + +#ifndef KDE_NO_COMPAT +public: + KActionCollection( QObject *parent, const char *name = 0 /*US, KInstance *instance = 0 */); + + void insert( KAction* ); + + /** + * @deprecated Removes an action from the collection and deletes it. + * @param action The KAction to remove. + */ + void remove( KAction* action ); + + /** + * @deprecated Removes an action from the collection. + * @return NULL if not found else returns action. + * @param action the KAction to remove. + */ + KAction* take( KAction* action ); + + KActionCollection operator+ ( const KActionCollection& ) const; + KActionCollection& operator= ( const KActionCollection& ); + KActionCollection& operator+= ( const KActionCollection& ); + +public slots: + /** + * Clears the entire actionCollection, deleting all actions. + * @see #remove + */ + void clear(); +#endif // !KDE_NO_COMPAT +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionCollectionPrivate; + KActionCollectionPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kbuttonbox.cpp b/microkde/kdeui/kbuttonbox.cpp new file mode 100644 index 0000000..16206e8 --- a/dev/null +++ b/microkde/kdeui/kbuttonbox.cpp @@ -0,0 +1,300 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * KButtonBox class + * + * A container widget for buttons. Uses Qt layout control to place the + * buttons, can handle both vertical and horizontal button placement. +* + * HISTORY + * + * 03/08/2000 Mario Weilguni <mweilguni@kde.org> + * Removed all those long outdated Motif stuff + * Improved and clarified some if conditions (easier to understand) + * + * 11/13/98 Reginald Stadlbauer <reggie@kde.org> + * Now in Qt 1.4x motif default buttons have no extra width/height anymore. + * So the KButtonBox doesn't add this width/height to default buttons anymore + * which makes the buttons look better. + * + * 01/17/98 Mario Weilguni <mweilguni@sime.com> + * Fixed a bug in sizeHint() + * Improved the handling of Motif default buttons + * + * 01/09/98 Mario Weilguni <mweilguni@sime.com> + * The last button was to far right away from the right/bottom border. + * Fixed this. Removed old code. Buttons get now a minimum width. + * Programmer may now override minimum width and height of a button. + * + */ + +//US #include "kbuttonbox.moc" + +#include <kbuttonbox.h> +#include <qpushbutton.h> +#include <qptrlist.h> +#include <assert.h> + +#define minButtonWidth 50 + +class KButtonBox::Item { +public: + QPushButton *button; + bool noexpand; + unsigned short stretch; + unsigned short actual_size; +}; + +template class QPtrList<KButtonBox::Item>; + +class KButtonBoxPrivate { +public: + unsigned short border; + unsigned short autoborder; + unsigned short orientation; + bool activated; + QPtrList<KButtonBox::Item> buttons; +}; + +KButtonBox::KButtonBox(QWidget *parent, Orientation _orientation, + int border, int autoborder) + : QWidget(parent) +{ + data = new KButtonBoxPrivate; + assert(data != 0); + + data->orientation = _orientation; + data->border = border; + data->autoborder = autoborder < 0 ? border : autoborder; + data->buttons.setAutoDelete(TRUE); +} + +KButtonBox::~KButtonBox() { + delete data; +} + +QPushButton *KButtonBox::addButton(const QString& text, bool noexpand) { + Item *item = new Item; + + item->button = new QPushButton(text, this); + item->noexpand = noexpand; + data->buttons.append(item); + item->button->adjustSize(); + + return item->button; +} + + QPushButton * +KButtonBox::addButton( + const QString & text, + QObject * receiver, + const char * slot, + bool noexpand +) +{ + QPushButton * pb = addButton(text, noexpand); + + if ((0 != receiver) && (0 != slot)) + QObject::connect(pb, SIGNAL(clicked()), receiver, slot); + + return pb; +} + + +void KButtonBox::addStretch(int scale) { + if(scale > 0) { + Item *item = new Item; + item->button = 0; + item->noexpand = FALSE; + item->stretch = scale; + data->buttons.append(item); + } +} + +void KButtonBox::layout() { + // resize all buttons + QSize bs = bestButtonSize(); + + for(unsigned int i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + QPushButton *b = item->button; + if(b != 0) { + if(item->noexpand) + b->setFixedSize(buttonSizeHint(b)); + else + b->setFixedSize(bs); + } + } + + setMinimumSize(sizeHint()); +} + +void KButtonBox::placeButtons() { + unsigned int i; + + if(data->orientation == Horizontal) { + // calculate free size and stretches + int fs = width() - 2 * data->border; + int stretch = 0; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + fs -= item->button->width(); + + // Last button? + if(i != data->buttons.count() - 1) + fs -= data->autoborder; + } else + stretch +=item->stretch; + } + + // distribute buttons + int x_pos = data->border; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + QPushButton *b = item->button; + b->move(x_pos, (height() - b->height()) / 2); + + x_pos += b->width() + data->autoborder; + } else + x_pos += (int)((((double)fs) * item->stretch) / stretch); + } + } else { // VERTICAL + // calcualte free size and stretches + int fs = height() - 2 * data->border; + int stretch = 0; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) + fs -= item->button->height() + data->autoborder; + else + stretch +=item->stretch; + } + + // distribute buttons + int y_pos = data->border; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + QPushButton *b = item->button; + b->move((width() - b->width()) / 2, y_pos); + + y_pos += b->height() + data->autoborder; + } else + y_pos += (int)((((double)fs) * item->stretch) / stretch); + } + } +} + +void KButtonBox::resizeEvent(QResizeEvent *) { + placeButtons(); +} + +QSize KButtonBox::bestButtonSize() const { + QSize s(0, 0); + unsigned int i; + + // calculate optimal size + for(i = 0; i < data->buttons.count(); i++) { + KButtonBox *that = (KButtonBox*)this; // to remove the const ;( + Item *item = that->data->buttons.at(i); + QPushButton *b = item->button; + + if(b != 0 && !item->noexpand) { + QSize bs = buttonSizeHint(b); + + if(bs.width() > s.width()) + s.setWidth(bs.width()); + if(bs.height() > s.height()) + s.setHeight(bs.height()); + } + } + + return s; +} + +QSize KButtonBox::sizeHint() const { + unsigned int i, dw; + + if(data->buttons.count() == 0) + return QSize(0, 0); + else { + dw = 2 * data->border; + + QSize bs = bestButtonSize(); + for(i = 0; i < data->buttons.count(); i++) { + KButtonBox *that = (KButtonBox*)this; + Item *item = that->data->buttons.at(i); + QPushButton *b = item->button; + if(b != 0) { + QSize s; + if(item->noexpand) + s = that->buttonSizeHint(b); + else + s = bs; + + if(data->orientation == Horizontal) + dw += s.width(); + else + dw += s.height(); + + if( i != data->buttons.count() - 1 ) + dw += data->autoborder; + } + } + + if(data->orientation == Horizontal) + return QSize(dw, bs.height() + 2 * data->border); + else + return QSize(bs.width() + 2 * data->border, dw); + } +} + +QSizePolicy KButtonBox::sizePolicy() const +{ + return data->orientation == Horizontal? + QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) : + QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ); +} + +/* + * Returns the best size for a button. If a button is less than + * minButtonWidth pixels wide, return minButtonWidth pixels + * as minimum width + */ +QSize KButtonBox::buttonSizeHint(QPushButton *b) const { + QSize s = b->sizeHint(); + QSize ms = b->minimumSize(); + if(s.width() < minButtonWidth) + s.setWidth(minButtonWidth); + + // allows the programmer to override the settings + if(ms.width() > s.width()) + s.setWidth(ms.width()); + if(ms.height() > s.height()) + s.setHeight(ms.height()); + + return s; +} + +void KButtonBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdeui/kbuttonbox.h b/microkde/kdeui/kbuttonbox.h new file mode 100644 index 0000000..1104366 --- a/dev/null +++ b/microkde/kdeui/kbuttonbox.h @@ -0,0 +1,139 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __KBUTTONBOX__H__ +#define __KBUTTONBOX__H__ + +#include <qwidget.h> +class QPushButton; + +class KButtonBoxPrivate; +/** + * Container widget for buttons. + * + * This class uses Qt layout control to place the buttons; can handle + * both vertical and horizontal button placement. The default border + * is now @p 0 (making it easier to deal with layouts). The space + * between buttons is now more Motif compliant. + * + * @author Mario Weilguni <mweilguni@sime.com> + * @version $Id$ + **/ + +class KButtonBox : public QWidget +{ + Q_OBJECT + +public: + /** + * Create an empty container for buttons. + * + * If @p _orientation is @p Vertical, the buttons inserted with + * @ref addButton() are laid out from top to bottom, otherwise they + * are laid out from left to right. + */ + KButtonBox(QWidget *parent, Orientation _orientation = Horizontal, + int border = 0, int _autoborder = 6); + + /** + * Free private data field + */ + ~KButtonBox(); + + /** + * @return The minimum size needed to fit all buttons. + * + * This size is + * calculated by the width/height of all buttons plus border/autoborder. + */ + virtual QSize sizeHint() const; + /** + * @reimplemented + */ + virtual QSizePolicy sizePolicy() const; + /** + * @reimplemented + */ + virtual void resizeEvent(QResizeEvent *); + + /** + * Add a new @ref QPushButton. + * + * @param noexpand If @p noexpand is @p false, the width + * of the button is adjusted to fit the other buttons (the maximum + * of all buttons is taken). If @p noexpand is @p true, the width of this + * button will be set to the minimum width needed for the given text). + * + * @return A pointer to the new button. + */ + QPushButton *addButton(const QString& text, bool noexpand = FALSE); + + /** + * Add a new @ref QPushButton. + * + * @param receiver An object to connect to. + * @param slot A Qt slot to connect the 'clicked()' signal to. + * @param noexpand If @p noexpand is @p false, the width + * of the button is adjusted to fit the other buttons (the maximum + * of all buttons is taken). If @p noexpand @p true, the width of this + * button will be set to the minimum width needed for the given text). + * + * @return A pointer to the new button. + */ + QPushButton *addButton(const QString& text, QObject * receiver, const char * slot, bool noexpand = FALSE); + + /** + * Add a stretch to the buttonbox. + * + * Can be used to separate buttons. That is, if you add the + * buttons OK and Cancel, add a stretch, and then add the button Help, + * the buttons OK and Cancel will be left-aligned (or top-aligned + * for vertical) whereas Help will be right-aligned (or + * bottom-aligned for vertical). + * + * @see QBoxLayout + */ + void addStretch(int scale = 1); + + /** + * This function must be called @em once after all buttons have been + * inserted. + * + * It will start layout control. + */ + void layout(); + +public: // as PrivateData needs Item, it has to be exported + class Item; +protected: + /** + * @return the best size for a button. Checks all buttons and takes + * the maximum width/height. + */ + QSize bestButtonSize() const; + void placeButtons(); + QSize buttonSizeHint(QPushButton *) const; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KButtonBoxPrivate *data; +}; + +#endif diff --git a/microkde/kdeui/kcmodule.cpp b/microkde/kdeui/kcmodule.cpp new file mode 100644 index 0000000..915cd0f --- a/dev/null +++ b/microkde/kdeui/kcmodule.cpp @@ -0,0 +1,106 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2001 Michael Goffioul <goffioul@imec.be> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include "kcmodule.h" +//US#include <kinstance.h> +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +class KCModulePrivate +{ +public: +//US KInstance *_instance; + QString _rootOnlyMsg; + bool _useRootOnlyMsg; + bool _hasOwnInstance; +}; + +KCModule::KCModule(QWidget *parent, const char *name, const QStringList &) + : QWidget(parent, name), _btn(Help|Default|Apply) +{ + kdDebug() << "KCModule " << name << endl; + d = new KCModulePrivate; + d->_useRootOnlyMsg = true; +/*US + d->_instance = new KInstance(name); + if (name && strlen(name)) { + d->_instance = new KInstance(name); + KGlobal::locale()->insertCatalogue(name); + } else + d->_instance = new KInstance("kcmunnamed"); +*/ + d->_hasOwnInstance = true; +//US KGlobal::setActiveInstance(this->instance()); +} + +/*US +KCModule::KCModule(KInstance *instance, QWidget *parent, const QStringList & ) + : QWidget(parent, instance ? instance->instanceName().data() : 0), _btn(Help|Default|Apply) +{ + kdDebug() << "KCModule instance " << (instance ? instance->instanceName().data() : "none") << endl; + d = new KCModulePrivate; + d->_useRootOnlyMsg = true; + d->_instance = instance; + KGlobal::locale()->insertCatalogue(instance->instanceName()); + d->_hasOwnInstance = false; + KGlobal::setActiveInstance(this->instance()); +} +*/ +KCModule::~KCModule() +{ +/*US + if (d->_hasOwnInstance) + delete d->_instance; +*/ + delete d; +} + +void KCModule::setRootOnlyMsg(const QString& msg) +{ + d->_rootOnlyMsg = msg; +} + +QString KCModule::rootOnlyMsg() const +{ + return d->_rootOnlyMsg; +} + +void KCModule::setUseRootOnlyMsg(bool on) +{ + d->_useRootOnlyMsg = on; +} + +bool KCModule::useRootOnlyMsg() const +{ + return d->_useRootOnlyMsg; +} +/*US +KInstance *KCModule::instance() const +{ + return d->_instance; +} +*/ +void KCModule::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "kcmodule.moc" diff --git a/microkde/kdeui/kcmodule.h b/microkde/kdeui/kcmodule.h new file mode 100644 index 0000000..90a87c9 --- a/dev/null +++ b/microkde/kdeui/kcmodule.h @@ -0,0 +1,266 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +#ifndef __KCMODULE_H__ +#define __KCMODULE_H__ + +#include <qwidget.h> +#include <qstringlist.h> +//USclass KAboutData; +class KCModulePrivate; +//US class KInstance; + +/** + * The base class for control center modules. + * + * Starting from KDE 2.0, control center modules are realized as shared + * libraries that are loaded into the control center at runtime. + * + * The module in principle is a simple widget displaying the + * item to be changed. The module has a very small interface. + * + * All the necessary glue logic and the GUI bells and whistles + * are provided by the control center and must not concern + * the module author. + * + * To write a config module, you have to create a library + * that contains at one factory function like this: + * + * <pre> + * #include <kgenericfactory.h> + * + * typedef KGenericFactory<YourKCModule, QWidget> YourKCModuleFactory; + * K_EXPORT_COMPONENT_FACTORY( yourLibName, YourKCModuleFactory("name_of_the_po_file") ); + * </pre> + * + * The parameter "name_of_the_po_file" has to correspond with the messages target + * that you created in your Makefile.am. + * + * See kdebase/kcontrol/HOWTO for more detailed documentation. + * + * @author Matthias Hoelzer-Kluepfel <hoelzer@kde.org> + */ + +class KCModule : public QWidget +{ + Q_OBJECT + +public: + + /** + * An enumeration type for the buttons used by this module. + * You should only use Help, Default and Apply. The rest is obsolete. + * + * @see KCModule::buttons @see KCModule::setButtons + */ + enum Button {Help=1, Default=2, Apply=16, + Reset=4, /* obsolete, do not use! */ + Cancel=8, /* obsolete, do not use! */ + Ok=32, /* obsolete, do not use! */ + SysDefault=64 /* obsolete, do not use! */ }; + + /* + * Base class for all KControlModules. + * Make sure you have a QStringList argument in your + * implementation. + */ + KCModule(QWidget *parent=0, const char *name=0, const QStringList &args=QStringList() ); + +//US KCModule(KInstance *instance, QWidget *parent=0, const QStringList &args=QStringList() ); + + /* + * Destroys the module. + */ + ~KCModule(); + + /** + * Load the configuration data into the module. + * + * The load method sets the user interface elements of the + * module to reflect the current settings stored in the + * configuration files. + * + * This method is invoked whenever the module should read its configuration + * (most of the times from a config file) and update the user interface. + * This happens when the user clicks the "Reset" button in the control + * center, to undo all of his changes and restore the currently valid + * settings. NOTE that this is not called after the modules is loaded, + * so you probably want to call this method in the constructor. + */ + virtual void load() {}; + + /** + * Save the configuration data. + * + * The save method stores the config information as shown + * in the user interface in the config files. + * + * If necessary, this method also updates the running system, + * e.g. by restarting applications. + * + * save is called when the user clicks "Apply" or "Ok". + */ + virtual void save() {}; + + /** + * Sets the configuration to sensible default values. + * + * This method is called when the user clicks the "Default" + * button. It should set the display to useful values. + */ + virtual void defaults() {}; + + /** + * Set the configuration to system default values. + * + * This method is called when the user clicks the "System-Default" + * button. It should set the display to the system default values. + * + * NOTE: The default behaviour is to call defaults(). + */ + virtual void sysdefaults() { defaults(); }; + + /** + * Return a quick-help text. + * + * This method is called when the module is docked. + * The quick-help text should contain a short description of the module and + * links to the module's help files. You can use QML formating tags in the text. + * + * NOTE: Please make sure the quick help text gets translated (use i18n()). + */ + virtual QString quickHelp() const { return QString::null; }; + + /** + * Returns a the KAboutData for this module + * This is generally only called for the KBugReport. + * Override and have it return a pointer to a constant + */ +//US virtual const KAboutData *aboutData() const { return 0; } + + /** + * Indicate which buttons will be used. + * + * The return value is a value or'ed together from + * the Button enumeration type. + * + * @see KCModule::setButtons + */ + int buttons() const { return _btn; }; + + /** + * Get the RootOnly message for this module. + * + * When the module must be run as root, or acts differently + * for root and a normal user, it is sometimes useful to + * customize the message that appears at the top of the module + * when used as a normal user. This function returns this + * customized message. If none has been set, a default message + * will be used. + * + * @see KCModule::setRootOnlyMsg + */ + QString rootOnlyMsg() const; + + /** + * Tell if KControl should show a RootOnly message when run as + * a normal user. + * + * In some cases, the module don't want a RootOnly message to + * appear (for example if it has already one). This function + * tells KControl if a RootOnly message should be shown + * + * @see KCModule::setUseRootOnlyMsg + */ + bool useRootOnlyMsg() const; + + +//US KInstance *instance() const; + +signals: + + /** + * Indicate that the state of the modules contents has changed. + * + * This signal is emitted whenever the state of the configuration + * shown in the module changes. It allows the control center to + * keep track of unsaved changes. + * + */ + void changed(bool state); + + /** + * Indicate that the module's quickhelp has changed. + * + * Emit this signal whenever the module's quickhelp changes. + * Modules implemented as tabbed dialogs might want to implement + * per-tab quickhelp for example. + * + */ + void quickHelpChanged(); + +protected: + + /** + * Sets the buttons to display. + * + * Help: shows a "Help" button. + * Default: shows a "Use Defaults" button + * Apply: in kcontrol this will show an "Apply" and "Reset" button + * in kcmshell this will show an "Ok", "Apply" and "Cancel" button + * + * If Apply is not specified, kcmshell will show a "Close" button. + * + * @see KCModule::buttons + */ + void setButtons(int btn) { _btn = btn; }; + + /** + * Sets the RootOnly message. + * + * This message will be shown at the top of the module of the + * corresponding desktop file contains the line X-KDE-RootOnly=true. + * If no message is set, a default one will be used. + * + * @see KCModule::rootOnlyMessage + */ + void setRootOnlyMsg(const QString& msg); + + /** + * Change wether or not the RootOnly message should be shown. + * + * Following the value of @p on, the RootOnly message will be + * shown or not. + * + * @see KCModule::useRootOnlyMsg + */ + void setUseRootOnlyMsg(bool on); + +private: + + int _btn; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KCModulePrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kguiitem.cpp b/microkde/kdeui/kguiitem.cpp new file mode 100644 index 0000000..828c5e6 --- a/dev/null +++ b/microkde/kdeui/kguiitem.cpp @@ -0,0 +1,205 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Holger Freyther (freyher@yahoo.com) + based on ideas from Martijn and Simon + many thanks to Simon + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qregexp.h> +#include <qstring.h> +#include <qiconset.h> +#include <qpixmap.h> + +#include <assert.h> +//US #include <kiconloader.h> +#include <kdebug.h> + +#include "kguiitem.h" + +class KGuiItem::KGuiItemPrivate +{ +public: + KGuiItemPrivate() + { + m_enabled = true; + m_hasIcon = false; + } + + KGuiItemPrivate( const KGuiItemPrivate &rhs ) + { + (*this ) = rhs; + } + + KGuiItemPrivate &operator=( const KGuiItemPrivate &rhs ) + { + m_text = rhs.m_text; + m_iconSet = rhs.m_iconSet; + m_iconName = rhs.m_iconName; + m_toolTip = rhs.m_toolTip; + m_whatsThis = rhs.m_whatsThis; + m_statusText = rhs.m_statusText; + m_enabled = rhs.m_enabled; + m_hasIcon = rhs.m_hasIcon; + + return *this; + } + + QString m_text; + QString m_toolTip; + QString m_whatsThis; + QString m_statusText; + QString m_iconName; + QIconSet m_iconSet; + bool m_hasIcon : 1; + bool m_enabled : 1; +}; + + +KGuiItem::KGuiItem() { + d = new KGuiItemPrivate; +} + +KGuiItem::KGuiItem( const QString &text, const QString &iconName, + const QString &toolTip, const QString &whatsThis ) +{ + d = new KGuiItemPrivate; + d->m_text = text; + d->m_toolTip = toolTip; + d->m_whatsThis = whatsThis; + setIconName( iconName ); +} + +KGuiItem::KGuiItem( const QString &text, const QIconSet &iconSet, + const QString &toolTip, const QString &whatsThis ) +{ + d = new KGuiItemPrivate; + d->m_text = text; + d->m_toolTip = toolTip; + d->m_whatsThis = whatsThis; + setIconSet( iconSet ); +} + +KGuiItem::KGuiItem( const KGuiItem &rhs ) + : d( 0 ) +{ + (*this) = rhs; +} + +KGuiItem &KGuiItem::operator=( const KGuiItem &rhs ) { + if ( d == rhs.d ) + return *this; + + assert( rhs.d ); + + delete d; + d = new KGuiItemPrivate( *rhs.d ); + + return *this; +} + +KGuiItem::~KGuiItem() { + delete d; +} + +QString KGuiItem::text() const { + return d->m_text; +} +QString KGuiItem::plainText() const { + QString stripped( d->m_text ); + stripped.replace( QRegExp( "&(?!&)" ), QString::null ); + + return stripped; +} + +QIconSet KGuiItem::iconSet( KIcon::Group group, int size /*US, KInstance* instance */ ) const +{ + if( d->m_hasIcon ) + { + if( !d->m_iconName.isEmpty()) + { +// some caching here would(?) come handy +//US return instance->iconLoader()->loadIconSet( d->m_iconName, group, size ); + return KGlobal::iconLoader()->loadIconSet( d->m_iconName); +// here is a little problem that with delayed icon loading +// we can't check if the icon really exists ... so what ... +// if( set.isNull() ) +// { +// d->m_hasIcon = false; +// return QIconSet(); +// } +// return set; + } + else + { + return d->m_iconSet; + } + } + else + return QIconSet(); +} + +QString KGuiItem::iconName() const +{ + return d->m_iconName; +} + +QString KGuiItem::toolTip() const { + return d->m_toolTip; +} +QString KGuiItem::whatsThis() const { + return d->m_whatsThis; +} + +bool KGuiItem::isEnabled() const +{ + return d->m_enabled; +} + +bool KGuiItem::hasIcon() const +{ + return d->m_hasIcon; +} + +void KGuiItem::setText( const QString &text ) { + d->m_text=text; +} + +void KGuiItem::setIconSet( const QIconSet &iconset ) +{ + d->m_iconSet = iconset; + d->m_iconName = QString::null; + d->m_hasIcon = !iconset.isNull(); +} + +void KGuiItem::setIconName( const QString &iconName ) +{ + d->m_iconName = iconName; + d->m_iconSet = QIconSet(); + d->m_hasIcon = !iconName.isEmpty(); +} + +void KGuiItem::setToolTip( const QString &toolTip) { + d->m_toolTip = toolTip; +} +void KGuiItem::setWhatsThis( const QString &whatsThis ) { + d->m_whatsThis = whatsThis; +} +void KGuiItem::setEnabled( bool enabled ){ + d->m_enabled = enabled; +} + +/* vim: et sw=4 + */ diff --git a/microkde/kdeui/kguiitem.h b/microkde/kdeui/kguiitem.h new file mode 100644 index 0000000..0079bb4 --- a/dev/null +++ b/microkde/kdeui/kguiitem.h @@ -0,0 +1,87 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Holger Freyther (freyher@yahoo.com) + based on ideas from Martijn and Simon + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Many thanks to Simon tronical Hausmann +*/ + +#ifndef __kguiitem_h__ +#define __kguiitem_h__ + +#include <qstring.h> +#include <qiconset.h> +#include <qpixmap.h> +#include <qvaluelist.h> +//US#include <kicontheme.h> +#include <kglobal.h> + +//US added the following files +#include <kiconloader.h> + +class KGuiItem +{ +public: + KGuiItem(); + + KGuiItem( const QString &text, + const QString &iconName = QString::null, + const QString &toolTip = QString::null, + const QString &whatsThis = QString::null ); + + KGuiItem( const QString &text, const QIconSet &iconSet, + const QString &toolTip = QString::null, + const QString &whatsThis = QString::null ); + + KGuiItem( const KGuiItem &rhs ); + KGuiItem &operator=( const KGuiItem &rhs ); + + ~KGuiItem(); + + QString text() const; + QString plainText() const; + QIconSet iconSet( KIcon::Group, int size = 0/*US , KInstance* instance = KGlobal::instance()*/) const; + +#ifndef KDE_NO_COMPAT + QIconSet iconSet() const { return iconSet( KIcon::Small); } +#endif + + QString iconName() const; + QString toolTip() const; + QString whatsThis() const; + bool isEnabled() const; + bool hasIcon() const; +#ifndef KDE_NO_COMPAT + bool hasIconSet() const { return hasIcon(); } +#endif + + void setText( const QString &text ); + void setIconSet( const QIconSet &iconset ); + void setIconName( const QString &iconName ); + void setToolTip( const QString &tooltip ); + void setWhatsThis( const QString &whatsThis ); + void setEnabled( bool enable ); + +private: + class KGuiItemPrivate; + KGuiItemPrivate *d; +}; + +/* vim: et sw=4 + */ + +#endif + diff --git a/microkde/kdeui/kjanuswidget.cpp b/microkde/kdeui/kjanuswidget.cpp new file mode 100644 index 0000000..7d25854 --- a/dev/null +++ b/microkde/kdeui/kjanuswidget.cpp @@ -0,0 +1,1176 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espensa@online.no) + * Copyright (C) 2003 Ravikiran Rajagopal (ravi@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 as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <qpixmap.h> +#include <qbitmap.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qwidgetstack.h> +#include <qtabwidget.h> +#include <qlistview.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qgrid.h> +#include <qpainter.h> +#include <qobjectlist.h> + +/*US +#include <qbitmap.h> +#include <qgrid.h> +#include <qhbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qpixmap.h> +#include <qsplitter.h> +#include <qtabwidget.h> +#include <qvbox.h> +#include <qwidgetstack.h> +#include <qpainter.h> +#include <qstyle.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kseparator.h> +#include <kdebug.h> +#include "kjanuswidget.h" +#include <klistview.h> + +*/ + +#include <kseparator.h> +#include <kdialog.h> // Access to some static members +#include <kdebug.h> +#include <klistview.h> + +#include "kjanuswidget.h" + +class KJanusWidget::IconListItem : public QListBoxItem +{ + public: + IconListItem( QListBox *listbox, const QPixmap &pixmap, + const QString &text ); + virtual int height( const QListBox *lb ) const; + virtual int width( const QListBox *lb ) const; + int expandMinimumWidth( int width ); + + protected: + const QPixmap &defaultPixmap(); + void paint( QPainter *painter ); + + private: + QPixmap mPixmap; + int mMinimumWidth; +}; + +class KJanusWidget::KJanusWidgetPrivate +{ +public: + KJanusWidgetPrivate() : mNextPageIndex(0) { } + + int mNextPageIndex; // The next page index. + + // Dictionary for multipage modes. + QMap<int,QWidget*> mIntToPage; + // Reverse dictionary. Used because showPage() may be performance critical. + QMap<QWidget*,int> mPageToInt; + // Dictionary of title string associated with page. + QMap<int, QString> mIntToTitle; +}; + +template class QPtrList<QListViewItem>; + + +KJanusWidget::KJanusWidget( QWidget *parent, const char *name, int face ) + : QWidget( parent, name ), + mValid(false), mPageList(0), + mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0), + mShowIconsInTreeList(false), d(0) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this ); + if( mFace == TreeList || mFace == IconList ) + { + d = new KJanusWidgetPrivate; + + QFrame *page = 0; + if( mFace == TreeList ) + { + //US + qDebug("KJanusWidget::KJanusWidget TreeList not implemented yet"); +/*US + QSplitter *splitter = new QSplitter( this ); + topLayout->addWidget( splitter, 10 ); + mTreeListResizeMode = QSplitter::KeepSize; + + mTreeList = new KListView( splitter ); + mTreeList->addColumn( QString::null ); + mTreeList->header()->hide(); + mTreeList->setRootIsDecorated(true); + mTreeList->setSorting( -1 ); + connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) ); + connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *))); + + // + // Page area. Title at top with a separator below and a pagestack using + // all available space at bottom. + // + QFrame *p = new QFrame( splitter ); + + QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 ); + hbox->addSpacing( KDialog::marginHint() ); + + page = new QFrame( p ); + hbox->addWidget( page, 10 ); +*/ + } + else + { + QHBoxLayout *hbox = new QHBoxLayout( topLayout ); + mIconList = new IconListBox( this ); + + QFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + + mIconList->verticalScrollBar()->installEventFilter( this ); + hbox->addWidget( mIconList ); + connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage())); + hbox->addSpacing( KDialog::marginHint() ); + page = new QFrame( this ); + hbox->addWidget( page, 10 ); + } + + // + // Rest of page area. Title at top with a separator below and a + // pagestack using all available space at bottom. + // + + QVBoxLayout *vbox = new QVBoxLayout( page, 0, KDialog::spacingHint() ); + + mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "KJanusWidgetTitleLabel" ); + vbox->addWidget( mTitleLabel ); + + QFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + + mTitleSep = new KSeparator( page ); + mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain ); + vbox->addWidget( mTitleSep ); + + mPageStack = new QWidgetStack( page ); + connect(mPageStack, SIGNAL(aboutToShow(QWidget *)), + SIGNAL(aboutToShowPage(QWidget *))); + vbox->addWidget( mPageStack, 10 ); + } + else if( mFace == Tabbed ) + { + d = new KJanusWidgetPrivate; + + mTabControl = new QTabWidget( this ); + mTabControl->setMargin (KDialog::marginHint()); + topLayout->addWidget( mTabControl, 10 ); + } + else if( mFace == Swallow ) + { + mSwallowPage = new QWidget( this ); + topLayout->addWidget( mSwallowPage, 10 ); + } + else + { + mFace = Plain; + mPlainPage = new QFrame( this ); + topLayout->addWidget( mPlainPage, 10 ); + } +/*US + if ( kapp ) + connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged())); +*/ + mValid = true; + setSwallowedWidget(0); // Set default size if 'mFace' is Swallow. +} + + +KJanusWidget::~KJanusWidget() +{ + +/*US the destroyed signal caused a segmentation fault while closing the dialog and destructing + all pages. Why not just remove all pages in the destructor?? +*/ +// LR we have all subwidgets with parent-child relation +// LR we do not need to delete here anything by the private class +/* + if( mFace == Tabbed ) + { + QMap<QWidget*,int>::Iterator it; + for (it = d->mPageToInt.begin(); it != d->mPageToInt.end(); ++it) { + QObject*page = (QObject*)it.key(); + pageGone(page); + } + } + else + qDebug("KJanusWidget::~KJanusWidget so far "); +*/ +//US end + + delete d; + + +} + + +bool KJanusWidget::isValid() const +{ + return( mValid ); +} + + +QFrame *KJanusWidget::plainPage() +{ + return( mPlainPage ); +} + + +int KJanusWidget::face() const +{ + return( mFace ); +} + +QWidget *KJanusWidget::FindParent() +{ + if( mFace == Tabbed ) { + return mTabControl; + } + else { + return this; + } +} + +QFrame *KJanusWidget::addPage( const QStringList &items, const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QFrame *page = new QFrame( FindParent(), "page" ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +void KJanusWidget::pageGone( QObject *obj ) +{ +// QObject* obj = (QObject*)sender(); + removePage( static_cast<QWidget*>( obj ) ); +} + +void KJanusWidget::slotReopen( QListViewItem * item ) +{ + if( item ) + item->setOpen( true ); +} + +QFrame *KJanusWidget::addPage( const QString &itemName, const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addPage(items, header, pixmap); +} + + + +QVBox *KJanusWidget::addVBoxPage( const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + qDebug("addPage: Invalid object "); + + return( 0 ); + } + + QVBox *page = new QVBox(FindParent() , "vbox_page" ); + page->setSpacing( KDialog::spacingHintSmall() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +QVBox *KJanusWidget::addVBoxPage( const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addVBoxPage(items, header, pixmap); +} + +QHBox *KJanusWidget::addHBoxPage( const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QHBox *page = new QHBox(FindParent(), "hbox_page"); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +QHBox *KJanusWidget::addHBoxPage( const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addHBoxPage(items, header, pixmap); +} + +QGrid *KJanusWidget::addGridPage( int n, QGrid::Direction dir, + const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QGrid *page = new QGrid( n, dir, FindParent(), "page" ); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + + +QGrid *KJanusWidget::addGridPage( int n, QGrid::Direction dir, + const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addGridPage(n, dir, items, header, pixmap); +} + +void KJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page) +{ + bool isTop = true; + QListViewItem *curTop = 0, *child, *last, *newChild; + unsigned int index = 1; + QStringList curPath; + + for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) { + QString name = (*it); + bool isPath = ( index != items.count() ); + + // Find the first child. + if (isTop) { + child = mTreeList->firstChild(); + } + else { + child = curTop->firstChild(); + } + + // Now search for a child with the current Name, and if it we doesn't + // find it, then remember the location of the last child. + for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling()); + + if (last == 0 && child == 0) { + // This node didn't have any children at all, lets just insert the + // new child. + if (isTop) + newChild = new QListViewItem(mTreeList, name); + else + newChild = new QListViewItem(curTop, name); + + } + else if (child != 0) { + // we found the given name in this child. + if (!isPath) { + kdDebug() << "The element inserted was already in the TreeList box!" << endl; + return; + } + else { + // Ok we found the folder + newChild = child; + } + } + else { + // the node had some children, but we didn't find the given name + if (isTop) + newChild = new QListViewItem(mTreeList, last, name); + else + newChild = new QListViewItem(curTop, last, name); + } + + // Now make the element expandable if it is a path component, and make + // ready for next loop + if (isPath) { + newChild->setExpandable(true); + curTop = newChild; + isTop = false; + curPath << name; + + QString key = curPath.join("_/_"); + if (mFolderIconMap.contains(key)) { + QPixmap p = mFolderIconMap[key]; + newChild->setPixmap(0,p); + } + } + else { + if (mShowIconsInTreeList) { + newChild->setPixmap(0, pixmap); + } + mTreeListToPageStack.insert(newChild, page); + } + } +} + +void KJanusWidget::addPageWidget( QFrame *page, const QStringList &items, + const QString &header,const QPixmap &pixmap ) +{ +/*US the following signal causes a segmentation fault while closing the dialog. + Why not just remove all pages in the destructor?? +*/ +//US connect(page, SIGNAL(destroyed(QObject*)), this, SLOT(pageGone(QObject*))); +// we have the SIGNAL(destroyed(QObject*) only in Qt3 +#ifdef DESKTOP_VERSION + // connect(page, SIGNAL(destroyed(QObject*)), this, SLOT(pageGone(QObject*))); +#endif + if( mFace == Tabbed ) + { + mTabControl->addTab (page, items.last()); + d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page); + d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex; + d->mNextPageIndex++; + } + else if( mFace == TreeList || mFace == IconList ) + { + d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page); + d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex; + mPageStack->addWidget( page, 0 ); + + if (items.count() == 0) { + kdDebug() << "Invalid QStringList, with zero items" << endl; + return; + } + + if( mFace == TreeList ) + { + InsertTreeListItem(items, pixmap, page); + } + else // mFace == IconList + { + QString itemName = items.last(); + IconListItem *item = new IconListItem( mIconList, pixmap, itemName ); + mIconListToPageStack.insert(item, page); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + + if (mIconList->isVisible()) + mIconList->updateWidth(); + } + + // + // Make sure the title label is sufficiently wide + // + QString lastName = items.last(); + const QString &title = (!header.isNull() ? header : lastName); + QRect r = mTitleLabel->fontMetrics().boundingRect( title ); + if( mTitleLabel->minimumWidth() < r.width() ) + { + mTitleLabel->setMinimumWidth( r.width() ); + } + d->mIntToTitle[d->mNextPageIndex] = title; + if( d->mIntToTitle.count() == 1 ) + { + showPage(0); + } + d->mNextPageIndex++; + } + else + { + kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl; + } + +} + +void KJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap) +{ + QString key = path.join("_/_"); + mFolderIconMap.insert(key,pixmap); +} + + + +bool KJanusWidget::setSwallowedWidget( QWidget *widget ) +{ + if( mFace != Swallow || mValid == false ) + { + return( false ); + } + + // + // Remove current layout and make a new. + // + if( mSwallowPage->layout() != 0 ) + { + delete mSwallowPage->layout(); + } + QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 ); + + // + // Hide old children + // + QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please + for( uint i=0; i < l->count(); i++ ) + { + QObject *o = l->at(i); + if( o->isWidgetType() ) + { + ((QWidget*)o)->hide(); + } + } + + // + // Add new child or make default size + // + if( widget == 0 ) + { + gbox->addRowSpacing(0,100); + gbox->addColSpacing(0,100); + mSwallowPage->setMinimumSize(100,100); + } + else + { + if( widget->parent() != mSwallowPage ) + { + widget->reparent( mSwallowPage, 0, QPoint(0,0) ); + } + gbox->addWidget(widget, 0, 0 ); + gbox->activate(); + mSwallowPage->setMinimumSize( widget->minimumSize() ); + } + + return( true ); +} + +bool KJanusWidget::slotShowPage() +{ + if( mValid == false ) + { + return( false ); + } + + if( mFace == TreeList ) + { + QListViewItem *node = mTreeList->selectedItem(); + if( node == 0 ) { return( false ); } + + QWidget *stackItem = mTreeListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + else if( mFace == IconList ) + { + QListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( node == 0 ) { return( false ); } + QWidget *stackItem = mIconListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + + return( false ); +} + + +bool KJanusWidget::showPage( int index ) +{ + if( d == 0 || mValid == false ) + { + return( false ); + } + else + { + return showPage(d->mIntToPage[index]); + } +} + + +bool KJanusWidget::showPage( QWidget *w ) +{ + if( w == 0 || mValid == false ) + { + return( false ); + } + + if( mFace == TreeList || mFace == IconList ) + { + mPageStack->raiseWidget( w ); + mActivePageWidget = w; + + int index = d->mPageToInt[w]; + mTitleLabel->setText( d->mIntToTitle[index] ); + if( mFace == TreeList ) + { + QMap<QListViewItem *, QWidget *>::Iterator it; + for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){ + QListViewItem *key = it.key(); + QWidget *val = it.data(); + if (val == w) { + mTreeList->setSelected(key, true ); + break; + } + } + } + else + { + QMap<QListBoxItem *, QWidget *>::Iterator it; + for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){ + QListBoxItem *key = it.key(); + QWidget *val = it.data(); + if (val == w) { + mIconList->setSelected( key, true ); + break; + } + } + } + } + else if( mFace == Tabbed ) + { + mTabControl->showPage(w); + mActivePageWidget = w; + } + else + { + return( false ); + } + + return( true ); +} + + +int KJanusWidget::activePageIndex() const +{ + if( mFace == TreeList) { + QListViewItem *node = mTreeList->selectedItem(); + if( node == 0 ) { return -1; } + QWidget *stackItem = mTreeListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if (mFace == IconList) { + QListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( node == 0 ) { return( false ); } + QWidget *stackItem = mIconListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if( mFace == Tabbed ) { + QWidget *widget = mTabControl->currentPage(); + return( widget == 0 ? -1 : d->mPageToInt[widget] ); + } + else { + return( -1 ); + } +} + + +int KJanusWidget::pageIndex( QWidget *widget ) const +{ + if( widget == 0 ) + { + return( -1 ); + } + else if( mFace == TreeList || mFace == IconList ) + { + return( d->mPageToInt[widget] ); + } + else if( mFace == Tabbed ) + { + // + // The user gets the real page widget with addVBoxPage(), addHBoxPage() + // and addGridPage() but not with addPage() which returns a child of + // the toplevel page. addPage() returns a QFrame so I check for that. + // + if( widget->isA("QFrame") ) + { + return( d->mPageToInt[widget->parentWidget()] ); + } + else + { + return( d->mPageToInt[widget] ); + } + } + else + { + return( -1 ); + } +} +/*US not yet implemented +void KJanusWidget::slotFontChanged() +{ + if( mTitleLabel != 0 ) + { + mTitleLabel->setFont( KGlobalSettings::generalFont() ); + QFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + } + + if( mFace == IconList ) + { + QFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + } +} +*/ + +// makes the treelist behave like the list of kcontrol +void KJanusWidget::slotItemClicked(QListViewItem *it) +{ + if(it && (it->childCount()>0)) + it->setOpen(!it->isOpen()); +} + +void KJanusWidget::setFocus() +{ + if( mValid == false ) { return; } + if( mFace == TreeList ) + { + mTreeList->setFocus(); + } + if( mFace == IconList ) + { + mIconList->setFocus(); + } + else if( mFace == Tabbed ) + { + mTabControl->setFocus(); + } + else if( mFace == Swallow ) + { + mSwallowPage->setFocus(); + } + else if( mFace == Plain ) + { + mPlainPage->setFocus(); + } +} + + +QSize KJanusWidget::minimumSizeHint() const +{ + if( mFace == TreeList || mFace == IconList ) + { + QSize s1( KDialog::spacingHint(), KDialog::spacingHint()*2 ); + QSize s2(0,0); + QSize s3(0,0); + QSize s4( mPageStack->sizeHint() ); + + if( mFace == TreeList ) + { +/*US + s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth ); + s2 = mTreeList->minimumSize(); +*/ + } + else + { + mIconList->updateMinimumHeight(); + mIconList->updateWidth(); + s2 = mIconList->minimumSize(); + } + + if( mTitleLabel->isVisible() == true ) + { + s3 += mTitleLabel->sizeHint(); + s3.rheight() += mTitleSep->minimumSize().height(); + } + + // + // Select the tallest item. It has only effect in IconList mode + // + int h1 = s1.rheight() + s3.rheight() + s4.height(); + int h2 = QMAX( h1, s2.rheight() ); + + return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) ); + } + else if( mFace == Tabbed ) + { + return( mTabControl->sizeHint() ); + } + else if( mFace == Swallow ) + { + return( mSwallowPage->minimumSize() ); + } + else if( mFace == Plain ) + { + return( mPlainPage->sizeHint() ); + } + else + { + return( QSize( 100, 100 ) ); // Should never happen though. + } + +} + + +QSize KJanusWidget::sizeHint() const +{ + return( minimumSizeHint() ); +} + + +void KJanusWidget::setTreeListAutoResize( bool state ) +{ + if( mFace == TreeList ) + { +/*US + mTreeListResizeMode = state == false ? + QSplitter::KeepSize : QSplitter::Stretch; + QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget()); + splitter->setResizeMode( mTreeList, mTreeListResizeMode ); +*/ + } +} + + +void KJanusWidget::setIconListAllVisible( bool state ) +{ + if( mFace == IconList ) + { + mIconList->setShowAll( state ); + } +} + +void KJanusWidget::setShowIconsInTreeList( bool state ) +{ + mShowIconsInTreeList = state; +} + +void KJanusWidget::setRootIsDecorated( bool state ) +{ + if( mFace == TreeList ) { + mTreeList->setRootIsDecorated(state); + } +} + +void KJanusWidget::unfoldTreeList( bool persist ) +{ + if( mFace == TreeList ) + { + if( persist ) + connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) ); + else + disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) ); + + for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() ) + item->setOpen( true ); + } +} + +void KJanusWidget::showEvent( QShowEvent * ) +{ + if( mFace == TreeList ) + { +/*US + QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget()); + splitter->setResizeMode( mTreeList, mTreeListResizeMode ); +*/ + } +} + + +// +// 2000-13-02 Espen Sand +// It should be obvious that this eventfilter must only be +// be installed on the vertical scrollbar of the mIconList. +// +bool KJanusWidget::eventFilter( QObject *o, QEvent *e ) +{ + if( e->type() == QEvent::Show ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item != 0 ) + { + int lw = item->width( mIconList ); + int sw = mIconList->verticalScrollBar()->sizeHint().width(); + mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 ); + } + } + else if( e->type() == QEvent::Hide ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item != 0 ) + { + int lw = item->width( mIconList ); + mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 ); + } + } + return QWidget::eventFilter( o, e ); +} + + + +// +// Code for the icon list box +// + + +KJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name, + WFlags f ) + :KListBox( parent, name, f ), mShowAll(false), mHeightValid(false), + mWidthValid(false) +{ +} + + +void KJanusWidget::IconListBox::updateMinimumHeight() +{ + if( mShowAll == true && mHeightValid == false ) + { + int h = frameWidth()*2; + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + h += i->height( this ); + } + setMinimumHeight( h ); + mHeightValid = true; + } +} + + +void KJanusWidget::IconListBox::updateWidth() +{ + if( mWidthValid == false ) + { + int maxWidth = 10; + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + int w = ((IconListItem *)i)->width(this); + maxWidth = QMAX( w, maxWidth ); + } + + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + ((IconListItem *)i)->expandMinimumWidth( maxWidth ); + } + + if( verticalScrollBar()->isVisible() ) + { + maxWidth += verticalScrollBar()->sizeHint().width(); + } + + setFixedWidth( maxWidth + frameWidth()*2 ); + mWidthValid = true; + } +} + + +void KJanusWidget::IconListBox::invalidateHeight() +{ + mHeightValid = false; +} + + +void KJanusWidget::IconListBox::invalidateWidth() +{ + mWidthValid = false; +} + + +void KJanusWidget::IconListBox::setShowAll( bool showAll ) +{ + mShowAll = showAll; + mHeightValid = false; +} + + + +KJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap, + const QString &text ) + : QListBoxItem( listbox ) +{ + mPixmap = pixmap; + if( mPixmap.isNull() == true ) + { + mPixmap = defaultPixmap(); + } + setText( text ); + mMinimumWidth = 0; +} + + +int KJanusWidget::IconListItem::expandMinimumWidth( int width ) +{ + mMinimumWidth = QMAX( mMinimumWidth, width ); + return( mMinimumWidth ); +} + + +const QPixmap &KJanusWidget::IconListItem::defaultPixmap() +{ + static QPixmap *pix=0; + if( pix == 0 ) + { + pix = new QPixmap( 32, 32 ); + QPainter p( pix ); + p.eraseRect( 0, 0, pix->width(), pix->height() ); + p.setPen( Qt::red ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + QBitmap mask( pix->width(), pix->height(), true); + mask.fill( Qt::black ); + p.begin( &mask ); + p.setPen( Qt::white ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + pix->setMask( mask ); + } + return( *pix ); +} + + +void KJanusWidget::IconListItem::paint( QPainter *painter ) +{ + QFontMetrics fm = painter->fontMetrics(); + //int wt = fm.boundingRect(text()).width(); + int wp = mPixmap.width(); + int ht = fm.lineSpacing(); + int hp = mPixmap.height(); + + painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap ); + if( text().isEmpty() == false ) + { + painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() ); + } +} + +int KJanusWidget::IconListItem::height( const QListBox *lb ) const +{ + if( text().isEmpty() == true ) + { + return( mPixmap.height() ); + } + else + { + return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 ); + } +} + + +int KJanusWidget::IconListItem::width( const QListBox *lb ) const +{ + int wt = lb->fontMetrics().boundingRect(text()).width()+10; + int wp = mPixmap.width() + 10; + int w = QMAX( wt, wp ); + return( QMAX( w, mMinimumWidth ) ); +} + + +void KJanusWidget::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +// TODO: In TreeList, if the last child of a node is removed, and there is no corrsponding widget for that node, allow the caller to +// delete the node. +void KJanusWidget::removePage( QWidget *page ) +{ +//US qDebug("KJanusWidget::removePage 1 %lu , %lu, %lu", d, page, &(d->mPageToInt)); + if (!d || !(d->mPageToInt.contains(page))) + { + return; + } + + int index = d->mPageToInt[page]; + + if ( mFace == TreeList ) + { + QMap<QListViewItem*, QWidget *>::Iterator i; + for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mTreeListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else if ( mFace == IconList ) + { + QMap<QListBoxItem*, QWidget *>::Iterator i; + for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mIconListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else // Tabbed + { + mTabControl->removePage(page); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + } +} + +QString KJanusWidget::pageTitle(int index) const +{ + if (!d || !d->mIntToTitle.contains(index)) + return QString::null; + else + return d->mIntToTitle[index]; +} + +QWidget *KJanusWidget::pageWidget(int index) const +{ + if (!d || !d->mIntToPage.contains(index)) + return 0; + else + return d->mIntToPage[index]; +} + +//US #include "kjanuswidget.moc" diff --git a/microkde/kdeui/kjanuswidget.h b/microkde/kdeui/kjanuswidget.h new file mode 100644 index 0000000..6d3f23d --- a/dev/null +++ b/microkde/kdeui/kjanuswidget.h @@ -0,0 +1,565 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espen@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 as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _KJANUS_WIDGET_H_ +#define _KJANUS_WIDGET_H_ + +#include <qptrlist.h> +#include <qwidget.h> +#include <qmap.h> +#include <qgrid.h> +#include <klistbox.h> + +/*US +#include <qptrlist.h> +#include <qpixmap.h> +#include <qsplitter.h> + +#include <qstringlist.h> +#include <qmap.h> + +*/ + +class KSeparator; +class KListView; +class QWidgetStack; +class QLabel; +class QTabWidget; +class QListViewItem; +class QVBox; +class QHBox; + +/** + * Provides a number of ready to use layouts (faces). It is used + * as an internal widget in @ref KDialogBase, but can also used as a + * widget of its own. + * + * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts. + * + * The TreeList face provides a list in the left area and pages in the + * right. The area are separated by a movable splitter. The style is somewhat + * similar to the layout in the Control Center. A page is raised by + * selecting the corresponding tree list item. + * + * The IconList face provides an icon list in the left area and pages in the + * right. For each entry the Icon is on top with the text below. The style + * is somewhat similar to the layout of the Eudora configuation dialog box. + * A page is raised by selecting the corresponding icon list item. The + * preferred icon size is 32x32 pixels. + * + * The Tabbed face is a common tabbed widget. The procedure for creating a + * page is similar for creating a TreeList. This has the advantage that if + * your widget contain too many pages it is trivial to convert it into a + * TreeList. Just change the face in the KJanusWidget constructor to + * KJanusWidget::TreeList and you have a tree list layout instead. + * + * The Plain face provides an empty widget (QFrame) where you can place your + * widgets. The KJanusWidget makes no assumptions regarding the contents so + * you are free to add whatever you want. + * + * The Swallow face is provided in order to simplify the usage of existing + * widgets and to allow changing the visible widget. You specify the widget + * to be displayed by @ref #setSwallowedWidget(). Your widget will be + * reparented inside the widget. You can specify a Null (0) widget. A empty + * space is then displayed. + * + * For all modes it is important that you specify the @ref QWidget::minimumSize() + * on the page, plain widget or the swallowed widget. If you use a QLayout + * on the page, plain widget or the swallowed widget this will be taken care + * of automatically. The size is used when the KJanusWidget determines its + * own minimum size. You get the minimum size by using the + * @ref #minimumSizeHint() or @ref #sizeHint() methods. + * + * Pages that have been added in TreeList, IconList or Tabbed mode can be + * removed by simply deleting the page. However, it would be preferable to use + * the QObject::deleteLater() function on the page as the main event loop + * may have optimized UI update events of the page by scheduling them for later. + * + * @short Easy to use widget with many layouts + * @author Espen Sand (espen@kde.org) + */ +class KJanusWidget : public QWidget +{ + Q_OBJECT + + private: + class IconListBox : public KListBox + { + public: + IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 ); + void updateMinimumHeight(); + void updateWidth(); + void invalidateHeight(); + void invalidateWidth(); + void setShowAll( bool showAll ); + + private: + bool mShowAll; + bool mHeightValid; + bool mWidthValid; + }; + + public: + enum Face + { + TreeList = 0, + Tabbed, + Plain, + Swallow, + IconList + }; + + public: + + /** + * Constructor where you specify the face. + * + * @param parent Parent of the widget. + * @param name Widget name. + * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or + * Swallow. + */ + KJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain ); + + /** + * Destructor. + */ + ~KJanusWidget(); + + /** + * Raises the page which was added by @ref addPage(). + * + * @param index The index of the page you want to raise. + */ + virtual bool showPage( int index ); + + /** + * Returns the index of the page that are currently displayed. + * + * @return The index or -1 if the face is not Tabbed, TreeList or + * IconList. + */ + virtual int activePageIndex() const; + + /** + * Use this to verify + * that no memory allocation failed. + * + * @return true if the widget was properly created. + */ + virtual bool isValid() const; + + /** + * Returns the face type. + * + * @return The face type. + */ + virtual int face() const; + + /** + * Returns the minimum size that must be made available for the widget + * so that UIs can be displayed properly + * + * @return The minimum size. + */ + virtual QSize minimumSizeHint() const; + + /** + * Returns the recommended size for the widget in order to be displayed + * properly. + * + * @return The recommended size. + */ + virtual QSize sizeHint() const; + + /** + * Returns the empty widget that is available in Plain mode. + * + * @return The widget or 0 if the face in not Plain. + */ + virtual QFrame *plainPage(); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. In most cases you must create a layout + * manager and associate it with this widget as well. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ + virtual QFrame *addPage(const QString &item,const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QVBox + * so it contains a QVBoxLayout layout that lines up the child widgets + * are vertically. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. */ + virtual QVBox *addVBoxPage( const QString &item, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addVBoxPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QVBox *addVBoxPage( const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QHBox + * so it contains a QHBoxLayout layout that lines up the child widgets + * are horizontally. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ + virtual QHBox *addHBoxPage( const QString &itemName, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addHBoxPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QHBox *addHBoxPage( const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in either TreeList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QGrid + * so it contains a QGridLayout layout that places up the child widgets + * in a grid. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal + * or the number of rows if 'dir' is QGrid::Vertical. + * @param dir Can be QGrid::Horizontal or QGrid::Vertical. + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ +//US changed Orientation into Direction for compatibility + virtual QGrid *addGridPage( int n, QGrid::Direction dir, + const QString &itemName, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addGridPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ +//US changed Orientation into Direction for compatibility + virtual QGrid *addGridPage( int n, QGrid::Direction dir, + const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * @short Removes a page created with @ref addPage, @ref addVBoxPage, + * @ref addHBoxPage or @ref addGridPage. If the page has already + * been deleted or has already been removed, nothing happens. The widget + * itself is not deleted. + * + * @param page The widget returned by @ref addPage , @ref addVBoxPage , + * @ref addHBoxPage or @ref addGridPage . + */ + void removePage( QWidget *page ); + + + /** + * Returns the index of a page created with @ref addPage , + * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage . + * You can can compare this index with the value returned from + * @ref activePageIndex if you need to do some page specific actions + * in your code. + * + * The returned index will never change so you can safely use this + * function once and save the value. + * + * @param widget The widget returned by @ref addPage , @ref addVBoxPage , + * @ref addHBoxPage or @ref addGridPage . + * + * @return The index or -1 if the face is not Tabbed, TreeList or + * IconList + */ + virtual int pageIndex( QWidget *widget ) const; + + /** + * Defines the widget to be swallowed. + * + * This method can be used several + * times. Only the latest defined widget will be shown. + * + * @param widget The widget to be swallowed. If 0, then an empty rectangle + * is displayed. + */ + virtual bool setSwallowedWidget( QWidget *widget ); + + /** + * This function has only effect in TreeList mode. + * + * Defines how the tree list is resized when the widget is resized + * horizontally. By default the tree list keeps its width when the + * widget becomes wider. + * + * @param state The resize mode. If false (default) the TreeList keeps + * its current width when the widget becomes wider. + */ + virtual void setTreeListAutoResize( bool state ); + + /** + * This function has only effect in TreeList mode. + * + * This tells the widgets whether the icons given in the @ref addPage, + * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should + * be shown in the TreeList. + * + * Note: This method must be called before calling any of the methods + * which add icons to the page. + * + * @param state If true the icons are shown. + **/ + virtual void setShowIconsInTreeList(bool state); + + /** + * This function has only effect in TreeList mode. + * + * This tells the widgets whether the root should be decorated. + * For details see @ref QListView::setRootIsDecorated + * + * @param state Root will be decorated if true. + **/ + virtual void setRootIsDecorated( bool state ); + + /** + * This function has only effect in TreeList mode. + * + * This tells the TreeList to unfold the whole tree so that all entries + * are visible. + * + * If the list is empty when you call this method newly created entries + * will not automatically be opened. If the @p persist flag is set opened + * entries cannot be closed again, though. + * + * @param persist If true the tree always stays unfolded. + * @since 3.2 + */ + /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual + + /** + * This function has only effect in IconList mode. + * + * Defines how the icon list widget is displayed. By default it is + * the widgets in the pages that decide the minimum height + * of the toplevel widget. A vertical scrollbar can be used in + * the icon list area. + * + * @param state The visibility mode. If true, the minimum height is + * adjusted so that every icon in the list is visible at the + * same time. The vertical scrollbar will never be visible. + */ + virtual void setIconListAllVisible( bool state ); + + /** + * Sets the icon used in TreeList Mode for the given path. + * @param path The path for which this icon should be shown. + * @param pixmap The icon used. + **/ + virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap); + /** + * Returns the title string associated with a page index in TreeList or IconList mode. + * @param index The index of the page or null if there is no such page. + * @see @ref #pageIndex() + * @since 3.2 + */ + /*virtual*/ QString pageTitle(int index) const; + /** + * Returns the page widget associated with a page index or null if there is + * no such page. + * @param index The index of the page. + * @see @ref #pageIndex() + * @since 3.2 + */ + /*virtual*/ QWidget *pageWidget(int index) const; + + signals: + void aboutToShowPage(QWidget *page); + + public slots: + /** + * Give the keyboard input focus to the widget. + */ + virtual void setFocus(); + + protected: + /** + * Reimplemented to handle the splitter width when the the face + * is TreeList + */ + virtual void showEvent( QShowEvent * ); + + /** + * This function is used internally when in IconList mode. If you + * reimplement this class a make your own event filter, make sure to + * call this function from your filter. + * + * @param o Object that has received an event. + * @param e The event. + */ + virtual bool eventFilter( QObject *o, QEvent *e ); + + private slots: + bool slotShowPage(); +//US not yet implemented void slotFontChanged(); + void slotItemClicked(QListViewItem *it); + void pageGone( QObject *obj); // signal from the added page's "destroyed" signal + void slotReopen(QListViewItem *item); + + protected: + bool showPage( QWidget *w ); + void addPageWidget( QFrame *page, const QStringList &items, + const QString &header, const QPixmap &pixmap ); + void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page); + QWidget *FindParent(); + + private: + bool mValid; + + // Obsolete members. Remove in KDE 4. + QPtrList<QWidget> *mPageList; + QStringList *mTitleList; + + int mFace; + KListView *mTreeList; + IconListBox *mIconList; + QWidgetStack *mPageStack; + QLabel *mTitleLabel; + QTabWidget *mTabControl; + QFrame *mPlainPage; + QWidget *mSwallowPage; + QWidget *mActivePageWidget; + KSeparator *mTitleSep; +//US QSplitter::ResizeMode mTreeListResizeMode; + bool mShowIconsInTreeList; + QMap<QListViewItem *, QWidget *> mTreeListToPageStack; + QMap<QListBoxItem *, QWidget *> mIconListToPageStack; + QMap<QString, QPixmap> mFolderIconMap; + QMap<QString, QStringList> mChildrenNames; + QMap<QString, QWidget *> mChildPages; + + public: + class IconListItem; + protected: + virtual void virtual_hook( int id, void* data ); + private: + class KJanusWidgetPrivate; + KJanusWidgetPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/klistbox.cpp b/microkde/kdeui/klistbox.cpp new file mode 100644 index 0000000..c65b892 --- a/dev/null +++ b/microkde/kdeui/klistbox.cpp @@ -0,0 +1,314 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#include <qtimer.h> + +#include <kglobalsettings.h> +//US#include <kcursor.h> +#include <kapplication.h> +//US#include <kipc.h> +#include <kdebug.h> + +#include "klistbox.h" + +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#endif +#ifdef _WIN32_ +#define Q_WS_QWS +#endif +KListBox::KListBox( QWidget *parent, const char *name, WFlags f ) + : QListBox( parent, name, f ) +{ + connect( this, SIGNAL( onViewport() ), + this, SLOT( slotOnViewport() ) ); + connect( this, SIGNAL( onItem( QListBoxItem * ) ), + this, SLOT( slotOnItem( QListBoxItem * ) ) ); + + connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); +/*US + + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + if (kapp) + { + connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); + kapp->addKipcEventMask( KIPC::SettingsChanged ); + } +*/ + m_pCurrentItem = 0L; +//US set single to true + m_bUseSingle = true; + m_pAutoSelect = new QTimer( this ); + connect( m_pAutoSelect, SIGNAL( timeout() ), + this, SLOT( slotAutoSelect() ) ); +} + +void KListBox::slotOnItem( QListBoxItem *item ) +{ +/*US + if ( item && m_bChangeCursorOverItem && m_bUseSingle ) + viewport()->setCursor( KCursor().handCursor() ); +*/ + if ( item && (m_autoSelectDelay > -1) && m_bUseSingle ) { + m_pAutoSelect->start( m_autoSelectDelay, true ); + m_pCurrentItem = item; + } +} + +void KListBox::slotOnViewport() +{ +/*US + if ( m_bChangeCursorOverItem ) + viewport()->unsetCursor(); +*/ + m_pAutoSelect->stop(); + m_pCurrentItem = 0L; +} + + +/*US +void KListBox::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) + return; + + m_bUseSingle = KGlobalSettings::singleClick(); + m_bUseSingle = true; + + disconnect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); +// disconnect( this, SIGNAL( doubleClicked( QListBoxItem *, +// const QPoint & ) ), +// this, SLOT( slotExecute( QListBoxItem *, +// const QPoint & ) ) ); + + if( m_bUseSingle ) + { + connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); + } + else + { +// connect( this, SIGNAL( doubleClicked( QListBoxItem *, +// const QPoint & ) ), +// this, SLOT( slotExecute( QListBoxItem *, +// const QPoint & ) ) ); + } + + m_bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); + m_autoSelectDelay = KGlobalSettings::autoSelectDelay(); + + if( !m_bUseSingle || !m_bChangeCursorOverItem ) + viewport()->unsetCursor(); + +} +*/ +void KListBox::slotAutoSelect() +{ + // check that the item still exists + if( index( m_pCurrentItem ) == -1 ) + return; + + //Give this widget the keyboard focus. + if( !hasFocus() ) + setFocus(); + +#ifdef Q_WS_X11 //FIXME + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); +#endif + + QListBoxItem* previousItem = item( currentItem() ); + setCurrentItem( m_pCurrentItem ); + + if( m_pCurrentItem ) { +#ifndef Q_WS_QWS //FIXME + //Shift pressed? + if( (keybstate & ShiftMask) ) { +#endif + bool block = signalsBlocked(); + blockSignals( true ); + +#ifndef Q_WS_QWS //FIXME + //No Ctrl? Then clear before! + if( !(keybstate & ControlMask) ) + clearSelection(); +#endif + +//US in my QT version it is called isSelected() So what is right? +//US bool select = !m_pCurrentItem->isSelected(); + bool select = !m_pCurrentItem->selected(); + bool update = viewport()->isUpdatesEnabled(); + viewport()->setUpdatesEnabled( false ); + + bool down = index( previousItem ) < index( m_pCurrentItem ); + QListBoxItem* it = down ? previousItem : m_pCurrentItem; + for (;it ; it = it->next() ) { + if ( down && it == m_pCurrentItem ) { + setSelected( m_pCurrentItem, select ); + break; + } + if ( !down && it == previousItem ) { + setSelected( previousItem, select ); + break; + } + setSelected( it, select ); + } + + blockSignals( block ); + viewport()->setUpdatesEnabled( update ); + triggerUpdate( false ); + + emit selectionChanged(); + + if( selectionMode() == QListBox::Single ) + emit selectionChanged( m_pCurrentItem ); + } +#ifndef Q_WS_QWS //FIXME + else if( (keybstate & ControlMask) ) + setSelected( m_pCurrentItem, !m_pCurrentItem->isSelected() ); +#endif + else { + bool block = signalsBlocked(); + blockSignals( true ); + +//US in my QT version it is called isSelected() So what is right? +//US if( !m_pCurrentItem->isSelected() ) + if( !m_pCurrentItem->selected() ) + clearSelection(); + + blockSignals( block ); + + setSelected( m_pCurrentItem, true ); + } +#ifndef Q_WS_QWS //FIXME + } + else + kdDebug() << "Thats not supposed to happen!!!!" << endl; +#endif +} + +void KListBox::emitExecute( QListBoxItem *item, const QPoint &pos ) +{ +#ifdef Q_WS_X11 //FIXME + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); +#endif + + m_pAutoSelect->stop(); + +#ifndef Q_WS_QWS //FIXME + //Dont emit executed if in SC mode and Shift or Ctrl are pressed + if( !( m_bUseSingle && ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { +#endif + emit executed( item ); + emit executed( item, pos ); +#ifndef Q_WS_QWS //FIXME + } +#endif +} + +// +// 2000-16-01 Espen Sand +// This widget is used in dialogs. It should ignore +// F1 (and combinations) and Escape since these are used +// to start help or close the dialog. This functionality +// should be done in QListView but it is not (at least now) +// +void KListBox::keyPressEvent(QKeyEvent *e) +{ + if( e->key() == Key_Escape ) + { + e->ignore(); + } + else if( e->key() == Key_F1 ) + { + e->ignore(); + } + else + { + QListBox::keyPressEvent(e); + } +} + +void KListBox::focusOutEvent( QFocusEvent *fe ) +{ + m_pAutoSelect->stop(); + + QListBox::focusOutEvent( fe ); +} + +void KListBox::leaveEvent( QEvent *e ) +{ + m_pAutoSelect->stop(); + + QListBox::leaveEvent( e ); +} + +void KListBox::contentsMousePressEvent( QMouseEvent *e ) +{ + if( (selectionMode() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) { + bool block = signalsBlocked(); + blockSignals( true ); + + clearSelection(); + + blockSignals( block ); + } + + QListBox::contentsMousePressEvent( e ); +} + +void KListBox::contentsMouseDoubleClickEvent ( QMouseEvent * e ) +{ + QListBox::contentsMouseDoubleClickEvent( e ); + + QListBoxItem* item = itemAt( e->pos() ); + + if( item ) { + emit doubleClicked( item, e->globalPos() ); + + if( (e->button() == LeftButton) && !m_bUseSingle ) + emitExecute( item, e->globalPos() ); + } +} + +void KListBox::slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos ) +{ + if( (btn == LeftButton) && item ) + emitExecute( item, pos ); +} + +void KListBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klistbox.moc" diff --git a/microkde/kdeui/klistbox.h b/microkde/kdeui/klistbox.h new file mode 100644 index 0000000..8023780 --- a/dev/null +++ b/microkde/kdeui/klistbox.h @@ -0,0 +1,141 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLISTBOX_H +#define KLISTBOX_H + +#include <qlistbox.h> + +/** + * Extends the functionality of @ref QListBox to honor the system + * wide settings for Single Click/Double Click mode, Auto Selection and + * Change Cursor over Link. + * + * There is a new signal @ref executed(). It gets connected to either + * @ref QListBox::clicked() or @ref QListBox::doubleClicked() + * depending on the KDE wide Single Click/Double Click settings. It is + * strongly recomended that you use this signal instead of the above + * mentioned. This way you don't need to care about the current + * settings. If you want to get informed when the user selects + * something connect to the @ref QListBox::selectionChanged() signal. + * + * @short A variant of @ref QListBox that honors KDE's system-wide settings. + **/ +class KListBox : public QListBox +{ + Q_OBJECT + +public: + KListBox( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + +signals: + + /** + * Emitted whenever the user executes an listbox item. + * + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listbox item. + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + */ + void executed( QListBoxItem *item ); + + /** + * Emitted whenever the user executes an listbox item. + * + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listbox item. + * @param pos is the position where the user has clicked + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + */ + void executed( QListBoxItem *item, const QPoint &pos ); + + /** + * This signal gets emitted whenever the user double clicks into the + * listbox. + * + * @param item The pointer to the clicked listbox item. + * @param pos The position where the user has clicked. + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + * + * This signal is more or less here for the sake of completeness. + * You should normally not need to use this. In most cases it's better + * to use @ref executed() instead. + */ + void doubleClicked( QListBoxItem *item, const QPoint &pos ); + +protected slots: + void slotOnItem( QListBoxItem *item ); + void slotOnViewport(); + +//US void slotSettingsChanged(int); + + /** + * Auto selection happend. + */ + void slotAutoSelect(); + +protected: + void emitExecute( QListBoxItem *item, const QPoint &pos ); + + /** + * @reimplemented + */ + virtual void keyPressEvent(QKeyEvent *e); + /** + * @reimplemented + */ + virtual void focusOutEvent( QFocusEvent *fe ); + /** + * @reimplemented + */ + virtual void leaveEvent( QEvent *e ); + /** + * @reimplemented + */ + virtual void contentsMousePressEvent( QMouseEvent *e ); + /** + * @reimplemented + */ + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + + bool m_bUseSingle; +//US bool m_bChangeCursorOverItem; + + QListBoxItem* m_pCurrentItem; + + QTimer* m_pAutoSelect; + int m_autoSelectDelay; + +private slots: + void slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListBoxPrivate; + KListBoxPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/klistview.cpp b/microkde/kdeui/klistview.cpp new file mode 100644 index 0000000..b53a88a --- a/dev/null +++ b/microkde/kdeui/klistview.cpp @@ -0,0 +1,2191 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2000 Charles Samuels <charles@kde.org> + Copyright (C) 2000 Peter Putzer + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdragobject.h> +#include <qtimer.h> +#include <qheader.h> +#include <qcursor.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qpainter.h> + +#include <kglobalsettings.h> +#include <kconfig.h> +#include <kconfigbase.h> +//US #include <kcursor.h> +#include <kapplication.h> +//US #include <kipc.h> +#include <kdebug.h> +#ifdef _WIN32_ +#define Q_WS_QWS +#endif +#ifndef _WIN32_ +#define private public +#include <qlistview.h> +#undef private +#endif +#include "klistview.h" +//US #include "klistviewlineedit.h" +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + +// /*US +class KListView::Tooltip : public QToolTip +{ +public: + Tooltip (KListView* parent, QToolTipGroup* group = 0L); + virtual ~Tooltip () {} + +protected: + // */ + /** + * Reimplemented from QToolTip for internal reasons. + */ + // /*US + virtual void maybeTip (const QPoint&); + +private: + KListView* mParent; +}; + +KListView::Tooltip::Tooltip (KListView* parent, QToolTipGroup* group) + : QToolTip (parent, group), + mParent (parent) +{ +} + +void KListView::Tooltip::maybeTip (const QPoint&) +{ + // FIXME +} +// */ + +class KListView::KListViewPrivate +{ +public: + KListViewPrivate (KListView* listview) + : pCurrentItem (0L), + autoSelectDelay(1), +//US dragDelay (KGlobalSettings::dndEventDelay()), + + dragDelay (10), +//US editor (new KListViewLineEdit (listview)), + cursorInExecuteArea(false), + bUseSingle(false), + bChangeCursorOverItem(false), + itemsMovable (true), + selectedBySimpleMove(false), + selectedUsingMouse(false), + showContextMenusOnPress(true), + itemsRenameable (false), + validDrag (false), + dragEnabled (false), + autoOpen (true), + dropVisualizer (true), + dropHighlighter (false), + createChildren (true), + pressedOnSelected (false), + wasShiftEvent (false), + fullWidth (false), + sortAscending(true), + tabRename(true), + sortColumn(0), + selectionDirection(0), + tooltipColumn (0), + selectionMode (Single), +//US contextMenuKey (KGlobalSettings::contextMenuKey()), +//US showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()), + mDropVisualizerWidth (4) + { + renameable += 0; +//US connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int))); + } + + ~KListViewPrivate () + { +//US delete editor; + } + + QListViewItem* pCurrentItem; + + QTimer autoSelect; + int autoSelectDelay; + + QTimer dragExpand; + QListViewItem* dragOverItem; + QPoint dragOverPoint; + + QPoint startDragPos; + int dragDelay; + +//US KListViewLineEdit *editor; + QValueList<int> renameable; + + bool cursorInExecuteArea:1; + bool bUseSingle:1; + bool bChangeCursorOverItem:1; + bool itemsMovable:1; + bool selectedBySimpleMove : 1; + bool selectedUsingMouse:1; + bool itemsRenameable:1; + bool validDrag:1; + bool dragEnabled:1; + bool autoOpen:1; + bool dropVisualizer:1; + bool dropHighlighter:1; + bool createChildren:1; + bool pressedOnSelected:1; + bool wasShiftEvent:1; + bool fullWidth:1; + bool sortAscending:1; + bool tabRename:1; + + int sortColumn; + + //+1 means downwards (y increases, -1 means upwards, 0 means not selected), aleXXX + int selectionDirection; + int tooltipColumn; + + SelectionModeExt selectionMode; + int contextMenuKey; + bool showContextMenusOnPress; + + QRect mOldDropVisualizer; + int mDropVisualizerWidth; + QRect mOldDropHighlighter; + QListViewItem *afterItemDrop; + QListViewItem *parentItemDrop; + + QColor alternateBackground; +}; + +/*US +KListViewLineEdit::KListViewLineEdit(KListView *parent) + : KLineEdit(parent->viewport()), item(0), col(0), p(parent) +{ + setFrame( false ); + hide(); + connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() )); +} + +KListViewLineEdit::~KListViewLineEdit() +{ +} + +void KListViewLineEdit::load(QListViewItem *i, int c) +{ + item=i; + col=c; + + QRect rect(p->itemRect(i)); + setText(item->text(c)); + + int fieldX = rect.x() - 1; + int fieldW = p->columnWidth(col) + 2; + + int pos = p->header()->mapToIndex(col); + for ( int index = 0; index < pos; index++ ) + fieldX += p->columnWidth( p->header()->mapToSection( index )); + + if ( col == 0 ) { + int d = i->depth() + (p->rootIsDecorated() ? 1 : 0); + d *= p->treeStepSize(); + fieldX += d; + fieldW -= d; + } + + if ( i->pixmap( col ) ) {// add width of pixmap + int d = i->pixmap( col )->width(); + fieldX += d; + fieldW -= d; + } + + setGeometry(fieldX, rect.y() - 1, fieldW, rect.height() + 2); + show(); + setFocus(); +} +*/ +/* Helper functions to for + * tabOrderedRename functionality. + */ + +static int nextCol (KListView *pl, QListViewItem *pi, int start, int dir) +{ + if (pi) + { + // Find the next renameable column in the current row + for (; ((dir == +1) ? (start < pl->columns()) : (start >= 0)); start += dir) + if (pl->isRenameable(start)) + return start; + } + + return -1; +} + +static QListViewItem *prevItem (QListViewItem *pi) +{ + QListViewItem *pa = pi->itemAbove(); + + /* Does what the QListViewItem::previousSibling() + * of my dreams would do. + */ + if (pa && pa->parent() == pi->parent()) + return pa; + + return NULL; +} + +static QListViewItem *lastQChild (QListViewItem *pi) +{ + if (pi) + { + /* Since there's no QListViewItem::lastChild(). + * This finds the last sibling for the given + * item. + */ + for (QListViewItem *pt = pi->nextSibling(); pt; pt = pt->nextSibling()) + pi = pt; + } + + return pi; +} +/*US +void KListViewLineEdit::selectNextCell (QListViewItem *pitem, int column, bool forward) +{ + const int ncols = p->columns(); + const int dir = forward ? +1 : -1; + const int restart = forward ? 0 : (ncols - 1); + QListViewItem *top = (pitem && pitem->parent()) + ? pitem->parent()->firstChild() + : p->firstChild(); + QListViewItem *pi = pitem; + + terminate(); // Save current changes + + do + { +*/ + /* Check the rest of the current row for an editable column, + * if that fails, check the entire next/previous row. The + * last case goes back to the first item in the current branch + * or the last item in the current branch depending on the + * direction. + */ +/*US + if ((column = nextCol(p, pi, column + dir, dir)) != -1 || + (column = nextCol(p, (pi = (forward ? pi->nextSibling() : prevItem(pi))), restart, dir)) != -1 || + (column = nextCol(p, (pi = (forward ? top : lastQChild(pitem))), restart, dir)) != -1) + { + if (pi) + { + p->setCurrentItem(pi); // Calls terminate + p->rename(pi, column); +*/ + /* Some listviews may override rename() to + * prevent certain items from being renamed, + * if this is done, [m_]item will be NULL + * after the rename() call... try again. + */ +/*US + if (!item) + continue; + + break; + } + } + } + while (pi && !item); +} +*/ + +/*US +#ifdef KeyPress +#undef KeyPress +#endif + +bool KListViewLineEdit::event (QEvent *pe) +{ + if (pe->type() == QEvent::KeyPress) + { + QKeyEvent *k = (QKeyEvent *) pe; + + if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab) && + p->tabOrderedRenaming() && p->itemsRenameable() && + !(k->state() & ControlButton || k->state() & AltButton)) + { + selectNextCell(item, col, + (k->key() == Key_Tab && !(k->state() & ShiftButton))); + return true; + } + } + + return KLineEdit::event(pe); +} + +void KListViewLineEdit::keyPressEvent(QKeyEvent *e) +{ + if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) + terminate(true); + else if(e->key() == Qt::Key_Escape) + terminate(false); + else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Up) + { + terminate(true); + KLineEdit::keyPressEvent(e); + } + else + KLineEdit::keyPressEvent(e); +} + +void KListViewLineEdit::terminate() +{ + terminate(true); +} + +void KListViewLineEdit::terminate(bool commit) +{ + if ( item ) + { + //kdDebug() << "KListViewLineEdit::terminate " << commit << endl; + if (commit) + item->setText(col, text()); + int c=col; + QListViewItem *i=item; + col=0; + item=0; + hide(); // will call focusOutEvent, that's why we set item=0 before + emit done(i,c); + } +} + +void KListViewLineEdit::focusOutEvent(QFocusEvent *ev) +{ + QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev); + // Don't let a RMB close the editor + if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow) + terminate(true); +} + +void KListViewLineEdit::paintEvent( QPaintEvent *e ) +{ + KLineEdit::paintEvent( e ); + + if ( !frame() ) { + QPainter p( this ); + p.setClipRegion( e->region() ); + p.drawRect( rect() ); + } +} + +// selection changed -> terminate. As our "item" can be already deleted, +// we can't call terminate(false), because that would emit done() with +// a dangling pointer to "item". +void KListViewLineEdit::slotSelectionChanged() +{ + item = 0; + col = 0; + hide(); +} +*/ + +KListView::KListView( QWidget *parent, const char *name ) + : QListView( parent, name ), + d (new KListViewPrivate (this)) +{ +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold ); +#endif +//US setDragAutoScroll(true); + + connect( this, SIGNAL( onViewport() ), + this, SLOT( slotOnViewport() ) ); + connect( this, SIGNAL( onItem( QListViewItem * ) ), + this, SLOT( slotOnItem( QListViewItem * ) ) ); + + connect (this, SIGNAL(contentsMoving(int,int)), + this, SLOT(cleanDropVisualizer())); + connect (this, SIGNAL(contentsMoving(int,int)), + this, SLOT(cleanItemHighlighter())); + +/*US + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + + if (kapp) + { + connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); + kapp->addKipcEventMask( KIPC::SettingsChanged ); + } +*/ + slotSettingsChanged(1); //US do this to initialize the connections + + + connect(&d->autoSelect, SIGNAL( timeout() ), + this, SLOT( slotAutoSelect() ) ); + connect(&d->dragExpand, SIGNAL( timeout() ), + this, SLOT( slotDragExpand() ) ); + + // context menu handling + if (d->showContextMenusOnPress) + { + connect (this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + else + { + connect (this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + + connect (this, SIGNAL (menuShortCutPressed (KListView*, QListViewItem*)), + this, SLOT (emitContextMenu (KListView*, QListViewItem*))); + + + //qDebug("KListView::KListView make alternate color configurable"); +//US d->alternateBackground = KGlobalSettings::alternateBackgroundColor(); + d->alternateBackground = QColor(240, 240, 240); +} + + + +KListView::~KListView() +{ + delete d; +} + +bool KListView::isExecuteArea( const QPoint& point ) +{ + if ( itemAt( point ) ) + return isExecuteArea( point.x() ); + + return false; +} + +bool KListView::isExecuteArea( int x ) +{ + if( allColumnsShowFocus() ) + return true; + else { + int offset = 0; + int width = columnWidth( 0 ); + int pos = header()->mapToIndex( 0 ); + + for ( int index = 0; index < pos; index++ ) + offset += columnWidth( header()->mapToSection( index ) ); + + x += contentsX(); // in case of a horizontal scrollbar + return ( x > offset && x < ( offset + width ) ); + } +} + +void KListView::slotOnItem( QListViewItem *item ) +{ + QPoint vp = viewport()->mapFromGlobal( QCursor::pos() ); + if ( item && isExecuteArea( vp.x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) { + d->autoSelect.start( d->autoSelectDelay, true ); + d->pCurrentItem = item; + } +} + +void KListView::slotOnViewport() +{ + if ( d->bChangeCursorOverItem ) + viewport()->unsetCursor(); + + d->autoSelect.stop(); + d->pCurrentItem = 0L; +} + +void KListView::slotSettingsChanged(int category) +{ +qDebug("KListView::slotSettingsChanged has to be verified"); +/*US + + switch (category) + { + case KApplication::SETTINGS_MOUSE: + d->dragDelay = KGlobalSettings::dndEventDelay(); + d->bUseSingle = KGlobalSettings::singleClick(); + + disconnect(this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked (int, QListViewItem*, const QPoint &, int))); + + if( d->bUseSingle ) + connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); + + d->bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); + d->autoSelectDelay = KGlobalSettings::autoSelectDelay(); + + if( !d->bUseSingle || !d->bChangeCursorOverItem ) + viewport()->unsetCursor(); + + break; + + case KApplication::SETTINGS_POPUPMENU: + d->contextMenuKey = KGlobalSettings::contextMenuKey (); + d->showContextMenusOnPress = KGlobalSettings::showContextMenusOnPress (); + + if (d->showContextMenusOnPress) + { + disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + + connect(this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + else + { + disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + + connect(this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + break; + + default: + break; + } +*/ + + if( d->bUseSingle ) + connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); + +} + +void KListView::slotAutoSelect() +{ + // check that the item still exists + if( itemIndex( d->pCurrentItem ) == -1 ) + return; + + if (!isActiveWindow()) + { + d->autoSelect.stop(); + return; + } + + //Give this widget the keyboard focus. + if( !hasFocus() ) + setFocus(); + + QListViewItem* previousItem = currentItem(); + setCurrentItem( d->pCurrentItem ); + +#if 0 +#ifndef Q_WS_QWS + // FIXME(E): Implement for Qt Embedded + if( d->pCurrentItem ) { + //Shift pressed? + if( (keybstate & ShiftMask) ) { + bool block = signalsBlocked(); + blockSignals( true ); + + //No Ctrl? Then clear before! + if( !(keybstate & ControlMask) ) + clearSelection(); + + bool select = !d->pCurrentItem->isSelected(); + bool update = viewport()->isUpdatesEnabled(); + viewport()->setUpdatesEnabled( false ); + + bool down = previousItem->itemPos() < d->pCurrentItem->itemPos(); + QListViewItemIterator lit( down ? previousItem : d->pCurrentItem ); + for ( ; lit.current(); ++lit ) { + if ( down && lit.current() == d->pCurrentItem ) { + d->pCurrentItem->setSelected( select ); + break; + } + if ( !down && lit.current() == previousItem ) { + previousItem->setSelected( select ); + break; + } + lit.current()->setSelected( select ); + } + + blockSignals( block ); + viewport()->setUpdatesEnabled( update ); + triggerUpdate(); + + emit selectionChanged(); + + if( selectionMode() == QListView::Single ) + emit selectionChanged( d->pCurrentItem ); + } + else if( (keybstate & ControlMask) ) + setSelected( d->pCurrentItem, !d->pCurrentItem->isSelected() ); + else { + bool block = signalsBlocked(); + blockSignals( true ); + + if( !d->pCurrentItem->isSelected() ) + clearSelection(); + + blockSignals( block ); + + setSelected( d->pCurrentItem, true ); + } + } + else + kdDebug() << "KListView::slotAutoSelect: Thats not supposed to happen!!!!" << endl; +#endif +#endif +} + +void KListView::slotHeaderChanged() +{ + if (d->fullWidth && columns()) + { + int w = 0; + for (int i = 0; i < columns() - 1; ++i) w += columnWidth(i); + setColumnWidth( columns() - 1, viewport()->width() - w - 1 ); + } +} + +void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c ) +{ + if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) { + + // Double click mode ? + if ( !d->bUseSingle ) + { + emit executed( item ); + emit executed( item, pos, c ); + } + else + { +#if 0 +#ifndef Q_WS_QWS + // FIXME(E): Implement for Qt Embedded + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); + + d->autoSelect.stop(); + + //Dont emit executed if in SC mode and Shift or Ctrl are pressed + if( !( ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { + emit executed( item ); + emit executed( item, pos, c ); + } +#endif +#endif + } + } +} + +void KListView::focusInEvent( QFocusEvent *fe ) +{ + // kdDebug()<<"KListView::focusInEvent()"<<endl; + QListView::focusInEvent( fe ); + if ((d->selectedBySimpleMove) + && (d->selectionMode == FileManager) + && (fe->reason()!=QFocusEvent::Popup) + && (fe->reason()!=QFocusEvent::ActiveWindow) + && (currentItem()!=0)) + { + currentItem()->setSelected(true); + currentItem()->repaint(); + emit selectionChanged(); + }; +} + +void KListView::focusOutEvent( QFocusEvent *fe ) +{ + cleanDropVisualizer(); + cleanItemHighlighter(); + + d->autoSelect.stop(); + + if ((d->selectedBySimpleMove) + && (d->selectionMode == FileManager) + && (fe->reason()!=QFocusEvent::Popup) + && (fe->reason()!=QFocusEvent::ActiveWindow) + && (currentItem()!=0) +/*US && (!d->editor->isVisible()) */ + ) + { + currentItem()->setSelected(false); + currentItem()->repaint(); + emit selectionChanged(); + }; + + QListView::focusOutEvent( fe ); +} + +void KListView::leaveEvent( QEvent *e ) +{ + d->autoSelect.stop(); + + QListView::leaveEvent( e ); +} + +bool KListView::event( QEvent *e ) +{ + if (e->type() == QEvent::ApplicationPaletteChange) { +qDebug("KListView::event make alternate color configurable"); +//US d->alternateBackground=KGlobalSettings::alternateBackgroundColor(); + d->alternateBackground = QColor(240, 240, 240); + } + + return QListView::event(e); +} + +void KListView::contentsMousePressEvent( QMouseEvent *e ) +{ + if( (selectionModeExt() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) + { + bool block = signalsBlocked(); + blockSignals( true ); + + clearSelection(); + + blockSignals( block ); + } + else if ((selectionModeExt()==FileManager) && (d->selectedBySimpleMove)) + { + d->selectedBySimpleMove=false; + d->selectedUsingMouse=true; + if (currentItem()!=0) + { + currentItem()->setSelected(false); + currentItem()->repaint(); +// emit selectionChanged(); + }; + }; + + QPoint p( contentsToViewport( e->pos() ) ); + QListViewItem *at = itemAt (p); + + // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) + bool rootDecoClicked = at + && ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) + && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); + + if (e->button() == LeftButton && !rootDecoClicked) + { + //Start a drag + d->startDragPos = e->pos(); + + if (at) + { + d->validDrag = true; + d->pressedOnSelected = at->isSelected(); + } + } + + QListView::contentsMousePressEvent( e ); +} + +void KListView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if (!dragEnabled() || d->startDragPos.isNull() || !d->validDrag) { + QListView::contentsMouseMoveEvent (e); + return; + } + + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt( vp ); + + //do we process cursor changes at all? + if ( item && d->bChangeCursorOverItem && d->bUseSingle ) + { + //Cursor moved on a new item or in/out the execute area + if( (item != d->pCurrentItem) || + (isExecuteArea(vp) != d->cursorInExecuteArea) ) + { + d->cursorInExecuteArea = isExecuteArea(vp); +qDebug("KListView::contentsMouseMoveEvent drag&drop not supported yet"); +/*US + if( d->cursorInExecuteArea ) //cursor moved in execute area + viewport()->setCursor( KCursor::handCursor() ); + else //cursor moved out of execute area + viewport()->unsetCursor(); +*/ + } + } + + bool dragOn = dragEnabled(); + QPoint newPos = e->pos(); + if (dragOn && d->validDrag && + (newPos.x() > d->startDragPos.x()+d->dragDelay || + newPos.x() < d->startDragPos.x()-d->dragDelay || + newPos.y() > d->startDragPos.y()+d->dragDelay || + newPos.y() < d->startDragPos.y()-d->dragDelay)) + //(d->startDragPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) + { + QListView::contentsMouseReleaseEvent( 0 ); + startDrag(); + d->startDragPos = QPoint(); + d->validDrag = false; + } +} + +void KListView::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + if (e->button() == LeftButton) + { + // If the row was already selected, maybe we want to start an in-place editing + if ( d->pressedOnSelected && itemsRenameable() ) + { + QPoint p( contentsToViewport( e->pos() ) ); + QListViewItem *at = itemAt (p); + if ( at ) + { + // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) + bool rootDecoClicked = + ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) + && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); + + if (!rootDecoClicked) + { + int col = header()->mapToLogical( header()->cellAt( p.x() ) ); + if ( d->renameable.contains(col) ) + rename(at, col); + } + } + } + + d->pressedOnSelected = false; + d->validDrag = false; + d->startDragPos = QPoint(); + } + QListView::contentsMouseReleaseEvent( e ); +} + +void KListView::contentsMouseDoubleClickEvent ( QMouseEvent *e ) +{ + // We don't want to call the parent method because it does setOpen, + // whereas we don't do it in single click mode... (David) + //QListView::contentsMouseDoubleClickEvent( e ); + + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt( vp ); + emit QListView::doubleClicked( item ); // we do it now + + int col = item ? header()->mapToLogical( header()->cellAt( vp.x() ) ) : -1; + + if( item ) { + emit doubleClicked( item, e->globalPos(), col ); + + if( (e->button() == LeftButton) && !d->bUseSingle ) + emitExecute( item, e->globalPos(), col ); + } +} + +void KListView::slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ) +{ + if( (btn == LeftButton) && item ) + emitExecute(item, pos, c); +} + +void KListView::contentsDropEvent(QDropEvent* e) +{ +qDebug("KListView::contentsDropEvent drag&drop not supported yet"); +/*US + cleanDropVisualizer(); + cleanItemHighlighter(); + d->dragExpand.stop(); + + if (acceptDrag (e)) + { + e->acceptAction(); + QListViewItem *afterme; + QListViewItem *parent; + findDrop(e->pos(), parent, afterme); + + if (e->source() == viewport() && itemsMovable()) + movableDropEvent(parent, afterme); + else + { + + emit dropped(e, afterme); + emit dropped(this, e, afterme); + emit dropped(e, parent, afterme); + emit dropped(this, e, parent, afterme); + + } + } +*/ + +} + +void KListView::movableDropEvent (QListViewItem* parent, QListViewItem* afterme) +{ + QPtrList<QListViewItem> items, afterFirsts, afterNows; + QListViewItem *current=currentItem(); + bool hasMoved=false; + for (QListViewItem *i = firstChild(), *iNext=0; i != 0; i = iNext) + { + iNext=i->itemBelow(); + if (!i->isSelected()) + continue; + + // don't drop an item after itself, or else + // it moves to the top of the list + if (i==afterme) + continue; + + i->setSelected(false); + + QListViewItem *afterFirst = i->itemAbove(); + + if (!hasMoved) + { + emit aboutToMove(); + hasMoved=true; + } + + moveItem(i, parent, afterme); + + // ###### This should include the new parent !!! -> KDE 3.0 + // If you need this right now, have a look at keditbookmarks. + emit moved(i, afterFirst, afterme); + + items.append (i); + afterFirsts.append (afterFirst); + afterNows.append (afterme); + + afterme = i; + } + clearSelection(); + for (QListViewItem *i=items.first(); i != 0; i=items.next() ) + i->setSelected(true); + if (current) + setCurrentItem(current); + + emit moved(items,afterFirsts,afterNows); + + if (firstChild()) + emit moved(); +} + +void KListView::contentsDragMoveEvent(QDragMoveEvent *event) +{ +qDebug("KListView::contentsDropEvent drag&drop not supported yet"); +/*US + if (acceptDrag(event)) + { + event->acceptAction(); + //Clean up the view + + findDrop(event->pos(), d->parentItemDrop, d->afterItemDrop); + QPoint vp = contentsToViewport( event->pos() ); + QListViewItem *item = isExecuteArea( vp ) ? itemAt( vp ) : 0L; + + if ( item != d->dragOverItem ) + { + d->dragExpand.stop(); + d->dragOverItem = item; + d->dragOverPoint = vp; + if ( d->dragOverItem && d->dragOverItem->isExpandable() && !d->dragOverItem->isOpen() ) + d->dragExpand.start( QApplication::startDragTime(), true ); + } + if (dropVisualizer()) + { + QRect tmpRect = drawDropVisualizer(0, d->parentItemDrop, d->afterItemDrop); + if (tmpRect != d->mOldDropVisualizer) + { + cleanDropVisualizer(); + d->mOldDropVisualizer=tmpRect; + viewport()->repaint(tmpRect); + } + } + if (dropHighlighter()) + { + QRect tmpRect = drawItemHighlighter(0, d->afterItemDrop); + if (tmpRect != d->mOldDropHighlighter) + { + cleanItemHighlighter(); + d->mOldDropHighlighter=tmpRect; + viewport()->repaint(tmpRect); + } + } + } + else + event->ignore(); +*/ +} + +void KListView::slotDragExpand() +{ + if ( itemAt( d->dragOverPoint ) == d->dragOverItem ) + d->dragOverItem->setOpen( true ); +} + +void KListView::contentsDragLeaveEvent (QDragLeaveEvent*) +{ + d->dragExpand.stop(); + cleanDropVisualizer(); + cleanItemHighlighter(); +} + +void KListView::cleanDropVisualizer() +{ + if (d->mOldDropVisualizer.isValid()) + { + QRect rect=d->mOldDropVisualizer; + d->mOldDropVisualizer = QRect(); + viewport()->repaint(rect, true); + } +} + +int KListView::depthToPixels( int depth ) +{ + return treeStepSize() * ( depth + (rootIsDecorated() ? 1 : 0) ) + itemMargin(); +} + +void KListView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after) +{ + QPoint p (contentsToViewport(pos)); + + // Get the position to put it in + QListViewItem *atpos = itemAt(p); + + QListViewItem *above; + if (!atpos) // put it at the end + above = lastItem(); + else + { + // Get the closest item before us ('atpos' or the one above, if any) + if (p.y() - itemRect(atpos).topLeft().y() < (atpos->height()/2)) + above = atpos->itemAbove(); + else + above = atpos; + } + + if (above) + { + // Now, we know we want to go after "above". But as a child or as a sibling ? + // We have to ask the "above" item if it accepts children. + if (above->isExpandable()) + { + // The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children + if (p.x() >= depthToPixels( above->depth() + 1 ) || + (above->isOpen() && above->childCount() > 0) ) + { + parent = above; + after = 0L; + return; + } + } + + // Ok, there's one more level of complexity. We may want to become a new + // sibling, but of an upper-level group, rather than the "above" item + QListViewItem * betterAbove = above->parent(); + QListViewItem * last = above; + while ( betterAbove ) + { + // We are allowed to become a sibling of "betterAbove" only if we are + // after its last child + if ( last->nextSibling() == 0 ) + { + if (p.x() < depthToPixels ( betterAbove->depth() + 1 )) + above = betterAbove; // store this one, but don't stop yet, there may be a better one + else + break; // not enough on the left, so stop + last = betterAbove; + betterAbove = betterAbove->parent(); // up one level + } else + break; // we're among the child of betterAbove, not after the last one + } + } + // set as sibling + after = above; + parent = after ? after->parent() : 0L ; +} + +QListViewItem* KListView::lastChild () const +{ + QListViewItem* lastchild = firstChild(); + + if (lastchild) + for (; lastchild->nextSibling(); lastchild = lastchild->nextSibling()); + + return lastchild; +} + +QListViewItem *KListView::lastItem() const +{ + QListViewItem* last = lastChild(); + + for (QListViewItemIterator it (last); it.current(); ++it) + last = it.current(); + + return last; +} + +KLineEdit *KListView::renameLineEdit() const +{ +//US return d->editor; +qDebug("KListView::renameLineEdit returns 0. Might crash"); +return 0; +} + +void KListView::startDrag() +{ +qDebug("KListView::startDrag drag&drop not supported yet."); +/*US + QDragObject *drag = dragObject(); + + if (!drag) + return; + + if (drag->drag() && drag->target() != viewport()) + emit moved(); +*/ +} + +QDragObject *KListView::dragObject() +{ + if (!currentItem()) + return 0; + + return new QStoredDrag("application/x-qlistviewitem", viewport()); +} + +void KListView::setItemsMovable(bool b) +{ + d->itemsMovable=b; +} + +bool KListView::itemsMovable() const +{ + return d->itemsMovable; +} + +void KListView::setItemsRenameable(bool b) +{ + d->itemsRenameable=b; +} + +bool KListView::itemsRenameable() const +{ + return d->itemsRenameable; +} + + +void KListView::setDragEnabled(bool b) +{ + d->dragEnabled=b; +} + +bool KListView::dragEnabled() const +{ + return d->dragEnabled; +} + +void KListView::setAutoOpen(bool b) +{ + d->autoOpen=b; +} + +bool KListView::autoOpen() const +{ + return d->autoOpen; +} + +bool KListView::dropVisualizer() const +{ + return d->dropVisualizer; +} + +void KListView::setDropVisualizer(bool b) +{ + d->dropVisualizer=b; +} + +QPtrList<QListViewItem> KListView::selectedItems() const +{ + QPtrList<QListViewItem> list; + for (QListViewItem *i=firstChild(); i!=0; i=i->itemBelow()) + if (i->isSelected()) list.append(i); + return list; +} + + +void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after) +{ + // sanity check - don't move a item into it's own child structure + QListViewItem *i = parent; + while(i) + { + if(i == item) + return; + i = i->parent(); + } + + // Basically reimplementing the QListViewItem(QListViewItem*, QListViewItem*) constructor + // in here, without ever deleting the item. + if (item->parent()) + item->parent()->takeItem(item); + else + takeItem(item); + + if (parent) + parent->insertItem(item); + else + insertItem(item); + + if (after) + ;//item->moveToJustAfter(after); +} + +void KListView::contentsDragEnterEvent(QDragEnterEvent *event) +{ +qDebug("KListView::contentsDragEnterEvent drag&drop not supported yet."); +/*US + if (acceptDrag (event)) + event->accept(); +*/ +} + +void KListView::setDropVisualizerWidth (int w) +{ + d->mDropVisualizerWidth = w > 0 ? w : 1; +} + +QRect KListView::drawDropVisualizer(QPainter *p, QListViewItem *parent, + QListViewItem *after) +{ + QRect insertmarker; + + if (!after && !parent) + insertmarker = QRect (0, 0, viewport()->width(), d->mDropVisualizerWidth/2); + else + { + int level = 0; + if (after) + { + QListViewItem* it = 0L; + if (after->isOpen()) + { + // Look for the last child (recursively) + it = after->firstChild(); + if (it) + while (it->nextSibling() || it->firstChild()) + if ( it->nextSibling() ) + it = it->nextSibling(); + else + it = it->firstChild(); + } + + insertmarker = itemRect (it ? it : after); + level = after->depth(); + } + else if (parent) + { + insertmarker = itemRect (parent); + level = parent->depth() + 1; + } + insertmarker.setLeft( treeStepSize() * ( level + (rootIsDecorated() ? 1 : 0) ) + itemMargin() ); + insertmarker.setRight (viewport()->width()); + insertmarker.setTop (insertmarker.bottom() - d->mDropVisualizerWidth/2 + 1); + insertmarker.setBottom (insertmarker.bottom() + d->mDropVisualizerWidth/2); + } + + // This is not used anymore, at least by KListView itself (see viewportPaintEvent) + // Remove for KDE 3.0. + if (p) + p->fillRect(insertmarker, Dense4Pattern); + + return insertmarker; +} + +QRect KListView::drawItemHighlighter(QPainter *painter, QListViewItem *item) +{ + QRect r; + + if (item) + { + r = itemRect(item); + r.setLeft(r.left()+(item->depth()+1)*treeStepSize()); + if (painter) { +//US style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(), +//US QStyle::Style_FocusAtBorder, colorGroup().highlight()); + const QColor* pHighl = &(colorGroup().highlight()); + //LR style().drawFocusRect(painter, r, colorGroup(), pHighl, true); + +qDebug("KListView::drawItemHighlighter has to be verified"); + + } + + } + + return r; +} + +void KListView::cleanItemHighlighter () +{ + if (d->mOldDropHighlighter.isValid()) + { + QRect rect=d->mOldDropHighlighter; + d->mOldDropHighlighter = QRect(); + viewport()->repaint(rect, true); + } +} + +void KListView::rename(QListViewItem *item, int c) +{ + if (d->renameable.contains(c)) + { + ensureItemVisible(item); +//US d->editor->load(item,c); +qDebug("KListView::rename has to be verified"); + + } +} + +bool KListView::isRenameable (int col) const +{ + return d->renameable.contains(col); +} + +void KListView::setRenameable (int col, bool yesno) +{ + if (col>=header()->count()) return; + + d->renameable.remove(col); + if (yesno && d->renameable.find(col)==d->renameable.end()) + d->renameable+=col; + else if (!yesno && d->renameable.find(col)!=d->renameable.end()) + d->renameable.remove(col); +} + +void KListView::doneEditing(QListViewItem *item, int row) +{ + emit itemRenamed(item, item->text(row), row); + emit itemRenamed(item); +} + +bool KListView::acceptDrag(QDropEvent* e) const +{ +qDebug("KListView::acceptDrag drag&drop not supported yet"); +//US return acceptDrops() && itemsMovable() && (e->source()==viewport()); +return false; +} + +void KListView::setCreateChildren(bool b) +{ + d->createChildren=b; +} + +bool KListView::createChildren() const +{ + return d->createChildren; +} + + +int KListView::tooltipColumn() const +{ + return d->tooltipColumn; +} + +void KListView::setTooltipColumn(int column) +{ + d->tooltipColumn=column; +} + +void KListView::setDropHighlighter(bool b) +{ + d->dropHighlighter=b; +} + +bool KListView::dropHighlighter() const +{ + return d->dropHighlighter; +} + +bool KListView::showTooltip(QListViewItem *item, const QPoint &, int column) const +{ + return ((tooltip(item, column).length()>0) && (column==tooltipColumn())); +} + +QString KListView::tooltip(QListViewItem *item, int column) const +{ + return item->text(column); +} + +void KListView::setTabOrderedRenaming(bool b) +{ + d->tabRename = b; +} + +bool KListView::tabOrderedRenaming() const +{ + return d->tabRename; +} + +void KListView::keyPressEvent (QKeyEvent* e) +{ + //don't we need a contextMenuModifier too ? (aleXXX) + if (e->key() == d->contextMenuKey) + { + emit menuShortCutPressed (this, currentItem()); + return; + } + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) + { + emit signalDelete ( ); + return; + } + + if (d->selectionMode != FileManager) + QListView::keyPressEvent (e); + else + fileManagerKeyPressEvent (e); +} + +void KListView::activateAutomaticSelection() +{ + d->selectedBySimpleMove=true; + d->selectedUsingMouse=false; + if (currentItem()!=0) + { + selectAll(false); + currentItem()->setSelected(true); + currentItem()->repaint(); + emit selectionChanged(); + }; +} + +void KListView::deactivateAutomaticSelection() +{ + d->selectedBySimpleMove=false; +} + +bool KListView::automaticSelection() const +{ + return d->selectedBySimpleMove; +} + +void KListView::fileManagerKeyPressEvent (QKeyEvent* e) +{ + //don't care whether it's on the keypad or not + int e_state=(e->state() & ~Keypad); + + int oldSelectionDirection(d->selectionDirection); + + if ((e->key()!=Key_Shift) && (e->key()!=Key_Control) + && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)) + { + if ((e_state==ShiftButton) && (!d->wasShiftEvent) && (!d->selectedBySimpleMove)) + selectAll(FALSE); + d->selectionDirection=0; + d->wasShiftEvent = (e_state == ShiftButton); + }; + + //d->wasShiftEvent = (e_state == ShiftButton); + + + QListViewItem* item = currentItem(); + if (item==0) return; + + QListViewItem* repaintItem1 = item; + QListViewItem* repaintItem2 = 0L; + QListViewItem* visItem = 0L; + + QListViewItem* nextItem = 0L; + int items = 0; + + bool shiftOrCtrl((e_state==ControlButton) || (e_state==ShiftButton)); + int selectedItems(0); + for (QListViewItem *tmpItem=firstChild(); tmpItem!=0; tmpItem=tmpItem->nextSibling()) + if (tmpItem->isSelected()) selectedItems++; + + if (((selectedItems==0) || ((selectedItems==1) && (d->selectedUsingMouse))) + && (e_state==NoButton) + && ((e->key()==Key_Down) + || (e->key()==Key_Up) + || (e->key()==Key_Next) + || (e->key()==Key_Prior) + || (e->key()==Key_Home) + || (e->key()==Key_End))) + { + d->selectedBySimpleMove=true; + d->selectedUsingMouse=false; + } + else if (selectedItems>1) + d->selectedBySimpleMove=false; + + bool emitSelectionChanged(false); + + switch (e->key()) + { + case Key_Escape: + selectAll(FALSE); + emitSelectionChanged=TRUE; + break; + + case Key_Space: + //toggle selection of current item + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + break; + + case Key_Insert: + //toggle selection of current item and move to the next item + if (d->selectedBySimpleMove) + { + d->selectedBySimpleMove=false; + if (!item->isSelected()) item->setSelected(TRUE); + } + else + { + item->setSelected(!item->isSelected()); + }; + + nextItem=item->itemBelow(); + + if (nextItem!=0) + { + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + d->selectionDirection=1; + emitSelectionChanged=TRUE; + break; + + case Key_Down: + nextItem=item->itemBelow(); + //toggle selection of current item and move to the next item + if (shiftOrCtrl) + { + d->selectionDirection=1; + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + else + { + if (oldSelectionDirection!=-1) + { + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + }; + }; + } + else if ((d->selectedBySimpleMove) && (nextItem!=0)) + { + item->setSelected(false); + emitSelectionChanged=TRUE; + }; + + if (nextItem!=0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + break; + + case Key_Up: + nextItem=item->itemAbove(); + d->selectionDirection=-1; + //move to the prev. item and toggle selection of this one + // => No, can't select the last item, with this. For symmetry, let's + // toggle selection and THEN move up, just like we do in down (David) + if (shiftOrCtrl) + { + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + else + { + if (oldSelectionDirection!=1) + { + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + }; + } + } + else if ((d->selectedBySimpleMove) && (nextItem!=0)) + { + item->setSelected(false); + emitSelectionChanged=TRUE; + }; + + if (nextItem!=0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + break; + + case Key_End: + //move to the last item and toggle selection of all items inbetween + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + d->selectedBySimpleMove=false; + + while(nextItem!=0) + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + if (nextItem->itemBelow()==0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + } + nextItem=nextItem->itemBelow(); + } + emitSelectionChanged=TRUE; + break; + + case Key_Home: + // move to the first item and toggle selection of all items inbetween + nextItem = firstChild(); + visItem = nextItem; + repaintItem2 = visItem; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectedBySimpleMove=false; + + while ( nextItem != item ) + { + nextItem->setSelected( !nextItem->isSelected() ); + nextItem = nextItem->itemBelow(); + } + item->setSelected( !item->isSelected() ); + } + setCurrentItem( firstChild() ); + emitSelectionChanged=TRUE; + break; + + case Key_Next: + items=visibleHeight()/item->height(); + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectedBySimpleMove=false; + d->selectionDirection=1; + }; + + for (int i=0; i<items; i++) + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + //the end + if ((i==items-1) || (nextItem->itemBelow()==0)) + + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + ensureItemVisible(nextItem); + setCurrentItem(nextItem); + update(); + if ((shiftOrCtrl) || (d->selectedBySimpleMove)) + { + emit selectionChanged(); + } + return; + } + nextItem=nextItem->itemBelow(); + } + break; + + case Key_Prior: + items=visibleHeight()/item->height(); + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectionDirection=-1; + d->selectedBySimpleMove=false; + }; + + for (int i=0; i<items; i++) + { + if ((nextItem!=item) &&(shiftOrCtrl)) + nextItem->setSelected(!nextItem->isSelected()); + //the end + if ((i==items-1) || (nextItem->itemAbove()==0)) + + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + ensureItemVisible(nextItem); + setCurrentItem(nextItem); + update(); + if ((shiftOrCtrl) || (d->selectedBySimpleMove)) + { + emit selectionChanged(); + } + return; + } + nextItem=nextItem->itemAbove(); + } + break; + + case Key_Minus: + if ( item->isOpen() ) + setOpen( item, FALSE ); + break; + case Key_Plus: + if ( !item->isOpen() && (item->isExpandable() || item->childCount()) ) + setOpen( item, TRUE ); + break; + default: + bool realKey = ((e->key()!=Key_Shift) && (e->key()!=Key_Control) + && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)); + + bool selectCurrentItem = (d->selectedBySimpleMove) && (item->isSelected()); + if (realKey && selectCurrentItem) + item->setSelected(false); + //this is mainly for the "goto filename beginning with pressed char" feature (aleXXX) + QListView::SelectionMode oldSelectionMode = selectionMode(); + setSelectionMode (QListView::Multi); + QListView::keyPressEvent (e); + setSelectionMode (oldSelectionMode); + if (realKey && selectCurrentItem) + { + currentItem()->setSelected(true); + emitSelectionChanged=TRUE; + } + repaintItem2=currentItem(); + if (realKey) + visItem=currentItem(); + break; + } + + if (visItem) + ensureItemVisible(visItem); + + QRect ir; + if (repaintItem1) + ir = ir.unite( itemRect(repaintItem1) ); + if (repaintItem2) + ir = ir.unite( itemRect(repaintItem2) ); + + if ( !ir.isEmpty() ) + { // rectangle to be repainted + if ( ir.x() < 0 ) + ir.moveBy( -ir.x(), 0 ); + viewport()->repaint( ir, FALSE ); + } + /*if (repaintItem1) + repaintItem1->repaint(); + if (repaintItem2) + repaintItem2->repaint();*/ + update(); + if (emitSelectionChanged) + emit selectionChanged(); +} + +void KListView::setSelectionModeExt (SelectionModeExt mode) +{ + d->selectionMode = mode; + + switch (mode) + { + case Single: + case Multi: + case Extended: + case NoSelection: + setSelectionMode (static_cast<QListView::SelectionMode>(static_cast<int>(mode))); + break; + + case FileManager: + setSelectionMode (QListView::Extended); + break; + + default: + kdWarning () << "Warning: illegal selection mode " << int(mode) << " set!" << endl; + break; + } +} + +KListView::SelectionModeExt KListView::selectionModeExt () const +{ + return d->selectionMode; +} + +int KListView::itemIndex( const QListViewItem *item ) const +{ + if ( !item ) + return -1; + + if ( item == firstChild() ) + return 0; + else { + QListViewItemIterator it(firstChild()); + uint j = 0; + for (; it.current() && it.current() != item; ++it, ++j ); + + if( !it.current() ) + return -1; + + return j; + } +} + +QListViewItem* KListView::itemAtIndex(int index) +{ + if (index<0) + return 0; + + int j(0); + for (QListViewItemIterator it=firstChild(); it.current(); it++) + { + if (j==index) + return it.current(); + j++; + }; + return 0; +} + + +void KListView::emitContextMenu (KListView*, QListViewItem* i) +{ + QPoint p; + qDebug("KListView::emitContextMenu "); + + if (i) + p = viewport()->mapToGlobal(itemRect(i).center()); + else + p = mapToGlobal(rect().center()); + + emit contextMenu (this, i, p); +} + +void KListView::emitContextMenu (QListViewItem* i, const QPoint& p, int) +{ + qDebug("KListView::emitContextMenu "); + emit contextMenu (this, i, p); +} + +void KListView::setAcceptDrops (bool val) +{ + QListView::setAcceptDrops (val); + viewport()->setAcceptDrops (val); +} + +int KListView::dropVisualizerWidth () const +{ + return d->mDropVisualizerWidth; +} + + +void KListView::viewportPaintEvent(QPaintEvent *e) +{ + QListView::viewportPaintEvent(e); + + if (d->mOldDropVisualizer.isValid() && e->rect().intersects(d->mOldDropVisualizer)) + { + QPainter painter(viewport()); + + // This is where we actually draw the drop-visualizer + painter.fillRect(d->mOldDropVisualizer, Dense4Pattern); + } + if (d->mOldDropHighlighter.isValid() && e->rect().intersects(d->mOldDropHighlighter)) + { + QPainter painter(viewport()); + +qDebug("KListView::viewportPaintEvent has to be verified"); + + // This is where we actually draw the drop-highlighter +//US style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(), +//US QStyle::Style_FocusAtBorder); + +//LR style().drawFocusRect(&painter, d->mOldDropHighlighter, colorGroup(), (const QColor*)0, true); + + + } +} + +void KListView::setFullWidth() +{ + setFullWidth(true); +} + +void KListView::setFullWidth(bool fullWidth) +{ + d->fullWidth = fullWidth; +//US header()->setStretchEnabled(fullWidth, columns()-1); +} + +bool KListView::fullWidth() const +{ + return d->fullWidth; +} + +int KListView::addColumn(const QString& label, int width) +{ + int result = QListView::addColumn(label, width); + if (d->fullWidth) { +//US header()->setStretchEnabled(false, columns()-2); +//US header()->setStretchEnabled(true, columns()-1); + } + return result; +} + +int KListView::addColumn(const QIconSet& iconset, const QString& label, int width) +{ + int result = QListView::addColumn(iconset, label, width); + if (d->fullWidth) { +//US header()->setStretchEnabled(false, columns()-2); +//US header()->setStretchEnabled(true, columns()-1); + } + return result; +} + +void KListView::removeColumn(int index) +{ + QListView::removeColumn(index); +//US if (d->fullWidth && index == columns()) header()->setStretchEnabled(true, columns()-1); +} + +void KListView::viewportResizeEvent(QResizeEvent* e) +{ + QListView::viewportResizeEvent(e); +} + +const QColor &KListView::alternateBackground() const +{ + return d->alternateBackground; +} + +void KListView::setAlternateBackground(const QColor &c) +{ + d->alternateBackground = c; + repaint(); +} + +void KListView::saveLayout(KConfig *config, const QString &group) const +{ + KConfigGroupSaver saver(config, group); + QStringList widths, order; + for (int i = 0; i < columns(); ++i) + { + widths << QString::number(columnWidth(i)); + order << QString::number(header()->mapToIndex(i)); + } + config->writeEntry("ColumnWidths", widths); + config->writeEntry("ColumnOrder", order); + config->writeEntry("SortColumn", d->sortColumn); + config->writeEntry("SortAscending", d->sortAscending); +} + +void KListView::restoreLayout(KConfig *config, const QString &group) +{ + KConfigGroupSaver saver(config, group); + QStringList cols = config->readListEntry("ColumnWidths"); + int i = 0; + for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) + setColumnWidth(i++, (*it).toInt()); + + cols = config->readListEntry("ColumnOrder"); + i = 0; + for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) + header()->moveSection(i++, (*it).toInt()); + +/*US I changed the following code, because hasKey is not available. +!!! check if my version is correct + if (config->hasKey("SortColumn")) + setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); +*/ + QStringList langLst = config->readListEntry( "SortColumn" ); + if (!langLst.isEmpty()) + setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); +} + +void KListView::setSorting(int column, bool ascending) +{ + d->sortColumn = column; + d->sortAscending = ascending; + QListView::setSorting(column, ascending); +} + +int KListView::columnSorted(void) const +{ + return d->sortColumn; +} + +bool KListView::ascendingSort(void) const +{ + return d->sortAscending; +} + +KListViewItem::KListViewItem(QListView *parent) + : QListViewItem(parent) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent) + : QListViewItem(parent) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, QListViewItem *after) + : QListViewItem(parent, after) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after) + : QListViewItem(parent, after) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, QListViewItem *after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::~KListViewItem() +{ +} + +void KListViewItem::init() +{ + m_known = false; +} + +const QColor &KListViewItem::backgroundColor() +{ + if (isAlternate()) + return static_cast< KListView* >(listView())->alternateBackground(); + return listView()->viewport()->colorGroup().base(); +} + +bool KListViewItem::isAlternate() +{ + KListView *lv = static_cast<KListView *>(listView()); + if (lv && lv->alternateBackground().isValid()) + { + KListViewItem *above = 0; +//US above = dynamic_cast<KListViewItem *>(itemAbove()); + above = (KListViewItem *)(itemAbove()); + m_known = above ? above->m_known : true; + if (m_known) + { + m_odd = above ? !above->m_odd : false; + } + else + { + KListViewItem *item; + bool previous = true; + if (parent()) + { +//US item = dynamic_cast<KListViewItem *>(parent()); + item = (KListViewItem *)(parent()); + if (item) + previous = item->m_odd; +//US item = dynamic_cast<KListViewItem *>(parent()->firstChild()); + item = (KListViewItem *)(parent()->firstChild()); + } + else + { +//US item = dynamic_cast<KListViewItem *>(lv->firstChild()); + item = (KListViewItem *)(lv->firstChild()); + } + + while(item) + { + item->m_odd = previous = !previous; + item->m_known = true; +//US item = dynamic_cast<KListViewItem *>(item->nextSibling()); + item = (KListViewItem *)(item->nextSibling()); + } + } + return m_odd; + } + return false; +} + +void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup _cg = cg; + const QPixmap *pm = listView()->viewport()->backgroundPixmap(); + if (pm && !pm->isNull()) + { + _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(), *pm)); + QPoint o = p->brushOrigin(); + p->setBrushOrigin( o.x()-listView()->contentsX(), o.y()-listView()->contentsY() ); + } + else if (isAlternate()) { +//US if (listView()->viewport()->backgroundMode()==Qt::FixedColor) + if (listView()->viewport()->backgroundMode()==QWidget::PaletteBackground) + _cg.setColor(QColorGroup::Background, static_cast< KListView* >(listView())->alternateBackground()); + else + _cg.setColor(QColorGroup::Base, static_cast< KListView* >(listView())->alternateBackground()); + } + QListViewItem::paintCell(p, _cg, column, width, alignment); +} + +void KListView::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klistview.moc" +//US #include "klistviewlineedit.moc" + +// vim: ts=2 sw=2 et diff --git a/microkde/kdeui/klistview.h b/microkde/kdeui/klistview.h new file mode 100644 index 0000000..f7d9f85 --- a/dev/null +++ b/microkde/kdeui/klistview.h @@ -0,0 +1,1033 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2000 Charles Samuels <charles@kde.org> + Copyright (C) 2000 Peter Putzer <putzer@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLISTVIEW_H +#define KLISTVIEW_H + +#include <qlistview.h> + +#include <qptrlist.h> + +//US +class QDropEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDragEnterEvent; + +class QDragObject; +class KConfig; +class KLineEdit; +/** + * This Widget extends the functionality of QListView to honor the system + * wide settings for Single Click/Double Click mode, AutoSelection and + * ChangeCursorOverLink (TM). + * + * There is a new signal executed(). It gets connected to either + * @ref QListView::clicked() or @ref QListView::doubleClicked() depending on the KDE + * wide Single Click/Double Click settings. It is strongly recommended that + * you use this signal instead of the above mentioned. This way you dont + * need to care about the current settings. + * If you want to get informed when the user selects something connect to the + * QListView::selectionChanged() signal. + * + * Drag-and-Drop is supported with the signal @ref #dropped(), just @ref #setAcceptDrops(true) + * and connect it to a suitable slot. + * To see where you are dropping, @ref setDropVisualizer(true). + * And also you'll need @ref acceptDrag(QDropEvent*) + * + * KListView is drag-enabled, too: to benefit from that you've got derive from it. + * Reimplement @ref dragObject() and (possibly) @ref startDrag(), + * and @ref setDragEnabled(true). + * + * @version $Id$ + */ +class KListView : public QListView +{ + Q_OBJECT + Q_ENUMS( SelectionModeExt ) + Q_PROPERTY( bool fullWidth READ fullWidth WRITE setFullWidth ) + Q_PROPERTY( bool itemsMovable READ itemsMovable WRITE setItemsMovable ) + Q_PROPERTY( bool itemsRenameable READ itemsRenameable WRITE setItemsRenameable ) + Q_PROPERTY( bool dragEnabled READ dragEnabled WRITE setDragEnabled ) + Q_PROPERTY( bool autoOpen READ autoOpen WRITE setAutoOpen ) + Q_PROPERTY( bool dropVisualizer READ dropVisualizer WRITE setDropVisualizer ) +//US Q_PROPERTY( int tooltipColumn READ tooltipColumn WRITE setTooltipColumn ) + Q_PROPERTY( int dropVisualizerWidth READ dropVisualizerWidth WRITE setDropVisualizerWidth ) + Q_PROPERTY( QColor alternateBackground READ alternateBackground WRITE setAlternateBackground ) + + Q_OVERRIDE( SelectionModeExt selectionMode READ selectionModeExt WRITE setSelectionModeExt ) + +public: + /** + * Possible selection modes. + * + * The first four correspond directly to QListView::SelectionMode, while + * the FileManager selection mode is defined as follows: + * @li home: move to the first + * @li end: move to the last + * @li PgUp/PgDn: move one page up/down + * @li up/down: move one item up/down + * @li insert: toggle selection of current and move to the next + * @li space: toggle selection of the current + * @li CTRL+up: move to the previous item and toggle selection of this one + * @li CTRL+down: toggle selection of the current item and move to the next + * @li CTRL+end: toggle selection from (including) the current + * item to (including) the last item + * @li CTRL+home: toggle selection from (including) the current + * item to the (including) the first item + * @li CTRL+PgDn: toggle selection from (including) the current + * item to (excluding) the item one page down + * @li CTRL+PgUp: toggle selection from (excluding) the current + * item to (including) the item one page up + * + * The combinations work the same with SHIFT instead of CTRL, except + * that if you start selecting something using SHIFT everything selected + * before will be deselected first. + * + * Additionally the current item is always selected automatically when + * navigating using the keyboard, except other items were selected explicitely. + * + * This way e.g. SHIFT+up/PgUp then SHIFT+down/PgDn leaves no item selected + */ + enum SelectionModeExt { + Single = QListView::Single, + Multi = QListView::Multi, + Extended = QListView::Extended, + NoSelection = QListView::NoSelection, + FileManager + }; + void repaintContents( bool erase = true ) + { + QScrollView::repaintContents( contentsX(), contentsY(), + visibleWidth(), visibleHeight(), erase ); + }; + /** + * Constructor. + * + * The parameters @p parent and @p name are handled by + * @ref QListView, as usual. + */ + KListView (QWidget *parent = 0, const char *name = 0); + + /** + * Destructor. + */ + virtual ~KListView(); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void setAcceptDrops (bool); + + /** + * This function determines whether the given coordinates are within the + * execute area. The execute area is the part of a @ref QListViewItem where mouse + * clicks or double clicks respectively generate a @ref #executed() signal. + * Depending on @ref QListView::allColumnsShowFocus() this is either the + * whole item or only the first column. + * @return true if point is inside execute area of an item, false in all + * other cases including the case that it is over the viewport. + */ + virtual bool isExecuteArea( const QPoint& point ); + + /** + * Same thing, but from an x coordinate only. This only checks if x is in + * the first column (if all columns don't show focus), without testing if + * the y coordinate is over an item or not. + */ + bool isExecuteArea( int x ); + + /** + * @return a list containing the currently selected items. + */ + QPtrList<QListViewItem> selectedItems() const; // ### BIC: KDE 4: use an implicitly shared class! (QValueList?) + + /** + * Arbitrarily move @p item to @p parent, positioned immediately after item @p after. + */ + void moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after); + + /** + * @return the last item (not child!) of this listview. + * + * @see lastChild() + */ + QListViewItem *lastItem() const; + + /** + * @return the last child of this listview. + * + * @see lastItem() + */ + QListViewItem* lastChild () const; + + /** + * @return the lineedit used for inline renaming. + * Use that to setup a @ref KCompletion or @ref QValidator for the lineedit + * + * @since 3.2 + */ + KLineEdit* renameLineEdit() const; + + /** + * @returns if it is legal to move items in the list view. True by default. + * + * @see #setDragEnabled() + * @see #setItemsMovable() + */ + bool itemsMovable() const; + + /** + * @return whether inplace-renaming has been enabled. False by default. + * + * @see #setItemsRenameable() + */ + bool itemsRenameable() const; + + /** + * @return whether dragging is enabled. False by default. + * + * @see #setDragEnabled() + */ + bool dragEnabled() const; + + /** + * @return true if AutoOpen is enabled (not implemented currently). + * + * @see #setAutoOpen() + */ + bool autoOpen() const; + + /** + * @return true if @p column is renamable. + * + * @see #setRenameable() + */ + bool isRenameable (int column) const; + + /** + * @return true if drawing of the drop-visualizer has been enabled. True by default. + * + * @see #setDropVisualizer() + */ + bool dropVisualizer() const; + + /** + * @return the column for which tooltips are displayed (or -1 if none set). + * + * @see #setTooltipColumn() + */ + int tooltipColumn() const; + + /** + * For future expansions. + * + * Do not use. + * @deprecated + */ + bool createChildren() const; + + /** + * @return true if drawing of the drop-highlighter has been enabled. False by default. + * + * @see #setDropHighlighter() + */ + bool dropHighlighter() const; + + /** + * The dropVisualizerWidth defaults to 4. + * + * @see #setDropVisualizerWidth() + * @return the current width of the drop-visualizer. + */ + int dropVisualizerWidth () const; + + /** + * @return the "extended" selection mode of this listview. + * + * @see SelectionModeExt + * @see setSelectionModeExt + */ + SelectionModeExt selectionModeExt () const; + + /** + * Returns the index of @p item within the item tree or -1 if + * @p item doesn't exist in this list view. This function takes + * all items into account not only the visible ones. + */ + int itemIndex( const QListViewItem *item ) const; + + /** + * Returns the item of @p index within the item tree or 0 if + * @p index doesn't exist in this list view. This function takes + * all items into account not only the visible ones. + */ + QListViewItem* itemAtIndex(int index); + + /** + * @deprecated + * @see #setFullWidth() + */ + void setFullWidth(); + + /** + * Let the last column fit exactly all the available width. + * + * @see #fullWidth() + */ + void setFullWidth(bool fullWidth); + + /** + * Returns whether the last column is set to fit the available width. + * + * @see #setFullWidth() + */ + bool fullWidth() const; + + /** + * Reimplemented for full width support + * + * @see #removeColumn() + */ + virtual int addColumn(const QString& label, int width = -1); + /** + * Reimplemented for full width support + */ + virtual int addColumn(const QIconSet& iconset, const QString& label, int width = -1); + /** + * Reimplemented for full width support + * + * @see #addColumn() + */ + virtual void removeColumn(int index); + + /** + * sets the alternate background background color. + * This only has an effect if the items are KListViewItems + * + * @param c the color to use for every other item. Set to an invalid + * colour to disable alternate colours. + * + * @see #alternateBackground() + **/ + void setAlternateBackground(const QColor &c); + /** + * @return the alternate background color + * + * @see #setAlternateBackground() + */ + const QColor &alternateBackground() const; + + /** + * Saves the list view's layout (column widtsh, column order, sort column) + * to a KConfig group + * + * @param config the @ref KConfig object to write to + * @param group the config group to use + */ + void saveLayout(KConfig *config, const QString &group) const; + /** + * Reads the list view's layout from a KConfig group as stored with + * @ref #saveLayout + * + * @param config the @ref KConfig object to read from + * @param group the config group to use + */ + void restoreLayout(KConfig *config, const QString &group); + /** + * Reimplemented to remember the current sort column and order. + * @param column is the column to be sorted, or -1 to sort in order of + * insertion + * @param whether to sort ascending (or descending) + */ + virtual void setSorting(int column, bool ascending = true); + + /** + * @return the currently sorted column, or -1 if none is sorted + */ + int columnSorted(void) const; + + /** + * @return whether the current sort is ascending (or descending) + */ + bool ascendingSort(void) const; + +signals: + + /** + * This signal is emitted whenever the user executes an listview item. + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listview item. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + */ + void executed( QListViewItem *item ); + + /** + * This signal is emitted whenever the user executes an listview item. + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listview item. + * @param pos is the position where the user has clicked + * @param c is the column into which the user clicked. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + */ + void executed( QListViewItem *item, const QPoint &pos, int c ); + + /** + * This signal gets emitted whenever the user double clicks into the + * listview. + * @param item is the pointer to the clicked listview item. + * @param pos is the position where the user has clicked, and + * @param c is the column into which the user clicked. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + * + * This signal is more or less here for the sake of completeness. + * You should normally not need to use this. In most cases its better + * to use @ref #executed() instead. + */ + void doubleClicked( QListViewItem *item, const QPoint &pos, int c ); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * @param e is the drop event itself (it has already been accepted) + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items) + * + * @see #acceptDrop() + */ + void dropped (QDropEvent * e, QListViewItem *after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This is an overloaded version of the above (provided to simplify + * processing drops outside of the class). + * + * @param list is the listview + * @param e is the drop event itself (it has already been accepted) + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (KListView* list, QDropEvent* e, QListViewItem* after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This function also provides a parent, in the event that your listview + * is a tree + * @param list is the listview + * @param e is the drop event itself (it has already been accepted) + * @param parent the item that is to be the parent of the new item + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (KListView* list, QDropEvent* e, QListViewItem* parent, QListViewItem* after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This function also provides a parent, in the event that your listview + * is a tree + * @param e is the drop event itself (it has already been accepted) + * @param parent the item that is to be the parent of the new item + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (QDropEvent* e, QListViewItem* parent, QListViewItem* after); + + /** + * This signal is emitted when ever the user moves an item in the list via + * DnD. + * If more than one item is moved at the same time, this signal is only emitted + * once. + */ + void moved(); + + /** + * Connect to this signal if you want to do some preprocessing before + * a move is made, for example, to disable sorting + * + * This is sent only once per each groups of moves. That is, for each + * drop that is a move this will be emitted once, before KListView calls + * @see moveItem() + */ + void aboutToMove(); + + /** + * This signal is emitted when ever the user moves an item in the list via + * DnD. + * If more than one item is moved at the same time, @p afterFirst and + * @p afterNow will reflect what was true before the move. + * This differs from @ref moved(), so be careful. All the items will have been + * moved before @ref moved() is emitted, which is not true in this method. // FIXME + * @param item the item that was moved + * @param afterFirst the item that parameter item was in before the move, in the list + * @param afterNow the item it's currently after. + */ + void moved (QListViewItem *item, QListViewItem *afterFirst, QListViewItem *afterNow); + + + /** + * This signal is emitted after all the items have been moved. It reports info for + * each and every item moved, in order. The first element in @p items associates + * with the first of afterFirst and afterNow. + */ + void moved(QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &afterFirst, QPtrList<QListViewItem> &afterNow); + + /** + * This signal gets emitted when an item is renamed via in-place renaming. + * + * @param item is the renamed item. + * @param str is the new value of column @p col. + * @param col is the renamed column. + */ + void itemRenamed(QListViewItem* item, const QString &str, int col); + + /** + * Same as above, but without the extra information. + */ + void itemRenamed(QListViewItem* item); + void signalDelete(); + + /** + * This signal is emitted when the shortcut key for popup-menus is pressed. + * + * Normally you should not use this, just connect a slot to signal + * @ref contextMenu (KListView*, QListViewItem*, const QPoint&) to correctly + * handle showing context menus regardless of settings. + * + * @param list is this listview. + * @param item is the @ref currentItem() at the time the key was pressed. May be 0L. + */ + void menuShortCutPressed (KListView* list, QListViewItem* item); + + /** + * This signal is emitted whenever a context-menu should be shown for item @p i. + * It automatically adjusts for all settings involved (Menu key, showMenuOnPress/Click). + * + * @param l is this listview. + * @param i is the item for which the menu should be shown. May be 0L. + * @param p is the point at which the menu should be shown. + */ + void contextMenu (KListView* l, QListViewItem* i, const QPoint& p); + +public slots: + /** + * Rename column @p c of @p item. + */ + virtual void rename(QListViewItem *item, int c); + + /** + * By default, if you called setItemsRenameable(true), + * only the first column is renameable. + * Use this function to enable the feature on other columns. + * + * If you want more intelligent (dynamic) selection, + * you'll have to derive from KListView, + * and override @ref rename() and call only call it + * if you want the item to be renamed. + */ + void setRenameable (int column, bool yesno=true); + + /** + * Set whether items in the list view can be moved. + * It is enabled by default. + * + * @see itemsMovable() + */ + virtual void setItemsMovable(bool b); + + /** + * Enables inplace-renaming of items. + * It is disabled by default. + * + * @see itemsRenameable() + * @see setRenameable() + */ + virtual void setItemsRenameable(bool b); + + /** + * Enable/Disable the dragging of items. + * It is disabled by default. + */ + virtual void setDragEnabled(bool b); + + /** + * Enable/Disable AutoOpen (not implemented currently). + */ + virtual void setAutoOpen(bool b); + + /** + * Enable/Disable the drawing of a drop-visualizer + * (a bar that shows where a dropped item would be inserted). + * It is enabled by default, if dragging is enabled + */ + virtual void setDropVisualizer(bool b); + + /** + * Set the width of the (default) drop-visualizer. + * If you don't call this method, the width is set to 4. + */ + void setDropVisualizerWidth (int w); + + /** + * Set which column should be used for automatic tooltips. + * + * @param column is the column for which tooltips will be shown. + * Set -1 to disable this feature. + */ + virtual void setTooltipColumn(int column); + + /** + * Enable/Disable the drawing of a drop-highlighter + * (a rectangle around the item under the mouse cursor). + * It is disabled by default. + */ + virtual void setDropHighlighter(bool b); + + /** + * For future expansions. + * + * Do not use. + * @deprecated + */ + virtual void setCreateChildren(bool b); + + /** + * Set the selection mode. + * + * A different name was chosen to avoid API-clashes with @ref QListView::setSelectionMode(). + */ + void setSelectionModeExt (SelectionModeExt mode); + + /** + * Enable/disable tabbing between editable cells + * @since 3.1 + */ + void setTabOrderedRenaming(bool b); + + /** + * Returns whether tab ordered renaming is enabled + * @since 3.1 + */ + bool tabOrderedRenaming() const; + +protected: + /** + * Determine whether a drop on position @p p would count as + * being above or below the QRect @p rect. + * + * @param rect is the rectangle we examine. + * @param p is the point located in the rectangle, p is assumed to be in + * viewport coordinates. + */ + inline bool below (const QRect& rect, const QPoint& p) + { + return (p.y() > (rect.top() + (rect.bottom() - rect.top())/2)); + } + + /** + * An overloaded version of below(const QRect&, const QPoint&). + * + * It differs from the above only in what arguments it takes. + * + * @param i the item whose rect() is passed to the above function. + * @param p is translated from contents coordinates to viewport coordinates + * before being passed to the above function. + */ + inline bool below (QListViewItem* i, const QPoint& p) + { + return below (itemRect(i), contentsToViewport(p)); + } + + /** + * Reimplemented to reload the alternate background in palette changes. + * @internal + */ + virtual bool event( QEvent * ); + + /** + * Emit signal @ref #executed. + * @internal + */ + void emitExecute( QListViewItem *item, const QPoint &pos, int c ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void focusInEvent(QFocusEvent* fe); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void focusOutEvent( QFocusEvent *fe ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void leaveEvent( QEvent *e ); + + /** + * @return the tooltip for @p column of @p item. + */ + virtual QString tooltip(QListViewItem* item, int column) const; + + /** + * @return whether the tooltip for @p column of @p item shall be shown at point @p pos. + */ + virtual bool showTooltip(QListViewItem *item, const QPoint &pos, int column) const; + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragMoveEvent (QDragMoveEvent *event); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMousePressEvent( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseMoveEvent( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragLeaveEvent (QDragLeaveEvent *event); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseReleaseEvent (QMouseEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDropEvent (QDropEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragEnterEvent (QDragEnterEvent *); + + /** + * @return a dragobject encoding the current selection. + * + * @see setDragEnabled() + */ + virtual QDragObject *dragObject(); + + /** + * @return true if the @p event provides some acceptable + * format. + * A common mistake is to forget the "const" in your reimplementation + */ + virtual bool acceptDrag (QDropEvent* event) const; + + /** + * Paint the drag line. If painter is null, don't try to :) + * + * If after == 0 then the marker should be drawn at the top. + * + * @return the rectangle that you painted to. + */ + virtual QRect drawDropVisualizer (QPainter *p, QListViewItem *parent, QListViewItem *after); + + /** + * Paint the drag rectangle. If painter is null, don't try to :) + * + * + * @return the rectangle that you painted to. + */ + virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item); + + /** + * This method calls @ref dragObject() and starts the drag. + * + * Reimplement it to do fancy stuff like setting a pixmap or + * using a non-default DragMode + */ + virtual void startDrag(); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void keyPressEvent (QKeyEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void viewportPaintEvent(QPaintEvent*); + + /** + * In FileManager selection mode: explicitely activate the mode + * in which the current item is automatically selected. + */ + void activateAutomaticSelection(); + /** + * In FileManager selection mode: explicitely deactivate the mode + * in which the current item is automatically selected. + */ + void deactivateAutomaticSelection(); + /** + * In FileManager selection mode: return whether it is currently in the mode + * where the current item is selected automatically. + * Returns false if items were selected explicitely, e.g. using the mouse. + */ + bool automaticSelection() const; + + /** + * Reimplemented for setFullWidth() + */ + virtual void viewportResizeEvent(QResizeEvent* e); + +protected slots: + /** + * Update internal settings whenever the global ones change. + * @internal + */ + void slotSettingsChanged(int); + + void slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ); + void doneEditing(QListViewItem *item, int row); + + /** + * Repaint the rect where I was drawing the drop line. + */ + void cleanDropVisualizer(); + + /** + * Repaint the rect where I was drawing the drop rectangle. + */ + void cleanItemHighlighter(); + + /** + * Emit the @ref contextMenu signal. This slot is for mouse actions. + */ + void emitContextMenu (QListViewItem*, const QPoint&, int); + + /** + * Emit the @ref #contextMenu signal. This slot is for key presses. + */ + void emitContextMenu (KListView*, QListViewItem*); + + /** + * Accessory slot for AutoSelect + * @internal + */ + void slotOnItem( QListViewItem *item ); + + /** + * Accessory slot for AutoSelect/ChangeCursorOverItem + * @internal + */ + void slotOnViewport(); + + /** + * Process AutoSelection. + * @internal + */ + void slotAutoSelect(); + + void slotDragExpand(); + + /** + * Reacts to header changes in full width mode + * @internal + */ + void slotHeaderChanged(); + +protected: + /** + * Handle dropEvent when itemsMovable() is set to true. + */ + virtual void movableDropEvent (QListViewItem* parent, QListViewItem* afterme); + + /** + * Where is the nearest QListViewItem that I'm going to drop? + * + * FIXME KDE 4.0: Make this method const so it can be called from an + * acceptDrag method without ugly casts + */ + virtual void findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after); + + /** + * A special keyPressEvent (for FileManager selection mode). + */ + void fileManagerKeyPressEvent (QKeyEvent*); + + /** + * Convert the depth of an item into its indentation in pixels + */ + int depthToPixels( int depth ); + +private: + class Tooltip; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListViewPrivate; + KListViewPrivate *d; +}; + +/** + * A listview item with support for alternate background colours. It is + * a drop-in replacement for @ref QListViewItem + * + * @short listview item with alternate background colour support + */ +class KListViewItem : public QListViewItem +{ +public: + /** + * constructors. The semantics remain as in @ref QListViewItem. + * Although they accept a @ref QListViewItem as parent, please + * don't mix KListViewItem (or subclasses) with QListViewItem + * (or subclasses). + */ + KListViewItem(QListView *parent); + KListViewItem(QListViewItem *parent); + KListViewItem(QListView *parent, QListViewItem *after); + KListViewItem(QListViewItem *parent, QListViewItem *after); + + KListViewItem(QListView *parent, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListViewItem *parent, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListView *parent, QListViewItem *after, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListViewItem *parent, QListViewItem *after, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + virtual ~KListViewItem(); + + /** + * retuns true if this item is to be drawn with the alternate background + */ + bool isAlternate(); + /** + * returns the background colour for this item + */ + const QColor &backgroundColor(); + + virtual void paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int alignment); + +private: + void init(); + +private: + uint m_odd : 1; + uint m_known : 1; + uint m_unused : 30; +}; + +#endif + +// vim: ts=2 sw=2 et diff --git a/microkde/kdeui/kmainwindow.cpp b/microkde/kdeui/kmainwindow.cpp new file mode 100644 index 0000000..3a2a4d0 --- a/dev/null +++ b/microkde/kdeui/kmainwindow.cpp @@ -0,0 +1,994 @@ + /* This file is part of the KDE libraries + Copyright + (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997 Stephan Kulow (coolo@kde.org) + (C) 1997-2000 Sven Radej (radej@kde.org) + (C) 1997-2000 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ +#include <qobjectlist.h> +#include <qstringlist.h> +#include <qtimer.h> +#include <qmenubar.h> +#include <qstatusbar.h> +#include <qapplication.h> + + +#include "kdebug.h" +#include "kmainwindow.h" +#include "kglobalsettings.h" +#include "kactioncollection.h" + +class KMainWindowPrivate { +public: +//US bool showHelpMenu:1; + + bool autoSaveSettings:1; + bool settingsDirty:1; + bool autoSaveWindowSize:1; + bool care_about_geometry:1; + QString autoSaveGroup; +//US KAccel * kaccel; +//US KMainWindowInterface *m_interface; + KDEPrivate::ToolBarHandler *toolBarHandler; + QTimer* settingsTimer; + KToggleAction *showStatusBarAction; + QRect defaultWindowSize; +}; + +static bool no_query_exit = false; + +KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f ) + : QMainWindow( parent, name, f )/*US, KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )*/ +{ + mQToolBar = 0; + initKMainWindow(name); +} + +void KMainWindow::parseGeometry(bool parsewidth) +{ +//US the following code is not getting used in the embedded version !! So disable it for now +/*US + + assert ( !kapp->geometryArgument().isNull() ); + assert ( d->care_about_geometry ); + +#ifndef Q_WS_QWS + // FIXME: (E) Implement something similar for Qt Embedded (or decide we don't need it) + int x, y; + int w, h; + int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); + if (parsewidth) { + QSize minSize = minimumSize(); + QSize maxSize = maximumSize(); + if ( (m & WidthValue) == 0 ) + w = width(); + if ( (m & HeightValue) == 0 ) + h = height(); + w = QMIN(w,maxSize.width()); + h = QMIN(h,maxSize.height()); + w = QMAX(w,minSize.width()); + h = QMAX(h,minSize.height()); + resize(w, h); + } else { + if ( parsewidth && (m & XValue) == 0 ) + x = geometry().x(); + if ( parsewidth && (m & YValue) == 0 ) + y = geometry().y(); + if ( (m & XNegative) ) + x = KApplication::desktop()->width() + x - w; + if ( (m & YNegative) ) + y = KApplication::desktop()->height() + y - h; + move(x, y); + } +#endif +*/ +} + +KMainWindow::~KMainWindow() +{ + delete d->settingsTimer; + QMenuBar* mb = internalMenuBar(); + delete mb; +//US delete d->m_interface; + + delete d; +//US memberList->remove( this ); +} + +void KMainWindow::initKMainWindow(const char *name) +{ + setDockMenuEnabled( FALSE ); +//US mHelpMenu = 0; + +//US kapp->setTopWidget( this ); + actionCollection()->setWidget( this ); +//US connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); +//US if( !memberList ) +//US memberList = new QPtrList<KMainWindow>; +/*US + + if ( !ksm ) + ksm = ksmd.setObject(new KMWSessionManaged()); + // set a unique object name. Required by session management. + QCString objname; + QCString s; + int unusedNumber; + if ( !name ) + { // no name given + objname = kapp->instanceName() + "-mainwindow#"; + s = objname + '1'; // start adding number immediately + unusedNumber = 1; + } + else if( name[ strlen( name ) - 1 ] == '#' ) + { // trailing # - always add a number + objname = name; + s = objname + '1'; // start adding number immediately + unusedNumber = 1; + } + else + { + objname = name; + s = objname; + unusedNumber = 0; // add numbers only when needed + } + for(;;) { + QWidgetList* list = kapp->topLevelWidgets(); + QWidgetListIt it( *list ); + bool found = false; + for( QWidget* w = it.current(); + w != NULL; + ++it, w = it.current()) + if( w != this && w->name() == s ) + { + found = true; + break; + } + delete list; + if( !found ) + break; + s.setNum( ++unusedNumber ); + s = objname + s; + } + setName( s ); + memberList->append( this ); +*/ + + d = new KMainWindowPrivate; +//US d->showHelpMenu = true; + d->settingsDirty = false; + d->autoSaveSettings = false; + d->autoSaveWindowSize = true; // for compatibility +//US d->kaccel = actionCollection()->kaccel(); + d->toolBarHandler = 0; + d->settingsTimer = 0; + d->showStatusBarAction = NULL; +/*US + if ((d->care_about_geometry == beeing_first)) { + beeing_first = false; + if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater + d->care_about_geometry = false; + else + parseGeometry(false); + } +*/ + d->care_about_geometry = false; + +//US setCaption( kapp->caption() ); + // attach dcop interface +//US d->m_interface = new KMainWindowInterface(this); + +//US if (!kapp->authorize("movable_toolbars")) +//US setDockWindowsMovable(false); +} + +KAction *KMainWindow::toolBarMenuAction() +{ + if ( !d->toolBarHandler ) + return 0; + + return d->toolBarHandler->toolBarMenuAction(); +} + +bool KMainWindow::canBeRestored( int number ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ +//US if ( !kapp->isRestored() ) +//US return FALSE; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + if ( !config ) + return FALSE; + config->setGroup( QString::fromLatin1("Number") ); + int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 ); + return number >= 1 && number <= n; + +} + +const QString KMainWindow::classNameOfToplevel( int number ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ +//US if ( !kapp->isRestored() ) +//US return QString::null; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + if ( !config ) + return QString::null; + QString s; + s.setNum( number ); + s.prepend( QString::fromLatin1("WindowProperties") ); + config->setGroup( s ); + if ( !config->hasKey( QString::fromLatin1("ClassName") ) ) + return QString::null; + else + return config->readEntry( QString::fromLatin1("ClassName") ); +} + +bool KMainWindow::restore( int number, bool show ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ + if ( !canBeRestored( number ) ) + return FALSE; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + + if ( readPropertiesInternal( config, number ) ){ + if ( show ) + KMainWindow::show(); + return FALSE; + } + return FALSE; + +} + +void KMainWindow::setCaption( const QString &caption ) +{ +//US setPlainCaption( kapp->makeStdCaption(caption) ); + setPlainCaption( caption ); +} + +void KMainWindow::setCaption( const QString &caption, bool modified ) +{ +//US setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); + setPlainCaption( caption + "modified:" ); +} + +void KMainWindow::setPlainCaption( const QString &caption ) +{ + QMainWindow::setCaption( caption ); +#ifndef Q_WS_QWS +//US the following is disabled for the embedded version +//US NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); +//US info.setName( caption.utf8().data() ); +#endif +} + +void KMainWindow::slotStateChanged(const QString &newstate) +{ + stateChanged(newstate, KXMLGUIClient::StateNoReverse); +} + +/* + * Get rid of this for KDE 4.0 + */ +void KMainWindow::slotStateChanged(const QString &newstate, + KXMLGUIClient::ReverseStateChange reverse) +{ + stateChanged(newstate, reverse); +} + +void KMainWindow::closeEvent ( QCloseEvent *e ) +{ + // Save settings if auto-save is enabled, and settings have changed + if (d->settingsDirty && d->autoSaveSettings) + saveAutoSaveSettings(); + + if (queryClose()) { + e->accept(); + + int not_withdrawn = 0; +/*US + QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); + for (it.toFirst(); it.current(); ++it){ + if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) + not_withdrawn++; + } +*/ + if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? +/*US + if ( queryExit() && !kapp->sessionSaving()) { // Yes, Quit app? + // don't call queryExit() twice + disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); + kapp->deref(); // ...and quit aplication. + } else { + // cancel closing, it's stupid to end up with no windows at all.... + e->ignore(); + } +*/ +//US we have no sessionmanagement. Simply close app. + if ( queryExit() ) { // Yes, Quit app? + qDebug("KMainWindow::closeEvent: Exit application ???"); + // don't call queryExit() twice +//US disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); + } + + } + } +} + +bool KMainWindow::queryExit() +{ + return TRUE; +} + +bool KMainWindow::queryClose() +{ + return TRUE; +} + +void KMainWindow::saveGlobalProperties( KConfig* ) +{ +} + +void KMainWindow::readGlobalProperties( KConfig* ) +{ +} + +void KMainWindow::savePropertiesInternal( KConfig *config, int number ) +{ + bool oldASWS = d->autoSaveWindowSize; + d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size + + QString s; + s.setNum(number); + s.prepend(QString::fromLatin1("WindowProperties")); + config->setGroup(s); + + // store objectName, className, Width and Height for later restoring + // (Only useful for session management) + config->writeEntry(QString::fromLatin1("ObjectName"), name()); + config->writeEntry(QString::fromLatin1("ClassName"), className()); + + saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. + + s.setNum(number); + config->setGroup(s); + saveProperties(config); + + d->autoSaveWindowSize = oldASWS; +} + +void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) +{ + if ( enable ) + { + if ( d->toolBarHandler ) + return; + + d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); + +/*US if ( factory() ) + factory()->addClient( d->toolBarHandler ); +*/ + } + else + { + if ( !d->toolBarHandler ) + return; +/*US + if ( factory() ) + factory()->removeClient( d->toolBarHandler ); +*/ + delete d->toolBarHandler; + d->toolBarHandler = 0; + } + +} + +bool KMainWindow::isStandardToolBarMenuEnabled() const +{ + return ( d->toolBarHandler != 0 ); +} + +void KMainWindow::createStandardStatusBarAction(){ + if(!d->showStatusBarAction){ + d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); + connect(d->showStatusBarAction, SIGNAL(toggled(bool)), statusBar(), SLOT(setShown(bool))); + if(internalStatusBar()) + d->showStatusBarAction->setChecked(!internalStatusBar()->isHidden()); + } +} + +QToolBar *KMainWindow::tBar( ) +{ + if ( ! mQToolBar ) + mQToolBar = new QToolBar( this ); + return mQToolBar; +} + +KToolBar *KMainWindow::toolBar( const char * name ) +{ + + if (!name) + name = "mainToolBar"; + KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); + if ( tb ) + return tb; + bool honor_mode = (name == "mainToolBar"); + +/*US + if ( builderClient() ) + return new KToolBar(this, name, honor_mode); // XMLGUI constructor + else +*/ + return new KToolBar(this, Top, false, name, honor_mode ); // non-XMLGUI +} + +QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() +{ + toolbarList.clear(); + QPtrList<QToolBar> lst; + for ( int i = (int)QMainWindow::Unmanaged; i <= (int)Minimized; ++i ) { + lst = toolBars( (ToolBarDock)i ); + for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { + if ( !tb->inherits( "KToolBar" ) ) + continue; + toolbarList.append( (KToolBar*)tb ); + } + } + return QPtrListIterator<KToolBar>( toolbarList ); +} + +void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) +{ + d->autoSaveSettings = true; + d->autoSaveGroup = groupName; + d->autoSaveWindowSize = saveWindowSize; + // Get notified when the user moves a toolbar around +//US connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), +//US this, SLOT( setSettingsDirty() ) ); + connect( this, SIGNAL( toolBarPositionChanged(QToolBar *) ), + this, SLOT( setSettingsDirty() ) ); + + + // Get default values +//US int scnum = QApplication::desktop()->screenNumber(parentWidget()); +//US QRect desk = QApplication::desktop()->screenGeometry(scnum); + QRect desk = KGlobalSettings::desktopGeometry(0); + + d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); + // Now read the previously saved settings + applyMainWindowSettings( KGlobal::config(), groupName ); +} + + +void KMainWindow::resetAutoSaveSettings() +{ + d->autoSaveSettings = false; + if ( d->settingsTimer ) + d->settingsTimer->stop(); +} + +bool KMainWindow::autoSaveSettings() const +{ + return d->autoSaveSettings; +} + +QString KMainWindow::autoSaveGroup() const +{ + return d->autoSaveGroup; +} + +void KMainWindow::saveAutoSaveSettings() +{ + ASSERT( d->autoSaveSettings ); + //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; + saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); + KGlobal::config()->sync(); + d->settingsDirty = false; + if ( d->settingsTimer ) + d->settingsTimer->stop(); +} + +void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory ) +{ + // disabling the updates prevents unnecessary redraws + setUpdatesEnabled( false ); + + // just in case we are rebuilding, let's remove our old client +//US guiFactory()->removeClient( this ); + + // make sure to have an empty GUI + QMenuBar* mb = internalMenuBar(); + if ( mb ) + mb->clear(); + + (void)toolBarIterator(); // make sure toolbarList is most-up-to-date + toolbarList.setAutoDelete( true ); + toolbarList.clear(); + toolbarList.setAutoDelete( false ); +/*US + // don't build a help menu unless the user ask for it + if (d->showHelpMenu) { + // we always want a help menu + if (helpMenu2 == 0) + helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, + actionCollection()); + } + + // we always want to load in our global standards file + setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); + + // now, merge in our local xml file. if this is null, then that + // means that we will be only using the global file + if ( !xmlfile.isNull() ) { + setXMLFile( xmlfile, true ); + } else { + QString auto_file(instance()->instanceName() + "ui.rc"); + setXMLFile( auto_file, true ); + } + + // make sure we don't have any state saved already + setXMLGUIBuildDocument( QDomDocument() ); + + // do the actual GUI building + guiFactory()->addClient( this ); + + // try and get back *some* of our memory + if ( _conserveMemory ) + { + // before freeing the memory allocated by the DOM document we also + // free all memory allocated internally in the KXMLGUIFactory for + // the menubar and the toolbars . This however implies that we + // have to take care of deleting those widgets ourselves. For + // destruction this is no problem, but when rebuilding we have + // to take care of that (and we want to rebuild the GUI when + // using stuff like the toolbar editor ). + // In addition we have to take care of not removing containers + // like popupmenus, defined in the XML document. + // this code should probably go into a separate method in KMainWindow. + // there's just one problem: I'm bad in finding names ;-) , so + // I skipped this ;-) + + QDomDocument doc = domDocument(); + + QDomElement e = doc.documentElement().firstChild().toElement(); + for (; !e.isNull(); e = e.nextSibling().toElement() ) { + if ( e.tagName().lower() == "toolbar" ) + factory_->resetContainer( e.attribute( "name" ) ); + else if ( e.tagName().lower() == "menubar" ) + factory_->resetContainer( e.tagName(), true ); + } + + conserveMemory(); + } +*/ + setUpdatesEnabled( true ); + updateGeometry(); +} + +void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) +{ + kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; +//US QStrList entryList; + QStringList entryList; + QString oldGroup; + + if (!configGroup.isEmpty()) + { + oldGroup = config->group(); + config->setGroup(configGroup); + } + + // Called by session management - or if we want to save the window size anyway + if ( d->autoSaveWindowSize ) + saveWindowSize( config ); + + QStatusBar* sb = internalStatusBar(); + if (sb) { + entryList.clear(); + if ( sb->isHidden() ) + entryList.append("Disabled"); + else + entryList.append("Enabled"); + + if(sb->isHidden()) +//US config->writeEntry(QString::fromLatin1("StatusBar"), entryList, ';'); + config->writeEntry(QString::fromLatin1("StatusBar"), entryList); + else + config->deleteEntry(QString::fromLatin1("StatusBar")); + } + + QMenuBar* mb = internalMenuBar(); + if (mb) { + entryList.clear(); + if ( mb->isHidden() ) + entryList.append("Disabled"); + else + entryList.append("Enabled"); + + // By default we don't hide. + if(mb->isHidden()) +//US config->writeEntry(QString::fromLatin1("MenuBar"), entryList, ';'); + config->writeEntry(QString::fromLatin1("MenuBar"), entryList); + else + config->deleteEntry(QString::fromLatin1("MenuBar")); + } + + int n = 1; // Toolbar counter. toolbars are counted from 1, + KToolBar *toolbar = 0; + QPtrListIterator<KToolBar> it( toolBarIterator() ); + while ( ( toolbar = it.current() ) ) { + ++it; + QString group; + if (!configGroup.isEmpty()) + { + // Give a number to the toolbar, but prefer a name if there is one, + // because there's no real guarantee on the ordering of toolbars + group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); + group.prepend(" Toolbar"); + group.prepend(configGroup); + } + toolbar->saveSettings(config, group); + n++; + } + if (!configGroup.isEmpty()) + config->setGroup(oldGroup); +} + +bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) +{ + if ( number == 1 ) + readGlobalProperties( config ); + + // in order they are in toolbar list + QString s; + s.setNum(number); + s.prepend(QString::fromLatin1("WindowProperties")); + + config->setGroup(s); + + // restore the object name (window role) + if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) + setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here + + applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. + + s.setNum(number); + config->setGroup(s); + readProperties(config); + return true; +} + +void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) +{ + kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; + QString entry; +//US QStrList entryList; + QStringList entryList; + int i = 0; // Number of entries in list + + if (!configGroup.isEmpty()) + config->setGroup(configGroup); + + restoreWindowSize(config); + + QStatusBar* sb = internalStatusBar(); + if (sb) { + entryList.clear(); +//US i = config->readListEntry (QString::fromLatin1("StatusBar"), entryList, ';'); + entryList = config->readListEntry (QString::fromLatin1("StatusBar")); + entry = entryList.first(); + if (entry == QString::fromLatin1("Disabled")) + sb->hide(); + else + sb->show(); + if(d->showStatusBarAction) + d->showStatusBarAction->setChecked(!sb->isHidden()); + } + + QMenuBar* mb = internalMenuBar(); + if (mb) { + entryList.clear(); +//US i = config->readListEntry (QString::fromLatin1("MenuBar"), entryList, ';'); + entryList = config->readListEntry (QString::fromLatin1("MenuBar")); + entry = entryList.first(); + if (entry==QString::fromLatin1("Disabled")) + { + mb->hide(); + } else + { + mb->show(); + } + } + + int n = 1; // Toolbar counter. toolbars are counted from 1, + KToolBar *toolbar; + QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator + + for ( ; it.current(); ++it) { + toolbar= it.current(); + QString group; + if (!configGroup.isEmpty()) + { + // Give a number to the toolbar, but prefer a name if there is one, + // because there's no real guarantee on the ordering of toolbars + group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); + group.prepend(" Toolbar"); + group.prepend(configGroup); + } + toolbar->applySettings(config, group); + n++; + } + + finalizeGUI( true ); + } + +void KMainWindow::finalizeGUI( bool force ) +{ + //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; + // The whole reason for this is that moveToolBar relies on the indexes + // of the other toolbars, so in theory it should be called only once per + // toolbar, but in increasing order of indexes. + // Since we can't do that immediately, we move them, and _then_ + // we call positionYourself again for each of them, but this time + // the toolbariterator should give them in the proper order. + // Both the XMLGUI and applySettings call this, hence "force" for the latter. + QPtrListIterator<KToolBar> it( toolBarIterator() ); + for ( ; it.current() ; ++ it ) + it.current()->positionYourself( force ); + + d->settingsDirty = false; +} + +void KMainWindow::saveWindowSize( KConfig * config ) const +{ +/*US + int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); +*/ + QRect desk = KGlobalSettings::desktopGeometry(0); + + QRect size( desk.width(), width(), desk.height(), height() ); + if(size != d->defaultWindowSize){ + config->writeEntry(QString::fromLatin1("Width %1").arg(desk.width()), width() ); + config->writeEntry(QString::fromLatin1("Height %1").arg(desk.height()), height() ); + } + else{ + config->deleteEntry(QString::fromLatin1("Width %1").arg(desk.width())); + config->deleteEntry(QString::fromLatin1("Height %1").arg(desk.height())); + } +} + +void KMainWindow::restoreWindowSize( KConfig * config ) +{ + if (d->care_about_geometry) { + parseGeometry(true); + } else { + // restore the size +/*US int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); +*/ + QRect desk = KGlobalSettings::desktopGeometry(0); + + QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), + config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); + if (size.isEmpty()) { + // try the KDE 2.0 way + size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), + config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); + if (!size.isEmpty()) { + // make sure the other resolutions don't get old settings + config->writeEntry( QString::fromLatin1("Width"), 0 ); + config->writeEntry( QString::fromLatin1("Height"), 0 ); + } + } + if ( !size.isEmpty() ) + resize( size ); + } +} + +bool KMainWindow::initialGeometrySet() const +{ + return d->care_about_geometry; +} + +void KMainWindow::ignoreInitialGeometry() +{ + d->care_about_geometry = false; +} + +void KMainWindow::setSettingsDirty() +{ + //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; + d->settingsDirty = true; + if ( d->autoSaveSettings ) + { + // Use a timer to save "immediately" user-wise, but not too immediately + // (to compress calls and save only once, in case of multiple changes) + if ( !d->settingsTimer ) + { + d->settingsTimer = new QTimer( this ); + connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); + } + d->settingsTimer->start( 500, true ); + } +} + +bool KMainWindow::settingsDirty() const +{ + return d->settingsDirty; +} + +QString KMainWindow::settingsGroup() const +{ + return d->autoSaveGroup; +} + +void KMainWindow::resizeEvent( QResizeEvent * ) +{ + if ( d->autoSaveWindowSize ) + setSettingsDirty(); +} + +bool KMainWindow::hasMenuBar() +{ + return (internalMenuBar()); +} + +//US KMenuBar *KMainWindow::menuBar() +QMenuBar *KMainWindow::menuBar() +{ +//US KMenuBar * mb = internalMenuBar(); + QMenuBar * mb = internalMenuBar(); + if ( !mb ) { +//US mb = new KMenuBar( this ); + mb = new QMenuBar( this ); + // trigger a re-layout and trigger a call to the private + // setMenuBar method. + QMainWindow::menuBar(); + } + return mb; +} + +//US KStatusBar *KMainWindow::statusBar() +QStatusBar *KMainWindow::statusBar() +{ +//US KStatusBar * sb = internalStatusBar(); + QStatusBar * sb = internalStatusBar(); + if ( !sb ) { +//US sb = new KStatusBar( this ); + sb = new QStatusBar( this ); + // trigger a re-layout and trigger a call to the private + // setStatusBar method. + QMainWindow::statusBar(); + } + return sb; +} + +void KMainWindow::shuttingDown() +{ + // Needed for Qt <= 3.0.3 at least to prevent reentrancy + // when queryExit() shows a dialog. Check before removing! + static bool reentrancy_protection = false; + if (!reentrancy_protection) + { + reentrancy_protection = true; + // call the virtual queryExit + queryExit(); + reentrancy_protection = false; + } + +} + +//US KMenuBar *KMainWindow::internalMenuBar() +QMenuBar *KMainWindow::internalMenuBar() +{ +//US QObjectList *l = queryList( "KMenuBar", 0, false, false ); + QObjectList *l = queryList( "QMenuBar", 0, false, false ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + +//US KMenuBar *m = (KMenuBar*)l->first(); + QMenuBar *m = (QMenuBar*)l->first(); + delete l; + return m; +} + +//US KStatusBar *KMainWindow::internalStatusBar() +QStatusBar *KMainWindow::internalStatusBar() +{ +//US QObjectList *l = queryList( "KStatusBar", 0, false, false ); + QObjectList *l = queryList( "QStatusBar", 0, false, false ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + +//US KStatusBar *s = (KStatusBar*)l->first(); + QStatusBar *s = (QStatusBar*)l->first(); + delete l; + return s; +} + +void KMainWindow::childEvent( QChildEvent* e) +{ + QMainWindow::childEvent( e ); +} + +void KMainWindow::paintEvent( QPaintEvent * ) +{ + // do nothing +} + +QSize KMainWindow::sizeForCentralWidgetSize(QSize size) +{ + KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); + if (tb && !tb->isHidden()) { + switch( tb->barPos() ) + { + case KToolBar::Top: + case KToolBar::Bottom: + size += QSize(0, tb->sizeHint().height()); + break; + + case KToolBar::Left: + case KToolBar::Right: + size += QSize(toolBar()->sizeHint().width(), 0); + break; + + case KToolBar::Flat: +//US size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); + size += QSize(0, tb->sizeHint().height()); + break; + + default: + break; + } + } +//US KMenuBar *mb = menuBar(); + QMenuBar *mb = menuBar(); + if (!mb->isHidden()) { + size += QSize(0,mb->heightForWidth(size.width())); +/*US if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) + size += QSize( 0, dockWindowsMovable() ? 1 : 2); +*/ + size += QSize( 0, 2); + } + QStatusBar *sb = internalStatusBar(); + if( sb && !sb->isHidden() ) + size += QSize(0, sb->sizeHint().height()); + + return size; +} + +// why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; +void KMainWindow::finalizeGUI( KXMLGUIClient *client ) +{ /*US KXMLGUIBuilder::finalizeGUI( client );*/ } + +void KMainWindow::virtual_hook( int id, void* data ) +{ /*US KXMLGUIBuilder::virtual_hook( id, data );*/ + KXMLGUIClient::virtual_hook( id, data ); } diff --git a/microkde/kdeui/kmainwindow.h b/microkde/kdeui/kmainwindow.h new file mode 100644 index 0000000..e76e732 --- a/dev/null +++ b/microkde/kdeui/kmainwindow.h @@ -0,0 +1,776 @@ +/* + This file is part of the KDE libraries + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + $Id$ + +*/ + + + +#ifndef KMAINWINDOW_H +#define KMAINWINDOW_H + +/*US +#include "kxmlguifactory.h" +#include "kxmlguiclient.h" +#include "kxmlguibuilder.h" +#include <qmetaobject.h> + +class KPopupMenu; +class KXMLGUIFactory; +class KConfig; +class KHelpMenu; +class KStatusBar; +class QStatusBar; +class KMenuBar; +class KMWSessionManaged; +class KAccel; +class KToolBarMenuAction; +*/ + +class QMenuBar; +class QStatusBar; +class KMainWindowPrivate; +class KAction; + +#include <ktoolbar.h> +#include <ktoolbarhandler.h> +#include <kxmlguiclient.h> +#include <qmainwindow.h> +#include <qptrlist.h> + +class KActionCollection; + +class KMainWindow : public QMainWindow, virtual public KXMLGUIClient +{ + Q_OBJECT + +private: +//US create private defaultconstructor + KMainWindow() {;}; + +public: +public: + /** + * Construct a main window. + * + * @param parent The widget parent. This is usually 0 but it may also be the window + * group leader. In that case, the KMainWindow becomes sort of a + * secondary window. + * + * @param name The object name. For session management and window management to work + * properly, all main windows in the application should have a + * different name. When passing 0 (the default), KMainWindow will create + * a unique name, but it's recommended to explicitly pass a window name that will + * also describe the type of the window. If there can be several windows of the same + * type, append '#' (hash) to the name, and KMainWindow will append numbers to make + * the names unique. For example, for a mail client which has one main window showing + * the mails and folders, and which can also have one or more windows for composing + * mails, the name for the folders window should be e.g. "mainwindow" and + * for the composer windows "composer#". + * + * @param f Specify the widget flags. The default is + * WType_TopLevel and WDestructiveClose. TopLevel indicates that a + * main window is a toplevel window, regardless of whether it has a + * parent or not. DestructiveClose indicates that a main window is + * automatically destroyed when its window is closed. Pass 0 if + * you do not want this behavior. + * + * KMainWindows must be created on the heap with 'new', like: + * <pre> KMainWindow *kmw = new KMainWindow (...</pre> + **/ + KMainWindow( QWidget* parent = 0, const char *name = 0, WFlags f = WType_TopLevel | WDestructiveClose ); + + + /** + * Destructor. + * + * Will also destroy the toolbars, and menubar if + * needed. + */ + virtual ~KMainWindow(); + + /** + * Retrieve the standard help menu. + * + * It contains entires for the + * help system (activated by F1), an optional "What's This?" entry + * (activated by Shift F1), an application specific dialog box, + * and an "About KDE" dialog box. + * + * Example (adding a standard help menu to your application): + * <pre> + * KPopupMenu *help = helpMenu( <myTextString> ); + * menuBar()->insertItem( i18n("&Help"), help ); + * </pre> + * + * @param aboutAppText The string that is used in the application + * specific dialog box. If you leave this string empty the + * information in the global @ref KAboutData of the + * application will be used to make a standard dialog box. + * + * @param showWhatsThis Set this to false if you do not want to include + * the "What's This" menu entry. + * + * @return A standard help menu. + */ +//US KPopupMenu* helpMenu( const QString &aboutAppText = QString::null, +//US bool showWhatsThis = TRUE ); + + /** + * Returns the help menu. Creates a standard help menu if none exists yet. + * + * It contains entries for the + * help system (activated by F1), an optional "What's This?" entry + * (activated by Shift F1), an application specific dialog box, + * and an "About KDE" dialog box. You must create the application + * specific dialog box yourself. When the "About application" + * menu entry is activated, a signal will trigger the + * @ref showAboutApplication slot. See @ref showAboutApplication for more + * information. + * + * Example (adding a help menu to your application): + * <pre> + * menuBar()->insertItem( i18n("&Help"), customHelpMenu() ); + * </pre> + * + * @param showWhatsThis Set this to @p false if you do not want to include + * the "What's This" menu entry. + * + * @return A standard help menu. + */ +//US KPopupMenu* customHelpMenu( bool showWhatsThis = TRUE ); + + /** + * @sect Session Management + * + * Try to restore the toplevel widget as defined by the number (1..X). + * + * If the session did not contain so high a number, the configuration + * is not changed and @p false returned. + * + * That means clients could simply do the following: + * <pre> + * if (kapp->isRestored()){ + * int n = 1; + * while (KMainWindow::canBeRestored(n)){ + * (new childMW)->restore(n); + * n++; + * } + * } else { + * // create default application as usual + * } + * </pre> + * Note that @ref QWidget::show() is called implicitly in restore. + * + * With this you can easily restore all toplevel windows of your + * application. + * + * If your application uses different kinds of toplevel + * windows, then you can use @ref KMainWindow::classNameOfToplevel(n) + * to determine the exact type before calling the childMW + * constructor in the example from above. + * + * If your client has only one kind of toplevel widgets (which + * should be pretty usual) then you should use the RESTORE-macro + * for backwards compatibility with 3.1 and 3.0 branches: + * + * <pre> + * if (kapp->isRestored()) + * RESTORE(childMW) + * else { + * // create default application as usual + * } + * </pre> + * + * The macro expands to the term above but is easier to use and + * less code to write. + * + * For new code or if you have more than one kind of toplevel + * widget (each derived from @ref KMainWindow, of course), you can + * use the templated @ref kRestoreMainWindows global functions: + * + * <pre> + * if (kapp->isRestored()) + * kRestoreMainWindows< childMW1, childMW2, childMW3 >(); + * else { + * // create default application as usual + * } + * </pre> + * + * Currently, these functions are provided for up to three + * template arguments. If you need more, tell us. To help you in + * deciding whether or not you can use @ref kRestoreMainWindows, a + * define KDE_RESTORE_MAIN_WINDOWS_NUM_TEMPLATE_ARGS is provided. + * + * @see restore() + * @see classNameOfToplevel() + * + **/ + static bool canBeRestored( int number ); + + /** + * Returns the @ref className() of the @p number of the toplevel window which + * should be restored. + * + * This is only useful if your application uses + * different kinds of toplevel windows. + */ + static const QString classNameOfToplevel( int number ); + + /** + * Restore the session specified by @p number. + * + * Returns @p false if this + * fails, otherwise returns @p true and shows the window. + * You should call @ref canBeRestored() first. + * If @p show is true (default), this widget will be shown automatically. + */ + bool restore( int number, bool show = TRUE ); + +//US virtual KXMLGUIFactory *guiFactory(); + + /** + * Create a GUI given a local XML file. + * + * If @p xmlfile is NULL, + * then it will try to construct a local XML filename like + * appnameui.rc where 'appname' is your app's name. If that file + * does not exist, then the XML UI code will only use the global + * (standard) XML file for the layout purposes. + * + * Note that when passing true for the conserveMemory argument subsequent + * calls to guiFactory()->addClient/removeClient may not work as expected. + * Also retrieving references to containers like popup menus or toolbars using + * the container method will not work. + * + * @param xmlfile The local xmlfile (relative or absolute) + * @param _conserveMemory Specify whether createGUI() should call + * @ref KXMLGuiClient::conserveMemory() to free all memory + * allocated by the @ref QDomDocument and by the KXMLGUIFactory. + */ + void createGUI( const QString &xmlfile = QString::null, bool _conserveMemory = TRUE ); + + /** + * Enables the build of a standard help menu when calling createGUI(). + * + * The default behavior is to build one, you must call this function + * to disable it + */ + void setHelpMenuEnabled(bool showHelpMenu = true); + + /** + * Return @p true when the help menu is enabled + */ + bool isHelpMenuEnabled(); + + + /** + * Returns true, if there is a menubar + * @since 3.1 + */ + bool hasMenuBar(); + + /** + * Returns a pointer to the menu bar. + * + * If there is no menu bar yet one will be created. + **/ +//US KMenuBar *menuBar(); + QMenuBar *menuBar(); + + /** + * Returns a pointer to the status bar. + * + * If there is no + * status bar yet one will be created. + */ +//US KStatusBar *statusBar(); + QStatusBar *statusBar(); + + /** + * List of members of KMainWindow class. + */ +//US static QPtrList<KMainWindow>* memberList; + + /** + * Returns a pointer to the toolbar with the specified name. + * This refers to toolbars created dynamically from the XML UI + * framework. If the toolbar does not exist one will be created. + * + * @param name The internal name of the toolbar. If no name is + * specified "mainToolBar" is assumed. + * + * @return A pointer to the toolbar + **/ + KToolBar *toolBar( const char *name=0 ); + // method for getting rid of KDE-Crap + QToolBar *tBar( ); + + /** + * @return An iterator over the list of all toolbars for this window. + */ + QPtrListIterator<KToolBar> toolBarIterator(); + + /** + * @return A KAccel instance bound to this mainwindow. Used automatically + * by KAction to make keybindings work in all cases. + */ + KAccel *accel(); + + void setFrameBorderWidth( int ) {} + + /** + * Call this to enable "auto-save" of toolbar/menubar/statusbar settings + * (and optionally window size). + * If the *bars were moved around/shown/hidden when the window is closed, + * saveMainWindowSettings( KGlobal::config(), groupName ) will be called. + * + * @param groupName a name that identifies this "type of window". + * You can have several types of window in the same application. + * + * @param saveWindowSize set it to true to include the window size + * when saving. + * + * Typically, you will call setAutoSaveSettings() in your + * KMainWindow-inherited class constructor, and it will take care + * of restoring and saving automatically. Make sure you call this + * _after all_ your *bars have been created. + */ + void setAutoSaveSettings( const QString & groupName = QString::fromLatin1("MainWindow"), + bool saveWindowSize = true ); + + /** + * Disable the auto-save-settings feature. + * You don't normally need to call this, ever. + */ + void resetAutoSaveSettings(); + + /** + * @return the current autosave setting, i.e. true if setAutoSaveSettings() was called, + * false by default or if resetAutoSaveSettings() was called. + * @since 3.1 + */ + bool autoSaveSettings() const; + + /** + * @return the group used for setting-autosaving. + * Only meaningful if setAutoSaveSettings() was called. + * This can be useful for forcing a save or an apply, e.g. before and after + * using KEditToolbar. + * @since 3.1 + */ + QString autoSaveGroup() const; + + /** + * Read settings for statusbar, menubar and toolbar from their respective + * groups in the config file and apply them. + * + * @param config Config file to read the settings from. + * @param groupName Group name to use. If not specified, the last used + * group name is used. + */ + void applyMainWindowSettings(KConfig *config, const QString &groupName = QString::null); + + /** + * Save settings for statusbar, menubar and toolbar to their respective + * groups in the config file @p config. + * + * @param config Config file to save the settings to. + * @param groupName Group name to use. If not specified, the last used + * group name is used + */ + void saveMainWindowSettings(KConfig *config, const QString &groupName = QString::null); + + /** + * Sets whether KMainWindow should provide a menu that allows showing/hiding + * the available toolbars ( using @ref KToggleToolBarAction ) . In case there + * is only one toolbar configured a simple 'Show <toolbar name here>' menu item + * is shown. + * + * The menu / menu item is implemented using xmlgui. It will be inserted in your + * menu structure in the 'Settings' menu. + * + * If your application uses a non-standard xmlgui resource file then you can + * specify the exact position of the menu / menu item by adding a + * <Merge name="StandardToolBarMenuHandler" /> + * line to the settings menu section of your resource file ( usually appname.rc ). + * + * Note that you should enable this feature before calling createGUI() ( or similar ) . + * You enable/disable it anytime if you pass false to the conserveMemory argument of createGUI. + * @since 3.1 + */ + void setStandardToolBarMenuEnabled( bool enable ); + /// @since 3.1 + bool isStandardToolBarMenuEnabled() const; + + + /** + * Sets whether KMainWindow should provide a menu that allows showing/hiding + * of the statusbar ( using @ref KToggleStatusBarAction ). + * + * The menu / menu item is implemented using xmlgui. It will be inserted + * in your menu structure in the 'Settings' menu. + * + * Note that you should enable this feature before calling createGUI() + * ( or similar ). + * + * If an application maintains the action on its own (i.e. never calls + * this function) a connection needs to be made to let KMainWindow + * know when that status (hidden/shown) of the statusbar has changed. + * For example: + * connect(action, SIGNAL(activated()), + * kmainwindow, SLOT(setSettingsDirty())); + * Otherwise the status (hidden/show) of the statusbar might not be saved + * by KMainWindow. + * @since 3.2 + */ + void createStandardStatusBarAction(); + + + /** + * Returns a pointer to the mainwindows action responsible for the toolbars menu + * @since 3.1 + */ + KAction *toolBarMenuAction(); + + // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; + /// @since 3.1 + virtual void finalizeGUI( KXMLGUIClient *client ); + + /** + * @internal + */ + void finalizeGUI( bool force ); + + /** + * @return true if a -geometry argument was given on the command line, + * and this is the first window created (the one on which this option applies) + */ + bool initialGeometrySet() const; + + /** + * @internal + * Used from Konqueror when reusing the main window. + */ + void ignoreInitialGeometry(); + + /** + * @return the size the mainwindow should have so that the central + * widget will be of @p size. + */ + QSize sizeForCentralWidgetSize(QSize size); + +public slots: + /** + * Makes a KDE compliant caption. + * + * @param caption Your caption. @em Do @em not include the application name + * in this string. It will be added automatically according to the KDE + * standard. + */ + virtual void setCaption( const QString &caption ); + /** + * Makes a KDE compliant caption. + * + * @param caption Your caption. @em Do @em not include the application name + * in this string. It will be added automatically according to the KDE + * standard. + * @param modified Specify whether the document is modified. This displays + * an additional sign in the title bar, usually "**". + */ + virtual void setCaption( const QString &caption, bool modified ); + + /** + * Make a plain caption without any modifications. + * + * @param caption Your caption. This is the string that will be + * displayed in the window title. + */ + virtual void setPlainCaption( const QString &caption ); + + /** + * Open the help page for the application. + * + * The application name is + * used as a key to determine what to display and the system will attempt + * to open <appName>/index.html. + * + * This method is intended for use by a help button in the toolbar or + * components outside the regular help menu. Use @ref helpMenu() when you + * want to provide access to the help system from the help menu. + * + * Example (adding a help button to the first toolbar): + * + * <pre> + * KIconLoader &loader = *KGlobal::iconLoader(); + * QPixmap pixmap = loader.loadIcon( "help" ); + * toolBar(0)->insertButton( pixmap, 0, SIGNAL(clicked()), + * this, SLOT(appHelpActivated()), true, i18n("Help") ); + * </pre> + * + */ +//US void appHelpActivated( void ); + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file + * @since 3.1 + */ + virtual void slotStateChanged(const QString &newstate); + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file, + * can "reverse" the state (disable the actions which should be + * enabled, and vice-versa) if specified. + * @since 3.1 + */ + void slotStateChanged(const QString &newstate, + KXMLGUIClient::ReverseStateChange); // KDE 4.0: remove this + + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file, + * can "reverse" the state (disable the actions which should be + * enabled, and vice-versa) if specified. + */ +// void slotStateChanged(const QString &newstate, +// bool reverse); // KDE 4.0: enable this + + /** + * Tell the main window that it should save its settings when being closed. + * This is part of the auto-save-settings feature. + * For everything related to toolbars this happens automatically, + * but you have to call setSettingsDirty() in the slot that toggles + * the visibility of the statusbar. + */ + void setSettingsDirty(); + +protected: + void paintEvent( QPaintEvent* e ); + void childEvent( QChildEvent* e); + void resizeEvent( QResizeEvent* e); + /** + * Reimplemented to call the queryClose() and queryExit() handlers. + * + * We recommend that you reimplement the handlers rather than @ref closeEvent(). + * If you do it anyway, ensure to call the base implementation to keep + * @ref queryExit() running. + */ + virtual void closeEvent ( QCloseEvent *); + + // KDE4 This seems to be flawed to me. Either the app has only one + // mainwindow, so queryClose() is enough, or if it can have more of them, + // then the windows should take care of themselves, and queryExit() + // would be useful only for the annoying 'really quit' dialog, which + // also doesn't make sense in apps with multiple mainwindows. + // And saving configuration in something called queryExit()? IMHO + // one can e.g. use KApplication::shutDown(), which if nothing else + // has at least better fitting name. + // See also KApplication::sessionSaving(). + // This stuff should get changed somehow, so that it at least doesn't + // mess with session management. + /** + Called before the very last window is closed, either by the + user or indirectly by the session manager. + + It is not recommended to do any user interaction in this + function other than indicating severe errors. Better ask the + user on @ref queryClose() (see below). + + A typical usage of @ref queryExit() is to write configuration data back. + Note that the application may continue to run after @ref queryExit() + (the user may have cancelled a shutdown), so you should not do any cleanups + here. The purpose of @ref queryExit() is purely to prepare the application + (with possible user interaction) so it can safely be closed later (without + user interaction). + + If you need to do serious things on exit (like shutting a + dial-up connection down), connect to the signal + @ref KApplication::shutDown(). + + Default implementation returns @p true. Returning @p false will + cancel the exiting. In the latter case, the last window will + remain visible. If KApplication::sessionSaving() is true, refusing + the exit will also cancel KDE logout. + + @see queryClose() + @see KApplication::sessionSaving() + */ + virtual bool queryExit(); + + /** + Called before the window is closed, either by the user or indirectly by + the session manager. + + The purpose of this function is to prepare the window in a way that it is + safe to close it, i.e. without the user losing some data. + + Default implementation returns true. Returning @p false will cancel + the closing, and, if KApplication::sessionSaving() is true, it will also + cancel KDE logout. + + Reimplement this function to prevent the user from losing data. + Example: + <pre> + + switch ( KMessageBox::warningYesNoCancel( this, + i18n("Save changes to document foo?")) ) { + case KMessageBox::Yes : + // save document here. If saving fails, return FALSE; + return TRUE; + case KMessageBox::No : + return TRUE; + default: // cancel + return FALSE; + + </pre> + + @see queryExit() + @see KApplication::sessionSaving() + + */ + virtual bool queryClose(); + /** + * Save your instance-specific properties. The function is + * invoked when the session manager requests your application + * to save its state. + * + * You @em must @em not change the group of the @p kconfig object, since + * KMainWindow uses one group for each window. Please + * reimplement these function in childclasses. + * + * Note: No user interaction is allowed + * in this function! + * + */ + virtual void saveProperties( KConfig* ) {} + + /** + * Read your instance-specific properties. + */ + virtual void readProperties( KConfig* ) {} + + /** + * Save your application-wide properties. The function is + * invoked when the session manager requests your application + * to save its state. + * + * This function is similar to @ref saveProperties() but is only called for + * the very first main window, regardless how many main window are open. + + * Override it if you need to save other data about your documents on + * session end. sessionConfig is a config to which that data should be + * saved. Normally, you don't need this function. But if you want to save + * data about your documents that are not in opened windows you might need + * it. + * + * Default implementation does nothing. + */ + virtual void saveGlobalProperties( KConfig* sessionConfig ); + + /** + * The counterpart of @ref saveGlobalProperties(). + * + * Read the application-specific properties in again. + */ + virtual void readGlobalProperties( KConfig* sessionConfig ); + void savePropertiesInternal( KConfig*, int ); + bool readPropertiesInternal( KConfig*, int ); + + /** + * For inherited classes + */ + bool settingsDirty() const; + /** + * For inherited classes + */ + QString settingsGroup() const; + /** + * For inherited classes + * Note that the group must be set before calling + */ + void saveWindowSize( KConfig * config ) const; + /** + * For inherited classes + * Note that the group must be set before calling, and that + * a -geometry on the command line has priority. + */ + void restoreWindowSize( KConfig * config ); + + /// parse the geometry from the geometry command line argument + void parseGeometry(bool parsewidth); + +protected slots: + + /** + * This slot does nothing. + * + * It must be reimplemented if you want + * to use a custom About Application dialog box. This slot is + * connected to the About Application entry in the menu returned + * by @ref customHelpMenu. + * + * Example: + * <pre> + * + * void MyMainLevel::setupInterface() + * { + * .. + * menuBar()->insertItem( i18n("&Help"), customHelpMenu() ); + * .. + * } + * + * void MyMainLevel::showAboutApplication() + * { + * <activate your custom dialog> + * } + * </pre> + */ +//US virtual void showAboutApplication(); + +private slots: + /** + * Called when the app is shutting down. + */ + void shuttingDown(); + + void saveAutoSaveSettings(); + +private: + QToolBar * mQToolBar; +//US KMenuBar *internalMenuBar(); + QMenuBar *internalMenuBar(); +//US KStatusBar *internalStatusBar(); + QStatusBar *internalStatusBar(); + + KMainWindowPrivate *d; + void initKMainWindow(const char *name); + + QPtrList<KToolBar> toolbarList; + +protected: + virtual void virtual_hook( int id, void* data ); + +}; + +#endif diff --git a/microkde/kdeui/knuminput.cpp b/microkde/kdeui/knuminput.cpp new file mode 100644 index 0000000..335d6f4 --- a/dev/null +++ b/microkde/kdeui/knuminput.cpp @@ -0,0 +1,1095 @@ +// -*- c-basic-offset: 4 -*- +/* + * knuminput.cpp + * + * Initial implementation: + * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca> + * Rewritten and maintained by: + * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org> + * KDoubleSpinBox: + * Copyright (c) 2002 Marc Mutz <mutz@kde.org> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +//US #include <config.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#include <assert.h> +#include <math.h> +#include <algorithm> + +#include <qlabel.h> +#include <qlineedit.h> +#include <qsize.h> +#include <qslider.h> +#include <qspinbox.h> +#include <qstyle.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "knumvalidator.h" +#include "knuminput.h" + +static inline int calcDiffByTen( int x, int y ) { + // calculate ( x - y ) / 10 without overflowing ints: + return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10; +} + +// ---------------------------------------------------------------------------- + +KNumInput::KNumInput(QWidget* parent, const char* name) + : QWidget(parent, name) +{ + init(); +} + +KNumInput::KNumInput(KNumInput* below, QWidget* parent, const char* name) + : QWidget(parent, name) +{ + init(); + + if(below) { + m_next = below->m_next; + m_prev = below; + below->m_next = this; + if(m_next) + m_next->m_prev = this; + } +} + +void KNumInput::init() +{ + m_prev = m_next = 0; + m_colw1 = m_colw2 = 0; + + m_label = 0; + m_slider = 0; + m_alignment = 0; +} + +KNumInput::~KNumInput() +{ + if(m_prev) + m_prev->m_next = m_next; + + if(m_next) + m_next->m_prev = m_prev; +} + +void KNumInput::setLabel(const QString & label, int a) +{ + if(label.isEmpty()) { + delete m_label; + m_label = 0; + m_alignment = 0; + } + else { + if (m_label) m_label->setText(label); + else m_label = new QLabel(label, this, "KNumInput::QLabel"); + m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter))) + | AlignVCenter); + // if no vertical alignment set, use Top alignment + if(!(a & (AlignTop|AlignBottom|AlignVCenter))) + a |= AlignTop; + m_alignment = a; + } + + layout(true); +} + +QString KNumInput::label() const +{ + if (m_label) return m_label->text(); + return QString::null; +} + +void KNumInput::layout(bool deep) +{ + int w1 = m_colw1; + int w2 = m_colw2; + + // label sizeHint + m_sizeLabel = (m_label ? m_label->sizeHint() : QSize(0,0)); + + if(m_label && (m_alignment & AlignVCenter)) + m_colw1 = m_sizeLabel.width() + 4; + else + m_colw1 = 0; + + // slider sizeHint + m_sizeSlider = (m_slider ? m_slider->sizeHint() : QSize(0, 0)); + + doLayout(); + + if(!deep) { + m_colw1 = w1; + m_colw2 = w2; + return; + } + + KNumInput* p = this; + while(p) { + p->doLayout(); + w1 = QMAX(w1, p->m_colw1); + w2 = QMAX(w2, p->m_colw2); + p = p->m_prev; + } + + p = m_next; + while(p) { + p->doLayout(); + w1 = QMAX(w1, p->m_colw1); + w2 = QMAX(w2, p->m_colw2); + p = p->m_next; + } + + p = this; + while(p) { + p->m_colw1 = w1; + p->m_colw2 = w2; + p = p->m_prev; + } + + p = m_next; + while(p) { + p->m_colw1 = w1; + p->m_colw2 = w2; + p = p->m_next; + } + +// kdDebug() << "w1 " << w1 << " w2 " << w2 << endl; +} + +QSizePolicy KNumInput::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); +} + +QSize KNumInput::sizeHint() const +{ + return minimumSizeHint(); +} + +void KNumInput::setSteps(int minor, int major) +{ + if(m_slider) + m_slider->setSteps( minor, major ); +} + + +// ---------------------------------------------------------------------------- + +KIntSpinBox::KIntSpinBox(QWidget *parent, const char *name) + : QSpinBox(0, 99, 1, parent, name) +{ + editor()->setAlignment(AlignRight); + val_base = 10; + setValue(0); +} + +KIntSpinBox::~KIntSpinBox() +{ +} + +KIntSpinBox::KIntSpinBox(int lower, int upper, int step, int value, int base, + QWidget* parent, const char* name) + : QSpinBox(lower, upper, step, parent, name) +{ + editor()->setAlignment(AlignRight); + val_base = base; + setValue(value); +} + +void KIntSpinBox::setBase(int base) +{ + val_base = base; +} + + +int KIntSpinBox::base() const +{ + return val_base; +} + +QString KIntSpinBox::mapValueToText(int v) +{ + return QString::number(v, val_base); +} + +int KIntSpinBox::mapTextToValue(bool* ok) +{ + return cleanText().toInt(ok, val_base); +} + +void KIntSpinBox::setEditFocus(bool mark) +{ + editor()->setFocus(); + if(mark) + editor()->selectAll(); +} + + +// ---------------------------------------------------------------------------- + +class KIntNumInput::KIntNumInputPrivate { +public: + int referencePoint; + short blockRelative; + KIntNumInputPrivate( int r ) + : referencePoint( r ), + blockRelative( 0 ) {} +}; + + +KIntNumInput::KIntNumInput(KNumInput* below, int val, QWidget* parent, + int _base, const char* name) + : KNumInput(below, parent, name) +{ + init(val, _base); +} + +KIntNumInput::KIntNumInput(QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(0, 10); +} + +KIntNumInput::KIntNumInput(int val, QWidget *parent, int _base, const char *name) + : KNumInput(parent, name) +{ + init(val, _base); + +} + +void KIntNumInput::init(int val, int _base) +{ + d = new KIntNumInputPrivate( val ); + m_spin = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base, this, "KIntNumInput::KIntSpinBox"); + m_spin->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidtr")); + connect(m_spin, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int))); + connect(this, SIGNAL(valueChanged(int)), + SLOT(slotEmitRelativeValueChanged(int))); + + setFocusProxy(m_spin); + layout(true); +} + +void KIntNumInput::setReferencePoint( int ref ) { + // clip to valid range: + ref = kMin( maxValue(), kMax( minValue(), ref ) ); + d->referencePoint = ref; +} + +int KIntNumInput::referencePoint() const { + return d->referencePoint; +} + +void KIntNumInput::spinValueChanged(int val) +{ + if(m_slider) + m_slider->setValue(val); + + emit valueChanged(val); +} + +void KIntNumInput::slotEmitRelativeValueChanged( int value ) { + if ( d->blockRelative || !d->referencePoint ) return; + emit relativeValueChanged( double( value ) / double( d->referencePoint ) ); +} + +void KIntNumInput::setRange(int lower, int upper, int step, bool slider) +{ + upper = kMax(upper, lower); + lower = kMin(upper, lower); + m_spin->setMinValue(lower); + m_spin->setMaxValue(upper); + m_spin->setLineStep(step); + + step = m_spin->lineStep(); // maybe QRangeControl didn't like out lineStep? + + if(slider) { + if (m_slider) + m_slider->setRange(lower, upper); + else { + m_slider = new QSlider(lower, upper, step, m_spin->value(), + QSlider::Horizontal, this); + m_slider->setTickmarks(QSlider::Below); + connect(m_slider, SIGNAL(valueChanged(int)), + m_spin, SLOT(setValue(int))); + } + + // calculate (upper-lower)/10 without overflowing int's: + int major = calcDiffByTen( upper, lower ); + if ( major==0 ) major = step; // #### workaround Qt bug in 2.1-beta4 + + m_slider->setSteps(step, major); + m_slider->setTickInterval(major); + } + else { + delete m_slider; + m_slider = 0; + } + + // check that reference point is still inside valid range: + setReferencePoint( referencePoint() ); + + layout(true); +} + +void KIntNumInput::setMinValue(int min) +{ + setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider); +} + +int KIntNumInput::minValue() const +{ + return m_spin->minValue(); +} + +void KIntNumInput::setMaxValue(int max) +{ + setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider); +} + +int KIntNumInput::maxValue() const +{ + return m_spin->maxValue(); +} + +void KIntNumInput::setSuffix(const QString &suffix) +{ + m_spin->setSuffix(suffix); + + layout(true); +} + +QString KIntNumInput::suffix() const +{ + return m_spin->suffix(); +} + +void KIntNumInput::setPrefix(const QString &prefix) +{ + m_spin->setPrefix(prefix); + + layout(true); +} + +QString KIntNumInput::prefix() const +{ + return m_spin->prefix(); +} + +void KIntNumInput::setEditFocus(bool mark) +{ + m_spin->setEditFocus(mark); +} + +QSize KIntNumInput::minimumSizeHint() const +{ + constPolish(); + + int w; + int h; + + h = 2 + QMAX(m_sizeSpin.height(), m_sizeSlider.height()); + + // if in extra row, then count it here + if(m_label && (m_alignment & (AlignBottom|AlignTop))) + h += 4 + m_sizeLabel.height(); + else + // label is in the same row as the other widgets + h = QMAX(h, m_sizeLabel.height() + 2); + + w = m_slider ? m_slider->sizeHint().width() + 8 : 0; + w += m_colw1 + m_colw2; + + if(m_alignment & (AlignTop|AlignBottom)) + w = QMAX(w, m_sizeLabel.width() + 4); + + return QSize(w, h); +} + +void KIntNumInput::doLayout() +{ + m_sizeSpin = m_spin->sizeHint(); + m_colw2 = m_sizeSpin.width(); + + if (m_label) + m_label->setBuddy(m_spin); +} + +void KIntNumInput::resizeEvent(QResizeEvent* e) +{ + int w = m_colw1; + int h = 0; + + if(m_label && (m_alignment & AlignTop)) { + m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height()); + h += m_sizeLabel.height() + 4; + } + + if(m_label && (m_alignment & AlignVCenter)) + m_label->setGeometry(0, 0, w, m_sizeSpin.height()); + + m_spin->setGeometry(w, h, m_slider ? m_colw2 : QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height()); + w += m_colw2 + 8; + + if(m_slider) + m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height()); + + h += m_sizeSpin.height() + 2; + + if(m_label && (m_alignment & AlignBottom)) + m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height()); +} + +KIntNumInput::~KIntNumInput() +{ + delete d; +} + +void KIntNumInput::setValue(int val) +{ + m_spin->setValue(val); + // slider value is changed by spinValueChanged +} + +void KIntNumInput::setRelativeValue( double r ) { + if ( !d->referencePoint ) return; + ++d->blockRelative; + setValue( int( d->referencePoint * r + 0.5 ) ); + --d->blockRelative; +} + +double KIntNumInput::relativeValue() const { + if ( !d->referencePoint ) return 0; + return double( value() ) / double ( d->referencePoint ); +} + +int KIntNumInput::value() const +{ + return m_spin->value(); +} + +void KIntNumInput::setSpecialValueText(const QString& text) +{ + m_spin->setSpecialValueText(text); + layout(true); +} + +QString KIntNumInput::specialValueText() const +{ + return m_spin->specialValueText(); +} + +void KIntNumInput::setLabel(const QString & label, int a) +{ + KNumInput::setLabel(label, a); + + if(m_label) + m_label->setBuddy(m_spin); +} + +// ---------------------------------------------------------------------------- + +class KDoubleNumInput::KDoubleNumInputPrivate { +public: + KDoubleNumInputPrivate( double r ) + : spin( 0 ), + referencePoint( r ), + blockRelative ( 0 ) {} + KDoubleSpinBox * spin; + double referencePoint; + short blockRelative; +}; + +KDoubleNumInput::KDoubleNumInput(QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(0.0, 0.0, 9999.0, 0.01, 2); +} + +KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value, + double step, int precision, QWidget* parent, + const char *name) + : KNumInput(parent, name) +{ + init(value, lower, upper, step, precision); +} + +KDoubleNumInput::KDoubleNumInput(KNumInput *below, + double lower, double upper, double value, + double step, int precision, QWidget* parent, + const char *name) + : KNumInput(below, parent, name) +{ + init(value, lower, upper, step, precision); +} + +KDoubleNumInput::KDoubleNumInput(double value, QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 ); +} + +KDoubleNumInput::KDoubleNumInput(KNumInput* below, double value, QWidget* parent, + const char* name) + : KNumInput(below, parent, name) +{ + init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 ); +} + +KDoubleNumInput::~KDoubleNumInput() +{ + delete d; +} + +// ### remove when BIC changes are allowed again: + +bool KDoubleNumInput::eventFilter( QObject * o, QEvent * e ) { + return KNumInput::eventFilter( o, e ); +} + +void KDoubleNumInput::resetEditBox() { + +} + +// ### end stuff to remove when BIC changes are allowed again + + + +void KDoubleNumInput::init(double value, double lower, double upper, + double step, int precision ) +{ + // ### init no longer used members: + edit = 0; + m_range = true; + m_value = 0.0; + m_precision = 2; + // ### end + + d = new KDoubleNumInputPrivate( value ); + + d->spin = new KDoubleSpinBox( lower, upper, step, value, precision, + this, "KDoubleNumInput::d->spin" ); + setFocusProxy(d->spin); + connect( d->spin, SIGNAL(valueChanged(double)), + this, SIGNAL(valueChanged(double)) ); + connect( this, SIGNAL(valueChanged(double)), + this, SLOT(slotEmitRelativeValueChanged(double)) ); + + updateLegacyMembers(); + + layout(true); +} + +void KDoubleNumInput::updateLegacyMembers() { + // ### update legacy members that are either not private or for + // which an inlined getter exists: + m_lower = minValue(); + m_upper = maxValue(); + m_step = d->spin->lineStep(); + m_specialvalue = specialValueText(); +} + + +double KDoubleNumInput::mapSliderToSpin( int val ) const +{ + // map [slidemin,slidemax] to [spinmin,spinmax] + double spinmin = d->spin->minValue(); + double spinmax = d->spin->maxValue(); + double slidemin = m_slider->minValue(); // cast int to double to avoid + double slidemax = m_slider->maxValue(); // overflow in rel denominator + double rel = ( double(val) - slidemin ) / ( slidemax - slidemin ); + return spinmin + rel * ( spinmax - spinmin ); +} + +void KDoubleNumInput::sliderMoved(int val) +{ + d->spin->setValue( mapSliderToSpin( val ) ); +} + +void KDoubleNumInput::slotEmitRelativeValueChanged( double value ) +{ + if ( !d->referencePoint ) return; + emit relativeValueChanged( value / d->referencePoint ); +} + +QSize KDoubleNumInput::minimumSizeHint() const +{ + constPolish(); + + int w; + int h; + + h = 2 + QMAX(m_sizeEdit.height(), m_sizeSlider.height()); + + // if in extra row, then count it here + if(m_label && (m_alignment & (AlignBottom|AlignTop))) + h += 4 + m_sizeLabel.height(); + else + // label is in the same row as the other widgets + h = QMAX(h, m_sizeLabel.height() + 2); + + w = m_slider ? m_slider->sizeHint().width() + 8 : 0; + w += m_colw1 + m_colw2; + + if(m_alignment & (AlignTop|AlignBottom)) + w = QMAX(w, m_sizeLabel.width() + 4); + + return QSize(w, h); +} + +void KDoubleNumInput::resizeEvent(QResizeEvent* e) +{ + int w = m_colw1; + int h = 0; + + if(m_label && (m_alignment & AlignTop)) { + m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height()); + h += m_sizeLabel.height() + 4; + } + + if(m_label && (m_alignment & AlignVCenter)) + m_label->setGeometry(0, 0, w, m_sizeEdit.height()); + + d->spin->setGeometry(w, h, m_slider ? m_colw2 + : e->size().width() - w, m_sizeEdit.height()); + w += m_colw2 + 8; + + if(m_slider) + m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height()); + + h += m_sizeEdit.height() + 2; + + if(m_label && (m_alignment & AlignBottom)) + m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height()); +} + +void KDoubleNumInput::doLayout() +{ + m_sizeEdit = d->spin->sizeHint(); + m_colw2 = m_sizeEdit.width(); +} + +void KDoubleNumInput::setValue(double val) +{ + d->spin->setValue( val ); +} + +void KDoubleNumInput::setRelativeValue( double r ) +{ + if ( !d->referencePoint ) return; + ++d->blockRelative; + setValue( r * d->referencePoint ); + --d->blockRelative; +} + +void KDoubleNumInput::setReferencePoint( double ref ) +{ + // clip to valid range: + ref = kMin( maxValue(), kMax( minValue(), ref ) ); + d->referencePoint = ref; +} + +void KDoubleNumInput::setRange(double lower, double upper, double step, + bool slider) +{ + if( m_slider ) { + // don't update the slider to avoid an endless recursion + QSpinBox * spin = d->spin; + disconnect(spin, SIGNAL(valueChanged(int)), + m_slider, SLOT(setValue(int)) ); + } + d->spin->setRange( lower, upper, step, d->spin->precision() ); + + if(slider) { + // upcast to base type to get the min/maxValue in int form: + QSpinBox * spin = d->spin; + int slmax = spin->maxValue(); + int slmin = spin->minValue(); + int slvalue = spin->value(); + int slstep = spin->lineStep(); + if (m_slider) { + m_slider->setRange(slmin, slmax); + m_slider->setLineStep(slstep); + m_slider->setValue(slvalue); + } else { + m_slider = new QSlider(slmin, slmax, slstep, slvalue, + QSlider::Horizontal, this); + m_slider->setTickmarks(QSlider::Below); + // feedback line: when one moves, the other moves, too: + connect(m_slider, SIGNAL(valueChanged(int)), + SLOT(sliderMoved(int)) ); + } + connect(spin, SIGNAL(valueChanged(int)), + m_slider, SLOT(setValue(int)) ); + // calculate ( slmax - slmin ) / 10 without overflowing ints: + int major = calcDiffByTen( slmax, slmin ); + if ( !major ) major = slstep; // ### needed? + m_slider->setTickInterval(major); + } else { + delete m_slider; + m_slider = 0; + } + + setReferencePoint( referencePoint() ); + + layout(true); + updateLegacyMembers(); +} + +void KDoubleNumInput::setMinValue(double min) +{ + setRange(min, maxValue(), d->spin->lineStep(), m_slider); +} + +double KDoubleNumInput::minValue() const +{ + return d->spin->minValue(); +} + +void KDoubleNumInput::setMaxValue(double max) +{ + setRange(minValue(), max, d->spin->lineStep(), m_slider); +} + +double KDoubleNumInput::maxValue() const +{ + return d->spin->maxValue(); +} + +double KDoubleNumInput::value() const +{ + return d->spin->value(); +} + +double KDoubleNumInput::relativeValue() const +{ + if ( !d->referencePoint ) return 0; + return value() / d->referencePoint; +} + +double KDoubleNumInput::referencePoint() const +{ + return d->referencePoint; +} + +QString KDoubleNumInput::suffix() const +{ + return d->spin->suffix(); +} + +QString KDoubleNumInput::prefix() const +{ + return d->spin->prefix(); +} + +void KDoubleNumInput::setSuffix(const QString &suffix) +{ + d->spin->setSuffix( suffix ); + + layout(true); +} + +void KDoubleNumInput::setPrefix(const QString &prefix) +{ + d->spin->setPrefix( prefix ); + + layout(true); +} + +void KDoubleNumInput::setPrecision(int precision) +{ + d->spin->setPrecision( precision ); + + layout(true); +} + +int KDoubleNumInput::precision() const +{ + return d->spin->precision(); +} + +void KDoubleNumInput::setSpecialValueText(const QString& text) +{ + d->spin->setSpecialValueText( text ); + + layout(true); + updateLegacyMembers(); +} + +void KDoubleNumInput::setLabel(const QString & label, int a) +{ + KNumInput::setLabel(label, a); + + if(m_label) + m_label->setBuddy(d->spin); + +} + +// ---------------------------------------------------------------------------- + + +// We use a kind of fixed-point arithmetic to represent the range of +// doubles [mLower,mUpper] in steps of 10^(-mPrecision). Thus, the +// following relations hold: +// +// 1. factor = 10^mPrecision +// 2. basicStep = 1/factor = 10^(-mPrecision); +// 3. lowerInt = lower * factor; +// 4. upperInt = upper * factor; +// 5. lower = lowerInt * basicStep; +// 6. upper = upperInt * basicStep; +class KDoubleSpinBox::Private { +public: + Private( int precision=1 ) + : mPrecision( precision ), + mValidator( 0 ) + { + } + + int factor() const { + int f = 1; + for ( int i = 0 ; i < mPrecision ; ++i ) f *= 10; + return f; + } + + double basicStep() const { + return 1.0/double(factor()); + } + + int mapToInt( double value, bool * ok ) const { + assert( ok ); + const double f = factor(); + if ( value > double(INT_MAX) / f ) { + kdWarning() << "KDoubleSpinBox: can't represent value " << value + << "in terms of fixed-point numbers with precision " + << mPrecision << endl; + *ok = false; + return INT_MAX; + } else if ( value < double(INT_MIN) / f ) { + kdWarning() << "KDoubleSpinBox: can't represent value " << value + << "in terms of fixed-point numbers with precision " + << mPrecision << endl; + *ok = false; + return INT_MIN; + } else { + *ok = true; + return int( value * f + ( value < 0 ? -0.5 : 0.5 ) ); + } + } + + double mapToDouble( int value ) const { + return double(value) * basicStep(); + } + + int mPrecision; + KDoubleValidator * mValidator; +}; + +KDoubleSpinBox::KDoubleSpinBox( QWidget * parent, const char * name ) + : QSpinBox( parent, name ) +{ + editor()->setAlignment( Qt::AlignRight ); + d = new Private(); + updateValidator(); +} + +KDoubleSpinBox::KDoubleSpinBox( double lower, double upper, double step, + double value, int precision, + QWidget * parent, const char * name ) + : QSpinBox( parent, name ) +{ + editor()->setAlignment( Qt::AlignRight ); + d = new Private(); + setRange( lower, upper, step, precision ); + setValue( value ); + connect( this, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)) ); +} + +KDoubleSpinBox::~KDoubleSpinBox() { + delete d; d = 0; +} + +bool KDoubleSpinBox::acceptLocalizedNumbers() const { + if ( !d->mValidator ) return true; // we'll set one that does; + // can't do it now, since we're const + return d->mValidator->acceptLocalizedNumbers(); +} + +void KDoubleSpinBox::setAcceptLocalizedNumbers( bool accept ) { + if ( !d->mValidator ) updateValidator(); + d->mValidator->setAcceptLocalizedNumbers( accept ); +} + +void KDoubleSpinBox::setRange( double lower, double upper, double step, + int precision ) { + lower = kMin(upper, lower); + upper = kMax(upper, lower); + setPrecision( precision, true ); // disable bounds checking, since + setMinValue( lower ); // it's done in set{Min,Max}Value + setMaxValue( upper ); // anyway and we want lower, upper + setLineStep( step ); // and step to have the right precision +} + +int KDoubleSpinBox::precision() const { + return d->mPrecision; +} + +void KDoubleSpinBox::setPrecision( int precision ) { + setPrecision( precision, false ); +} + +void KDoubleSpinBox::setPrecision( int precision, bool force ) { + if ( precision < 1 ) return; + if ( !force ) { + int maxPrec = maxPrecision(); + if ( precision > maxPrec ) + precision = maxPrec; + } + d->mPrecision = precision; + updateValidator(); +} + +int KDoubleSpinBox::maxPrecision() const { + // INT_MAX must be > maxAbsValue * 10^precision + // ==> 10^precision < INT_MAX / maxAbsValue + // ==> precision < log10 ( INT_MAX / maxAbsValue ) + // ==> maxPrecision = floor( log10 ( INT_MAX / maxAbsValue ) ); + double maxAbsValue = kMax( fabs(minValue()), fabs(maxValue()) ); + if ( maxAbsValue == 0 ) return 6; // return arbitrary value to avoid dbz... + + return int( floor( log10( double(INT_MAX) / maxAbsValue ) ) ); +} + +double KDoubleSpinBox::value() const { + return d->mapToDouble( base::value() ); +} + +void KDoubleSpinBox::setValue( double value ) { + if ( value == this->value() ) return; + if ( value < minValue() ) + base::setValue( base::minValue() ); + else if ( value > maxValue() ) + base::setValue( base::maxValue() ); + else { + bool ok = false; + base::setValue( d->mapToInt( value, &ok ) ); + assert( ok ); + } +} + +double KDoubleSpinBox::minValue() const { + return d->mapToDouble( base::minValue() ); +} + +void KDoubleSpinBox::setMinValue( double value ) { + bool ok = false; + int min = d->mapToInt( value, &ok ); + if ( !ok ) return; + base::setMinValue( min ); + updateValidator(); +} + + +double KDoubleSpinBox::maxValue() const { + return d->mapToDouble( base::maxValue() ); +} + +void KDoubleSpinBox::setMaxValue( double value ) { + bool ok = false; + int max = d->mapToInt( value, &ok ); + if ( !ok ) return; + base::setMaxValue( max ); + updateValidator(); +} + +double KDoubleSpinBox::lineStep() const { + return d->mapToDouble( base::lineStep() ); +} + +void KDoubleSpinBox::setLineStep( double step ) { + bool ok = false; + if ( step > maxValue() - minValue() ) + base::setLineStep( 1 ); + else + base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) ); +} + +QString KDoubleSpinBox::mapValueToText( int value ) { + if ( acceptLocalizedNumbers() ) + return KGlobal::locale() + ->formatNumber( d->mapToDouble( value ), d->mPrecision ); + else + return QString().setNum( d->mapToDouble( value ), 'f', d->mPrecision ); +} + +int KDoubleSpinBox::mapTextToValue( bool * ok ) { + double value; + if ( acceptLocalizedNumbers() ) + value = KGlobal::locale()->readNumber( cleanText(), ok ); + else + value = cleanText().toDouble( ok ); + if ( !*ok ) return 0; + if ( value > maxValue() ) + value = maxValue(); + else if ( value < minValue() ) + value = minValue(); + return d->mapToInt( value, ok ); +} + +void KDoubleSpinBox::setValidator( const QValidator * ) { + // silently discard the new validator. We don't want another one ;-) +} + +void KDoubleSpinBox::slotValueChanged( int value ) { + emit valueChanged( d->mapToDouble( value ) ); +} + +void KDoubleSpinBox::updateValidator() { + if ( !d->mValidator ) { + d->mValidator = new KDoubleValidator( minValue(), maxValue(), precision(), + this, "d->mValidator" ); + base::setValidator( d->mValidator ); + } else + d->mValidator->setRange( minValue(), maxValue(), precision() ); +} + +void KNumInput::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KIntNumInput::virtual_hook( int id, void* data ) +{ KNumInput::virtual_hook( id, data ); } + +void KDoubleNumInput::virtual_hook( int id, void* data ) +{ KNumInput::virtual_hook( id, data ); } + +void KIntSpinBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDoubleSpinBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "knuminput.moc" diff --git a/microkde/kdeui/knuminput.h b/microkde/kdeui/knuminput.h new file mode 100644 index 0000000..123fefa --- a/dev/null +++ b/microkde/kdeui/knuminput.h @@ -0,0 +1,948 @@ +/* + * knuminput.h + * + * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca> + * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org> + * Copyright (c) 2002 Marc Mutz <mutz@kde.org> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef K_NUMINPUT_H +#define K_NUMINPUT_H + +#include <qwidget.h> +#include <qspinbox.h> + +class QLabel; +class QSlider; +class QLineEdit; +class QLayout; +class QValidator; + +class KIntSpinBox; + +/* ------------------------------------------------------------------------ */ + +/** + * You need to inherit from this class if you want to implement K*NumInput + * for a different variable type + * + */ +class KNumInput : public QWidget +{ + Q_OBJECT + Q_PROPERTY( QString label READ label WRITE setLabel ) +public: + /** + * Default constructor + * + */ + KNumInput(QWidget* parent=0, const char* name=0); + + /** + * @param below A pointer to another KNumInput. + * + */ + KNumInput(KNumInput* below, QWidget* parent=0, const char* name=0); + ~KNumInput(); + + /** + * Sets the text and alignment of the main description label. + * + * @param label The text of the label. + * Use QString::null to remove an existing one. + * + * @param a one of @p AlignLeft, @p AlignHCenter, YAlignRight and + * @p AlignTop, @p AlignVCenter, @p AlignBottom. + * default is @p AlignLeft | @p AlignTop. + * + * The vertical alignment flags have special meaning with this + * widget: + * + * @li @p AlignTop The label is placed above the edit/slider + * @li @p AlignVCenter The label is placed left beside the edit + * @li @p AlignBottom The label is placed below the edit/slider + * + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + + /** + * @return the text of the label. + */ + QString label() const; + + /** + * @return if the num input has a slider. + * @since 3.1 + */ + bool showSlider() const { return m_slider; } + + /** + * Sets the spacing of tickmarks for the slider. + * + * @param minor Minor tickmark separation. + * @param major Major tickmark separation. + */ + void setSteps(int minor, int major); + + /** + * Specifies that this widget may stretch horizontally, but is + * fixed vertically (like @ref QSpinBox itself). + */ + QSizePolicy sizePolicy() const; + + /** + * Returns a size which fits the contents of the control. + * + * @return the preferred size necessary to show the control + */ + virtual QSize sizeHint() const; + +protected: + /** + * Call this function whenever you change something in the geometry + * of your KNumInput child. + * + */ + void layout(bool deep); + + /** + * You need to overwrite this method and implement your layout + * calculations there. + * + * See KIntNumInput::doLayout and KDoubleNumInput::doLayout implementation + * for details. + * + */ + virtual void doLayout() = 0; + + KNumInput* m_prev, *m_next; + int m_colw1, m_colw2; + + QLabel* m_label; + QSlider* m_slider; + QSize m_sizeSlider, m_sizeLabel; + + int m_alignment; + +private: + void init(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KNumInputPrivate; + KNumInputPrivate *d; +}; + +/* ------------------------------------------------------------------------ */ + +/** + * KIntNumInput combines a @ref QSpinBox and optionally a @ref QSlider + * with a label to make an easy to use control for setting some integer + * parameter. This is especially nice for configuration dialogs, + * which can have many such combinated controls. + * + * The slider is created only when the user specifies a range + * for the control using the setRange function with the slider + * parameter set to "true". + * + * A special feature of KIntNumInput, designed specifically for + * the situation when there are several KIntNumInputs in a column, + * is that you can specify what portion of the control is taken by the + * QSpinBox (the remaining portion is used by the slider). This makes + * it very simple to have all the sliders in a column be the same size. + * + * It uses @ref KIntValidator validator class. KIntNumInput enforces the + * value to be in the given range, and can display it in any base + * between 2 and 36. + * + * @short An input widget for integer numbers, consisting of a spinbox and a slider. + * @version $Id$ + */ + +class KIntNumInput : public KNumInput +{ + Q_OBJECT + Q_PROPERTY( int value READ value WRITE setValue ) + Q_PROPERTY( int minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( int referencePoint READ referencePoint WRITE setReferencePoint ) + Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) + Q_PROPERTY( QString prefix READ prefix WRITE setPrefix ) + Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText ) + +public: + /** + * Constructs an input control for integer values + * with base 10 and initial value 0. + */ + KIntNumInput(QWidget *parent=0, const char *name=0); + /** + * Constructor + * It constructs a QSpinBox that allows the input of integer numbers + * in the range of -INT_MAX to +INT_MAX. To set a descriptive label, + * use setLabel(). To enforce the value being in a range and optionally to + * attach a slider to it, use setRange(). + * + * @param value initial value for the control + * @param base numeric base used for display + * @param parent parent QWidget + * @param name internal name for this widget + */ + KIntNumInput(int value, QWidget* parent=0, int base = 10, const char *name=0); + + /** + * Constructor + * + * the difference to the one above is the "below" parameter. It tells + * this instance that it is visually put below some other KNumInput widget. + * Note that these two KNumInput's need not to have the same parent widget + * or be in the same layout group. + * The effect is that it'll adjust it's layout in correspondence + * with the layout of the other KNumInput's (you can build an arbitary long + * chain). + * + * @param below append KIntNumInput to the KNumInput chain + * @param value initial value for the control + * @param base numeric base used for display + * @param parent parent QWidget + * @param name internal name for this widget + */ + KIntNumInput(KNumInput* below, int value, QWidget* parent=0, int base = 10, const char *name=0); + + /** + * Destructor + * + * + */ + virtual ~KIntNumInput(); + + /** + * @return the current value. + */ + int value() const; + + /** + * @return the curent value in units of the @ref referencePoint. + * @since 3.1 + */ + double relativeValue() const; + + /** + * @return the current reference point + * @since 3.1 + */ + int referencePoint() const; + + /** + * @return the suffix displayed behind the value. + * @see #setSuffix() + */ + QString suffix() const; + /** + * @return the prefix displayed in front of the value. + * @see #setPrefix() + */ + QString prefix() const; + /** + * @return the string displayed for a special value. + * @see #setSpecialValueText() + */ + QString specialValueText() const; + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(int min, int max, int step=1, bool slider=true); + /** + * Sets the minimum value. + */ + void setMinValue(int min); + /** + * @return the minimum value. + */ + int minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(int max); + /** + * @return the maximum value. + */ + int maxValue() const; + + /** + * Sets the special value text. If set, the SpinBox will display + * this text instead of the numeric value whenever the current + * value is equal to minVal(). Typically this is used for indicating + * that the choice has a special (default) meaning. + */ + void setSpecialValueText(const QString& text); + + /** + * @reimplemented + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + + /** + * This method returns the minimum size necessary to display the + * control. The minimum size is enough to show all the labels + * in the current font (font change may invalidate the return value). + * + * @return the minimum size necessary to show the control + */ + virtual QSize minimumSizeHint() const; + +public slots: + /** + * Sets the value of the control. + */ + void setValue(int); + + /** + * Sets the value in units of the @ref referencePoint + * @since 3.1 + */ + void setRelativeValue(double); + + /** + * Sets the reference point for @ref relativeValue. + * @since 3.1 + */ + void setReferencePoint(int); + + /** + * Sets the suffix to @p suffix. + * Use QString::null to disable this feature. + * Formatting has to be provided (e.g. a space separator between the + * prepended @p value and the suffix's text has to be provided + * as the first character in the suffix). + * + * @see QSpinBox::setSuffix(), #setPrefix() + */ + void setSuffix(const QString &suffix); + + /** + * Sets the prefix to @p prefix. + * Use QString::null to disable this feature. + * Formatting has to be provided (see above). + * + * @see QSpinBox::setPrefix(), #setSuffix() + */ + void setPrefix(const QString &prefix); + + /** + * sets focus to the edit widget and marks all text in if mark == true + * + */ + void setEditFocus( bool mark = true ); + +signals: + /** + * Emitted every time the value changes (by calling @ref setValue() or + * by user interaction). + */ + void valueChanged(int); + + /** + * Emitted whenever @ref #valueChanged is. Contains the change + * relative to the @ref referencePoint. + * @since 3.1 + */ + void relativeValueChanged(double); + +private slots: + void spinValueChanged(int); + void slotEmitRelativeValueChanged(int); + +protected: + /** + * @reimplemented + */ + virtual void doLayout(); + /** + * @reimplemented + */ + void resizeEvent ( QResizeEvent * ); + + KIntSpinBox* m_spin; + QSize m_sizeSpin; + +private: + void init(int value, int _base); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KIntNumInputPrivate; + KIntNumInputPrivate *d; +}; + + +/* ------------------------------------------------------------------------ */ + +class KDoubleLine; + +/** + * KDoubleNumInput combines a @ref QSpinBox and optionally a @ref QSlider + * with a label to make an easy to use control for setting some float + * parameter. This is especially nice for configuration dialogs, + * which can have many such combinated controls. + * + * The slider is created only when the user specifies a range + * for the control using the setRange function with the slider + * parameter set to "true". + * + * A special feature of KDoubleNumInput, designed specifically for + * the situation when there are several instances in a column, + * is that you can specify what portion of the control is taken by the + * QSpinBox (the remaining portion is used by the slider). This makes + * it very simple to have all the sliders in a column be the same size. + * + * It uses the @ref KDoubleValidator validator class. KDoubleNumInput + * enforces the value to be in the given range, but see the class + * documentation of @ref KDoubleSpinBox for the tricky + * interrelationship of precision and values. All of what is said + * there applies here, too. + * + * @see KIntNumInput, KDoubleSpinBox + * @short An input control for real numbers, consisting of a spinbox and a slider. + */ + +class KDoubleNumInput : public KNumInput +{ + Q_OBJECT + Q_PROPERTY( double value READ value WRITE setValue ) + Q_PROPERTY( double minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( double maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) + Q_PROPERTY( QString prefix READ prefix WRITE setPrefix ) + Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText ) + Q_PROPERTY( int precision READ precision WRITE setPrecision ) + +public: + /** + * Constructs an input control for double values + * with initial value 0.00. + */ + KDoubleNumInput(QWidget *parent=0, const char *name=0); + + /** + * @deprecated (value is rounded to a multiple of 1/100) + * Constructor + * + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + */ + KDoubleNumInput(double value, QWidget *parent=0, const char *name=0); + + /** + * Constructor + * + * @param lower lower boundary value + * @param upper upper boundary value + * @param value initial value for the control + * @param step step size to use for up/down arrow clicks + * @param precision number of digits after the decimal point + * @param parent parent QWidget + * @param name internal name for this widget + * @since 3.1 + */ + KDoubleNumInput(double lower, double upper, double value, double step=0.01, + int precision=2, QWidget *parent=0, const char *name=0); + + /** + * destructor + */ + virtual ~KDoubleNumInput(); + + /** + * @deprecated (rounds @p value to a mulitple of 1/100) + * Constructor + * + * puts it below other KNumInput + * + * @param below + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + **/ + KDoubleNumInput(KNumInput* below, double value, QWidget* parent=0, const char* name=0); + + /** + * Constructor + * + * puts it below other KNumInput + * + * @param lower lower boundary value + * @param upper upper boundary value + * @param value initial value for the control + * @param step step size to use for up/down arrow clicks + * @param precision number of digits after the decimal point + * @param parent parent QWidget + * @param name internal name for this widget + * @since 3.1 + */ + KDoubleNumInput(KNumInput* below, + double lower, double upper, double value, double step=0.02, + int precision=2, QWidget *parent=0, const char *name=0); + + /** + * @return the current value. + */ + double value() const; + + /** + * @return the suffix. + * @see #setSuffix() + */ + QString suffix() const; + + /** + * @return the prefix. + * @see #setPrefix() + */ + QString prefix() const; + + /** + * @return the precision. + * @see #setPrecision() + */ + int precision() const; + + /** + * @return the string displayed for a special value. + * @see #setSpecialValueText() + */ + QString specialValueText() const { return m_specialvalue; } + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(double min, double max, double step=1, bool slider=true); + /** + * Sets the minimum value. + */ + void setMinValue(double min); + /** + * @return the minimum value. + */ + double minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(double max); + /** + * @return the maximum value. + */ + double maxValue() const; + + /** + * Specifies the number of digits to use. + */ + void setPrecision(int precision); + + /** + * @return the reference point for @ref #relativeValue calculation + * @since 3.1 + */ + double referencePoint() const; + + /** + * @return the current value in units of @ref #referencePoint. + * @since 3.1 + */ + double relativeValue() const; + + /** + * Sets the special value text. If set, the spin box will display + * this text instead of the numeric value whenever the current + * value is equal to @ref #minVal(). Typically this is used for indicating + * that the choice has a special (default) meaning. + */ + void setSpecialValueText(const QString& text); + + /** + * @reimplemented + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + /** + * @reimplemented + */ + virtual QSize minimumSizeHint() const; + /** + * @reimplemented + */ + virtual bool eventFilter(QObject*, QEvent*); + +public slots: + /** + * Sets the value of the control. + */ + void setValue(double); + + /** + * Sets the value in units of @ref #referencePoint. + * @since 3.1 + */ + void setRelativeValue(double); + + /** + * Sets the reference Point to @p ref. It @p ref == 0, emitting of + * @ref #relativeValueChanged is blocked and @ref #relativeValue + * just returns 0. + * @since 3.1 + */ + void setReferencePoint(double ref); + + /** + * Sets the suffix to be displayed to @p suffix. Use QString::null to disable + * this feature. Note that the suffix is attached to the value without any + * spacing. So if you prefer to display a space separator, set suffix + * to something like " cm". + * @see #setSuffix() + */ + void setSuffix(const QString &suffix); + + /** + * Sets the prefix to be displayed to @p prefix. Use QString::null to disable + * this feature. Note that the prefix is attached to the value without any + * spacing. + * @see #setPrefix() + */ + void setPrefix(const QString &prefix); + +signals: + /** + * Emitted every time the value changes (by calling @ref setValue() or + * by user interaction). + */ + void valueChanged(double); + /** + * This is an overloaded member function, provided for + * convenience. It essentially behaves like the above function. + * + * Contains the value in units of @ref #referencePoint. + * @since 3.1 + */ + void relativeValueChanged(double); + +private slots: + void sliderMoved(int); + void slotEmitRelativeValueChanged(double); + +protected: + + /** + * @reimplemented + */ + virtual void doLayout(); + /** + * @reimplemented + */ + void resizeEvent ( QResizeEvent * ); + virtual void resetEditBox(); + + // ### no longer used, remove when BIC allowed + KDoubleLine* edit; + + bool m_range; + double m_lower, m_upper, m_step; + // ### end no longer used + + QSize m_sizeEdit; + + friend class KDoubleLine; +private: + void init(double value, double lower, double upper, + double step, int precision); + double mapSliderToSpin(int) const; + void updateLegacyMembers(); + // ### no longer used, remove when BIC allowed: + QString m_specialvalue, m_prefix, m_suffix; + double m_value; + short m_precision; + // ### end remove when BIC allowed + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDoubleNumInputPrivate; + KDoubleNumInputPrivate *d; +}; + + +/* ------------------------------------------------------------------------ */ + +/** + * A @ref QSpinBox with support for arbitrary base numbers + * (e.g. hexadecimal). + * + * The class provides an easy interface to use other + * numeric systems than the decimal. + * + * @short A @ref QSpinBox with support for arbitrary base numbers. + */ +class KIntSpinBox : public QSpinBox +{ + Q_OBJECT + Q_PROPERTY( int base READ base WRITE setBase ) + +public: + + /** + * Constructor. + * + * Constructs a widget with an integer inputline with a little scrollbar + * and a slider, with minimal value 0, maximal value 99, step 1, base 10 + * and initial value 0. + */ + KIntSpinBox( QWidget *parent=0, const char *name=0); + + /** + * Constructor. + * + * Constructs a widget with an integer inputline with a little scrollbar + * and a slider. + * + * @param lower The lowest valid value. + * @param upper The greatest valid value. + * @param step The step size of the scrollbar. + * @param value The actual value. + * @param base The base of the used number system. + * @param parent The parent of the widget. + * @param name The Name of the widget. + */ + KIntSpinBox(int lower, int upper, int step, int value, int base = 10, + QWidget* parent = 0, const char* name = 0); + + /** + * Destructor. + */ + virtual ~KIntSpinBox(); + + /** + * Sets the base in which the numbers in the spin box are represented. + */ + void setBase(int base); + /** + * @return the base in which numbers in the spin box are represented. + */ + int base() const; + /** + * sets focus and optionally marks all text + * + */ + void setEditFocus(bool mark); + +protected: + + /** + * Overloaded the method in QSpinBox + * to make use of the base given in the constructor. + */ + virtual QString mapValueToText(int); + + /** + * Overloaded the method in QSpinBox + * to make use of the base given in the constructor. + */ + virtual int mapTextToValue(bool*); + +private: + int val_base; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KIntSpinBoxPrivate; + KIntSpinBoxPrivate *d; +}; + + +/* --------------------------------------------------------------------------- */ + +/** + This class provides a spin box for fractional numbers. + + @sect Parameters + + There are a number of interdependent parameters whose relation to + each other you need to understand in order to make successful use + of the spin box. + + @li precision: The number of decimals after the decimal point. + @li maxValue/minValue: upper and lower bound of the valid range + @li lineStep: the size of the step that is taken when the user hits + the up or down buttons + + Since we work with fixed-point numbers internally, the maximum + precision is a function of the valid range and vice versa. More + precisely, the following relations hold: + <pre> + max( abs(minValue()), abs(maxValue() ) <= INT_MAX/10^precision + maxPrecision = floor( log10( INT_MAX/max(abs(minValue()),abs(maxValue())) ) ) + </pre> + + Since the value, bounds and step are rounded to the current + precision, you may experience that the order of setting above + parameters matters. E.g. the following are @em not equivalent (try + it!): + + <pre> + // sets precision, + // then min/max value (rounded to precison and clipped to obtainable range if needed) + // then value and lineStep + KDoubleSpinBox * spin = new KDoubleSpinBox( 0, 9.999, 0.001, 4.321, 3, this ); + + // sets minValue to 0; maxValue to 10.00(!); value to 4.32(!) and only then + // increases the precision - too late, since e.g. value has already been rounded... + KDpubleSpinBox * spin = new KDoubleSpinBox( this ); + spin->setMinValue( 0 ); + spin->setMaxValue( 9.999 ); + spin->setValue( 4.321 ); + spin->setPrecision( 3 ); + </pre> + + @short A spin box for fractional numbers. + @author Marc Mutz <mutz@kde.org> + @version $Id$ + @since 3.1 +**/ + +class KDoubleSpinBox : public QSpinBox { + Q_OBJECT + Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers ) + Q_OVERRIDE( double maxValue READ maxValue WRITE setMaxValue ) + Q_OVERRIDE( double minValue READ minValue WRITE setMinValue ) + Q_OVERRIDE( double lineStep READ lineStep WRITE setLineStep ) + Q_OVERRIDE( double value READ value WRITE setValue ) + Q_PROPERTY( int precision READ precision WRITE setPrecision ) + +public: + /** Constructs a @ref KDoubleSpinBox with parent @p parent and + default values for range and value (whatever @ref QRangeControl + uses) and precision (2). */ + KDoubleSpinBox( QWidget * parent=0, const char * name=0 ); + /** Constructs a @ref KDoubleSpinBox with parent @p parent, range + [@p lower,@p upper], @ref lineStep @p step, @ref precision @p + precision and initial value @p value. */ + KDoubleSpinBox( double lower, double upper, double step, double value, + int precision=2, QWidget * parent=0, const char * name=0 ); + + virtual ~KDoubleSpinBox(); + + /** @return whether the spinbox uses localized numbers */ + bool acceptLocalizedNumbers() const; + /** Sets whether to use and accept localized numbers as returned by + @ref KLocale::formatNumber() */ + virtual void setAcceptLocalizedNumbers( bool accept ); + + /** Sets a new range for the spin box values. Note that @p lower, @p + upper and @p step are rounded to @p precision decimal points + first. */ + void setRange( double lower, double upper, double step=0.01, int precision=2 ); + + /** @return the current number of decimal points displayed. */ + int precision() const; + /** Equivalent to @ref setPrecsion( @p precison, @p false ); Needed + since Qt's moc doesn't ignore trailing parameters with default + args when searching for a property setter method. */ + void setPrecision( int precision ); + /** Sets the number of decimal points to use. Note that there is a + tradeoff between the precision used and the available range of + values. See the class docs for more. + @param precision the new number of decimal points to use + + @param force disables checking of bound violations that can + arise if you increase the precision so much that the + minimum and maximum values can't be represented + anymore. Disabling is useful if you don't want to keep + the current min and max values anyway. This is what + e.g. @ref setRange() does. + **/ + virtual void setPrecision( int precision, bool force ); + + /** @return the current value */ + double value() const; + /** @return the current lower bound */ + double minValue() const; + /** Sets the lower bound of the range to @p value, subject to the + contraints that @p value is first rounded to the current + precision and then clipped to the maximum representable + interval. + @see maxValue, minValue, setMaxValue, setRange + */ + void setMinValue( double value ); + /** @return the current upper bound */ + double maxValue() const; + /** Sets the upper bound of the range to @p value, subject to the + contraints that @p value is first rounded to the current + precision and then clipped to the maximum representable + interval. + @see minValue, maxValue, setMinValue, setRange + */ + void setMaxValue( double value ); + + /** @return the current step size */ + double lineStep() const; + /** Sets the step size for clicking the up/down buttons to @p step, + subject to the constraints that @p step is first rounded to the + current precision and then clipped to the meaningful interval + [1, @p maxValue - @p minValue]. */ + void setLineStep( double step ); + + /** Overridden to ignore any setValidator() calls. */ + void setValidator( const QValidator * ); + +signals: + /** Emitted whenever @ref QSpinBox::valueChanged( int ) is emitted. */ + void valueChanged( double value ); + +public slots: + /** Sets the current value to @p value, cubject to the constraints + that @p value is frist rounded to the current precision and then + clipped to the interval [@p minvalue(),@p maxValue()]. */ + virtual void setValue( double value ); + +protected: + virtual QString mapValueToText(int); + virtual int mapTextToValue(bool*); + +protected slots: + void slotValueChanged( int value ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + typedef QSpinBox base; + void updateValidator(); + int maxPrecision() const; + + class Private; + Private * d; +}; + +#endif // K_NUMINPUT_H diff --git a/microkde/kdeui/knumvalidator.cpp b/microkde/kdeui/knumvalidator.cpp new file mode 100644 index 0000000..78a8471 --- a/dev/null +++ b/microkde/kdeui/knumvalidator.cpp @@ -0,0 +1,372 @@ +/********************************************************************** +** +** $Id$ +** +** KIntValidator, KFloatValidator: +** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com> +** KDoubleValidator: +** Copyright (c) 2002 Marc Mutz <mutz@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 as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** 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; if not, write to the Free +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +*****************************************************************************/ + +#include <qwidget.h> +#include <qstring.h> + +#include "knumvalidator.h" +#include <klocale.h> +#include <kglobal.h> +#include <kdebug.h> + +/////////////////////////////////////////////////////////////// +// Implementation of KIntValidator +// + +KIntValidator::KIntValidator ( QWidget * parent, int base, const char * name ) + : QValidator(parent, name) +{ + _base = base; + if (_base < 2) _base = 2; + if (_base > 36) _base = 36; + + _min = _max = 0; +} + +KIntValidator::KIntValidator ( int bottom, int top, QWidget * parent, int base, const char * name ) + : QValidator(parent, name) +{ + _base = base; + if (_base > 36) _base = 36; + + _min = bottom; + _max = top; +} + +KIntValidator::~KIntValidator () +{} + +QValidator::State KIntValidator::validate ( QString &str, int & ) const +{ + bool ok; + int val = 0; + QString newStr; + + newStr = str.stripWhiteSpace(); + if (_base > 10) + newStr = newStr.upper(); + + if (newStr == QString::fromLatin1("-")) // a special case + if ((_min || _max) && _min >= 0) + ok = false; + else + return QValidator::Acceptable; + else if (newStr.length()) + val = newStr.toInt(&ok, _base); + else { + val = 0; + ok = true; + } + + if (! ok) + return QValidator::Invalid; + + if ((! _min && ! _max) || (val >= _min && val <= _max)) + return QValidator::Acceptable; + + if (_max && _min >= 0 && val < 0) + return QValidator::Invalid; + + return QValidator::Valid; +} + +void KIntValidator::fixup ( QString &str ) const +{ + int dummy; + int val; + QValidator::State state; + + state = validate(str, dummy); + + if (state == QValidator::Invalid || state == QValidator::Acceptable) + return; + + if (! _min && ! _max) + return; + + val = str.toInt(0, _base); + + if (val < _min) val = _min; + if (val > _max) val = _max; + + str.setNum(val, _base); +} + +void KIntValidator::setRange ( int bottom, int top ) +{ + _min = bottom; + _max = top; + + if (_max < _min) + _max = _min; +} + +void KIntValidator::setBase ( int base ) +{ + _base = base; + if (_base < 2) _base = 2; +} + +int KIntValidator::bottom () const +{ + return _min; +} + +int KIntValidator::top () const +{ + return _max; +} + +int KIntValidator::base () const +{ + return _base; +} + + +/////////////////////////////////////////////////////////////// +// Implementation of KFloatValidator +// + +class KFloatValidatorPrivate +{ +public: + KFloatValidatorPrivate() + { + } + ~KFloatValidatorPrivate() + { + } + bool acceptLocalizedNumbers; +}; + + +KFloatValidator::KFloatValidator ( QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers=false; + _min = _max = 0; +} + +KFloatValidator::KFloatValidator ( double bottom, double top, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers=false; + _min = bottom; + _max = top; +} + +KFloatValidator::KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers = localeAware; + _min = bottom; + _max = top; +} + +KFloatValidator::~KFloatValidator () +{ + delete d; +} + +void KFloatValidator::setAcceptLocalizedNumbers(bool _b) +{ + d->acceptLocalizedNumbers=_b; +} + +bool KFloatValidator::acceptLocalizedNumbers() const +{ + return d->acceptLocalizedNumbers; +} + +QValidator::State KFloatValidator::validate ( QString &str, int & ) const +{ + bool ok; + double val = 0; + QString newStr; + newStr = str.stripWhiteSpace(); + + if (newStr == QString::fromLatin1("-")) // a special case + if ((_min || _max) && _min >= 0) + ok = false; + else + return QValidator::Acceptable; + else if (newStr == QString::fromLatin1(".") || (d->acceptLocalizedNumbers && newStr==KGlobal::locale()->decimalSymbol())) // another special case + return QValidator::Acceptable; + else if (newStr.length()) + { + val = newStr.toDouble(&ok); + if(!ok && d->acceptLocalizedNumbers) + val= KGlobal::locale()->readNumber(newStr,&ok); + } + else { + val = 0; + ok = true; + } + + if (! ok) + return QValidator::Invalid; + + if (( !_min && !_max) || (val >= _min && val <= _max)) + return QValidator::Acceptable; + + if (_max && _min >= 0 && val < 0) + return QValidator::Invalid; + + if ( (_min || _max) && (val < _min || val > _max)) + return QValidator::Invalid; + + return QValidator::Valid; +} + +void KFloatValidator::fixup ( QString &str ) const +{ + int dummy; + double val; + QValidator::State state; + + state = validate(str, dummy); + + if (state == QValidator::Invalid || state == QValidator::Acceptable) + return; + + if (! _min && ! _max) + return; + + val = str.toDouble(); + + if (val < _min) val = _min; + if (val > _max) val = _max; + + str.setNum(val); +} + +void KFloatValidator::setRange ( double bottom, double top ) +{ + _min = bottom; + _max = top; + + if (_max < _min) + _max = _min; +} + +double KFloatValidator::bottom () const +{ + return _min; +} + +double KFloatValidator::top () const +{ + return _max; +} + + + + +/////////////////////////////////////////////////////////////// +// Implementation of KDoubleValidator +// + +class KDoubleValidator::Private { +public: + Private( bool accept=true ) : acceptLocalizedNumbers( accept ) {} + + bool acceptLocalizedNumbers; +}; + +KDoubleValidator::KDoubleValidator( QObject * parent, const char * name ) + : QDoubleValidator( (QWidget*)parent, name ), d( 0 ) +{ + d = new Private(); +} + +KDoubleValidator::KDoubleValidator( double bottom, double top, int decimals, + QObject * parent, const char * name ) + : QDoubleValidator( bottom, top, decimals, (QWidget*)parent, name ), d( 0 ) +{ + d = new Private(); +} + +KDoubleValidator::~KDoubleValidator() +{ + delete d; +} + +bool KDoubleValidator::acceptLocalizedNumbers() const { + return d->acceptLocalizedNumbers; +} + +void KDoubleValidator::setAcceptLocalizedNumbers( bool accept ) { + d->acceptLocalizedNumbers = accept; +} + +QValidator::State KDoubleValidator::validate( QString & input, int & p ) const { + QString s = input; + if ( acceptLocalizedNumbers() ) { + KLocale * l = KGlobal::locale(); + // ok, we have to re-format the number to have: + // 1. decimalSymbol == '.' + // 2. negativeSign == '-' + // 3. positiveSign == <empty> + // 4. thousandsSeparator() == <empty> (we don't check that there + // are exactly three decimals between each separator): + QString d = l->decimalSymbol(), + n = l->negativeSign(), + p = l->positiveSign(), + t = l->thousandsSeparator(); + // first, delete p's and t's: + if ( !p.isEmpty() ) + for ( int idx = s.find( p ) ; idx >= 0 ; idx = s.find( p, idx ) ) + s.remove( idx, p.length() ); + + + if ( !t.isEmpty() ) + for ( int idx = s.find( t ) ; idx >= 0 ; idx = s.find( t, idx ) ) + s.remove( idx, t.length() ); + + // then, replace the d's and n's + if ( ( !n.isEmpty() && n.find('.') != -1 ) || + ( !d.isEmpty() && d.find('-') != -1 ) ) { + // make sure we don't replace something twice: + kdWarning() << "KDoubleValidator: decimal symbol contains '-' or " + "negative sign contains '.' -> improve algorithm" << endl; + return Invalid; + } + + if ( !d.isEmpty() && d != "." ) + for ( int idx = s.find( d ) ; idx >= 0 ; idx = s.find( d, idx + 1 ) ) + s.replace( idx, d.length(), "."); + + if ( !n.isEmpty() && n != "-" ) + for ( int idx = s.find( n ) ; idx >= 0 ; idx = s.find( n, idx + 1 ) ) + s.replace( idx, n.length(), "-" ); + } + + return base::validate( s, p ); +} + +//US #include "knumvalidator.moc" diff --git a/microkde/kdeui/knumvalidator.h b/microkde/kdeui/knumvalidator.h new file mode 100644 index 0000000..2f0a937 --- a/dev/null +++ b/microkde/kdeui/knumvalidator.h @@ -0,0 +1,209 @@ +/********************************************************************** +** +** $Id$ +** +** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com> +** Copyright (C) 2002 Marc Mutz <mutz@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 as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** 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; if not, write to the Free +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +*****************************************************************************/ + +#ifndef __KNUMVALIDATOR_H +#define __KNUMVALIDATOR_H + +#include <qvalidator.h> + +class QWidget; +class QString; + +/** + * @ref QValidator for integers. + + This can be used by @ref QLineEdit or subclass to provide validated + text entry. Can be provided with a base value (default is 10), to allow + the proper entry of hexadecimal, octal, or any other base numeric data. + + @author Glen Parker <glenebob@nwlink.com> + @version 0.0.1 +*/ +class KIntValidator : public QValidator { + + public: + /** + Constuctor. Also sets the base value. + */ + KIntValidator ( QWidget * parent, int base = 10, const char * name = 0 ); + /** + * Constructor. Also sets the minimum, maximum, and numeric base values. + */ + KIntValidator ( int bottom, int top, QWidget * parent, int base = 10, const char * name = 0 ); + /** + * Destructs the validator. + */ + virtual ~KIntValidator (); + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + /** + * Sets the minimum and maximum values allowed. + */ + virtual void setRange ( int bottom, int top ); + /** + * Sets the numeric base value. + */ + virtual void setBase ( int base ); + /** + * Returns the current minimum value allowed. + */ + virtual int bottom () const; + /** + * Returns the current maximum value allowed. + */ + virtual int top () const; + /** + * Returns the current numeric base. + */ + virtual int base () const; + + private: + int _base; + int _min; + int _max; + +}; + +class KFloatValidatorPrivate; + +/** + @obsolete Use @ref KDoubleValidator + + @ref QValidator for floating point entry. + Extends the QValidator class to properly validate double numeric data. + This can be used by @ref QLineEdit or subclass to provide validated + text entry. + + @author Glen Parker <glenebob@nwlink.com> + @version 0.0.1 +*/ +class KFloatValidator : public QValidator { + + public: + /** + * Constructor. + */ + KFloatValidator ( QWidget * parent, const char * name = 0 ); + /** + * Constructor. Also sets the minimum and maximum values. + */ + KFloatValidator ( double bottom, double top, QWidget * parent, const char * name = 0 ); + /** + * Constructor. Sets the validator to be locale aware if @p localeAware is true. + */ + KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name = 0 ); + /** + * Destructs the validator. + */ + virtual ~KFloatValidator (); + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + /** + * Sets the minimum and maximum value allowed. + */ + virtual void setRange ( double bottom, double top ); + /** + * Returns the current minimum value allowed. + */ + virtual double bottom () const; + /** + * Returns the current maximum value allowed. + */ + virtual double top () const; + /** + * Sets the validator to be locale aware if @p is true. In this case, the + * character KLocale::decimalSymbol() from the global locale is recognized + * as decimal separator. + */ + void setAcceptLocalizedNumbers(bool b); + /** + * Returns true if the validator is locale aware. + * @see setAcceptLocalizedNumbers(). + */ + bool acceptLocalizedNumbers() const; + + private: + double _min; + double _max; + + KFloatValidatorPrivate *d; +}; + +/** + KDoubleValidator extends @ref QDoubleValidator to be + locale-aware. That means that - subject to not being disabled - + @ref KLocale::decimalPoint(), @ref KLocale::thousandsSeparator() + and @ref KLocale::positiveSign() and @ref KLocale::negativeSign() + are respected. + + @short A locale-aware @ref QDoubleValidator + @author Marc Mutz <mutz@kde.org> + @version $Id$ + @see KIntValidator + @since 3.1 +**/ + +class KDoubleValidator : public QDoubleValidator { + Q_OBJECT + Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers ) +public: + /** Constuct a locale-aware KDoubleValidator with default range + (whatever @ref QDoubleValidator uses for that) and parent @p + parent */ + KDoubleValidator( QObject * parent, const char * name=0 ); + /** Constuct a locale-aware KDoubleValidator for range [@p bottom,@p + top] and a precision of @p decimals decimals after the decimal + point. */ + KDoubleValidator( double bottom, double top, int decimals, + QObject * parent, const char * name=0 ); + /** Destructs the validator. + */ + virtual ~KDoubleValidator(); + + /** Overloaded for internal reasons. The API is not affected. */ + virtual QValidator::State validate( QString & input, int & pos ) const; + + /** @return whether localized numbers are accepted (default: true) */ + bool acceptLocalizedNumbers() const; + /** Sets whether to accept localized numbers (default: true) */ + void setAcceptLocalizedNumbers( bool accept ); + +private: + typedef QDoubleValidator base; + class Private; + Private * d; +}; + +#endif diff --git a/microkde/kdeui/kseparator.cpp b/microkde/kdeui/kseparator.cpp new file mode 100644 index 0000000..d028420 --- a/dev/null +++ b/microkde/kdeui/kseparator.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <qstyle.h> + +#include <kdebug.h> +//US #include <kapplication.h> + +//US #include "kseparator.moc" + +#include "kseparator.h" + +KSeparator::KSeparator(QWidget* parent, const char* name, WFlags f) + : QFrame(parent, name, f) +{ + setLineWidth(1); + setMidLineWidth(0); + setOrientation( HLine ); +} + + + +KSeparator::KSeparator(int orientation, QWidget* parent, const char* name, WFlags f) + : QFrame(parent, name, f) +{ + setLineWidth(1); + setMidLineWidth(0); + setOrientation( orientation ); +} + + + +void KSeparator::setOrientation(int orientation) +{ + switch(orientation) + { + case Vertical: + case VLine: + setFrameStyle( QFrame::VLine | QFrame::Sunken ); + setMinimumSize(2, 0); + break; + + default: + kdWarning() << "KSeparator::setOrientation(): invalid orientation, using default orientation HLine" << endl; + + case Horizontal: + case HLine: + setFrameStyle( QFrame::HLine | QFrame::Sunken ); + setMinimumSize(0, 2); + break; + } +} + + + +int KSeparator::orientation() const +{ + if ( frameStyle() & VLine ) + return VLine; + + if ( frameStyle() & HLine ) + return HLine; + + return 0; +} + +void KSeparator::drawFrame(QPainter *p) +{ + QPoint p1, p2; + QRect r = frameRect(); + const QColorGroup & g = colorGroup(); + + if ( frameStyle() & HLine ) { + p1 = QPoint( r.x(), r.height()/2 ); + p2 = QPoint( r.x()+r.width(), p1.y() ); + } + else { + p1 = QPoint( r.x()+r.width()/2, 0 ); + p2 = QPoint( p1.x(), r.height() ); + } + +/*US + QStyleOption opt( lineWidth(), midLineWidth() ); + style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g, + QStyle::Style_Sunken, opt ); +*/ +//LRstyle().drawSeparator( p, p1.x(), p1.y(), p2.x(), p2.y(), g, true, lineWidth(), midLineWidth()); + +} + + +QSize KSeparator::sizeHint() const +{ + if ( frameStyle() & VLine ) + return QSize(2, 0); + + if ( frameStyle() & HLine ) + return QSize(0, 2); + + return QSize(-1, -1); +} + +void KSeparator::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdeui/kseparator.h b/microkde/kdeui/kseparator.h new file mode 100644 index 0000000..6d2712a --- a/dev/null +++ b/microkde/kdeui/kseparator.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __KSEPARATOR_H__ +#define __KSEPARATOR_H__ + +#include <qframe.h> + +/** + * Standard horizontal or vertical separator. + * + * @author Michael Roth <mroth@wirlweb.de> + * @version $Id$ +*/ +class KSeparator : public QFrame +{ + Q_OBJECT + Q_PROPERTY( int orientation READ orientation WRITE setOrientation ) + public: + /** + * Constructor. + **/ + KSeparator(QWidget* parent=0, const char* name=0, WFlags f=0); + /** + * Constructor. + * + * @param orientation Set the orientation of the separator. + * Possible values are HLine or Horizontal and VLine or Vertical. + **/ + KSeparator(int orientation, QWidget* parent=0, const char* name=0, + WFlags f=0); + + /** + * Returns the orientation of the separator. + * + * Possible values are VLine and HLine. + **/ + int orientation() const; + + /** + * Set the orientation of the separator to @p orient + * + * Possible values are VLine and HLine. + */ + void setOrientation(int orient); + + /** + * The recommended height (width) for a horizontal (vertical) separator. + **/ + virtual QSize sizeHint() const; + +protected: + virtual void drawFrame( QPainter * ); +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KSeparatorPrivate* d; +}; + + +#endif // __KSEPARATOR_H__ diff --git a/microkde/kdeui/ksqueezedtextlabel.cpp b/microkde/kdeui/ksqueezedtextlabel.cpp new file mode 100644 index 0000000..37fa29a --- a/dev/null +++ b/microkde/kdeui/ksqueezedtextlabel.cpp @@ -0,0 +1,107 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de> + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "ksqueezedtextlabel.h" +#include <qtooltip.h> + +KSqueezedTextLabel::KSqueezedTextLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); + fullText = text; + squeezeTextToLabel(); +} + +KSqueezedTextLabel::KSqueezedTextLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); +} + +void KSqueezedTextLabel::resizeEvent( QResizeEvent * ) { + squeezeTextToLabel(); +} + +QSize KSqueezedTextLabel::minimumSizeHint() const +{ + QSize sh = QLabel::minimumSizeHint(); + sh.setWidth(-1); + return sh; +} + +void KSqueezedTextLabel::setText( const QString &text ) { + fullText = text; + squeezeTextToLabel(); +} + +void KSqueezedTextLabel::squeezeTextToLabel() { + QFontMetrics fm(fontMetrics()); + int labelWidth = size().width(); + int textWidth = fm.width(fullText); + if (textWidth > labelWidth) { + // start with the dots only + QString squeezedText = "..."; + int squeezedWidth = fm.width(squeezedText); + + // estimate how many letters we can add to the dots on both sides + int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2; + if (labelWidth < squeezedWidth) letters=1; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < labelWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < labelWidth); + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + } else if (squeezedWidth > labelWidth) { + // we estimated too long + // remove letters while text > label + do { + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (letters && squeezedWidth > labelWidth); + } + + if (letters < 5) { + // too few letters added -> we give up squeezing + QLabel::setText(fullText); + } else { + QLabel::setText(squeezedText); + } + +//US QToolTip::remove( this ); +//US QToolTip::add( this, fullText ); + + } else { + QLabel::setText(fullText); + +//US QToolTip::remove( this ); +//US QToolTip::hide(); + + }; +} + +void KSqueezedTextLabel::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ksqueezedtextlabel.moc" diff --git a/microkde/kdeui/ksqueezedtextlabel.h b/microkde/kdeui/ksqueezedtextlabel.h new file mode 100644 index 0000000..1634adc --- a/dev/null +++ b/microkde/kdeui/ksqueezedtextlabel.h @@ -0,0 +1,76 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de> + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KSQUEEZEDTEXTLABEL_H +#define KSQUEEZEDTEXTLABEL_H + +#include <qlabel.h> + +/** + * A label class that squeezes its text into the label + * + * If the text is too long to fit into the label it is divided into + * remaining left and right parts which are separated by three dots. + * + * Example: + * http://www.kde.org/documentation/index.html could be squeezed to + * http://www.kde...ion/index.html + + * @short A replacement for QLabel that squeezes its text + * @author Ronny Standtke <Ronny.Standtke@gmx.de> + * @version $Id$ + * + */ + +/* + * @ref QLabel + */ +class KSqueezedTextLabel : public QLabel { + Q_OBJECT + +public: + /** + * Default constructor. + */ + KSqueezedTextLabel( QWidget *parent, const char *name = 0 ); + KSqueezedTextLabel( const QString &text, QWidget *parent, const char *name = 0 ); + + virtual QSize minimumSizeHint() const; + +public slots: + void setText( const QString & ); + +protected: + /** + * used when widget is resized + */ + void resizeEvent( QResizeEvent * ); + /** + * does the dirty work + */ + void squeezeTextToLabel(); + QString fullText; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KSqueezedTextLabelPrivate; + KSqueezedTextLabelPrivate *d; +}; + +#endif // KSQUEEZEDTEXTLABEL_H diff --git a/microkde/kdeui/kstdaction.cpp b/microkde/kdeui/kstdaction.cpp new file mode 100644 index 0000000..cfd7b54 --- a/dev/null +++ b/microkde/kdeui/kstdaction.cpp @@ -0,0 +1,362 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000 Kurt Granroth <granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kstdaction.h" + +#include <qtoolbutton.h> +#include <qwhatsthis.h> + +//US #include <kaboutdata.h> +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +//US #include <kstdaccel.h> +//US #include <kmainwindow.h> + +namespace KStdAction +{ + +struct KStdActionInfo +{ + StdAction id; +/*US KStdAccel::StdAccel idAccel;*/ + const char* psName; + const char* psLabel; + const char* psWhatsThis; + const char* psIconName; +}; + +const KStdActionInfo g_rgActionInfo[] = +{ + { New, /*USKStdAccel::New,*/ "file_new", I18N_NOOP("&New"), 0, "filenew" }, + { Open, /*USKStdAccel::Open,*/ "file_open", I18N_NOOP("&Open..."), 0, "fileopen" }, + { OpenRecent, /*USKStdAccel::AccelNone,*/ "file_open_recent", I18N_NOOP("Open &Recent"), 0, 0 }, + { Save, /*USKStdAccel::Save,*/ "file_save", I18N_NOOP("&Save"), 0, "filesave" }, + { SaveAs, /*USKStdAccel::AccelNone,*/ "file_save_as", I18N_NOOP("Save &As..."), 0, "filesaveas" }, + { Revert, /*USKStdAccel::AccelNone,*/ "file_revert", I18N_NOOP("Re&vert"), 0, "revert" }, + { Close, /*USKStdAccel::Close,*/ "file_close", I18N_NOOP("&Close"), 0, "fileclose" }, + { Print, /*USKStdAccel::Print,*/ "file_print", I18N_NOOP("&Print..."), 0, "fileprint" }, + { PrintPreview, /*USKStdAccel::AccelNone,*/ "file_print_preview", I18N_NOOP("Print Previe&w..."), 0, "filequickprint" }, + { Mail, /*USKStdAccel::AccelNone,*/ "file_mail", I18N_NOOP("&Mail..."), 0, "mail_send" }, + { Quit, /*USKStdAccel::Quit,*/ "file_quit", I18N_NOOP("&Exit"), 0, "exit" }, + + { Undo, /*USKStdAccel::Undo,*/ "edit_undo", I18N_NOOP("&Undo"), 0, "undo" }, + { Redo, /*USKStdAccel::Redo,*/ "edit_redo", I18N_NOOP("Re&do"), 0, "redo" }, + { Cut, /*USKStdAccel::Cut,*/ "edit_cut", I18N_NOOP("Cu&t"), 0, "editcut" }, + { Copy, /*USKStdAccel::Copy,*/ "edit_copy", I18N_NOOP("&Copy"), 0, "editcopy" }, + { Paste, /*USKStdAccel::Paste,*/ "edit_paste", I18N_NOOP("&Paste"), 0, "editpaste" }, + { SelectAll, /*USKStdAccel::SelectAll,*/ "edit_select_all", I18N_NOOP("Select &All"), 0, 0 }, + { Deselect, /*USKStdAccel::Deselect,*/ "edit_deselect", I18N_NOOP("Dese&lect"), 0, 0 }, + { Find, /*USKStdAccel::Find,*/ "edit_find", I18N_NOOP("&Find..."), 0, "find" }, + { FindNext, /*USKStdAccel::FindNext,*/ "edit_find_next", I18N_NOOP("Find &Next"), 0, "next" }, + // FIXME: rename edit_find_last to edit_find_prev for KDE 4 + { FindPrev, /*USKStdAccel::FindPrev,*/ "edit_find_last", I18N_NOOP("Find Pre&vious"), 0, "previous" }, + { Replace, /*USKStdAccel::Replace,*/ "edit_replace", I18N_NOOP("&Replace..."), 0, 0 }, + + { ActualSize, /*USKStdAccel::AccelNone,*/ "view_actual_size", I18N_NOOP("&Actual Size"), 0, 0 }, + { FitToPage, /*USKStdAccel::AccelNone,*/ "view_fit_to_page", I18N_NOOP("&Fit to Page"), 0, 0 }, + { FitToWidth, /*USKStdAccel::AccelNone,*/ "view_fit_to_width", I18N_NOOP("Fit to Page &Width"), 0, 0 }, + { FitToHeight, /*USKStdAccel::AccelNone,*/ "view_fit_to_height", I18N_NOOP("Fit to Page &Height"), 0, 0 }, + { ZoomIn, /*USKStdAccel::ZoomIn,*/ "view_zoom_in", I18N_NOOP("Zoom &In"), 0, "viewmag+" }, + { ZoomOut, /*USKStdAccel::ZoomOut,*/ "view_zoom_out", I18N_NOOP("Zoom &Out"), 0, "viewmag-" }, + { Zoom, /*USKStdAccel::AccelNone,*/ "view_zoom", I18N_NOOP("&Zoom..."), 0, "viewmag" }, + { Redisplay, /*USKStdAccel::AccelNone,*/ "view_redisplay", I18N_NOOP("&Redisplay"), 0, "reload" }, + + { Up, /*USKStdAccel::Up,*/ "go_up", I18N_NOOP("&Up"), 0, "up" }, + // The following three have special i18n() needs for sLabel + { Back, /*USKStdAccel::Back,*/ "go_back", 0, 0, "back" }, + { Forward, /*USKStdAccel::Forward,*/ "go_forward", 0, 0, "forward" }, + { Home, /*USKStdAccel::Home,*/ "go_home", 0, 0, "gohome" }, + { Prior, /*USKStdAccel::Prior,*/ "go_previous", I18N_NOOP("&Previous Page"), 0, "previous" }, + { Next, /*USKStdAccel::Next,*/ "go_next", I18N_NOOP("&Next Page"), 0, "next" }, + { Goto, /*USKStdAccel::AccelNone,*/ "go_goto", I18N_NOOP("&Go To..."), 0, 0 }, + { GotoPage, /*USKStdAccel::AccelNone,*/ "go_goto_page", I18N_NOOP("&Go to Page..."), 0, "goto" }, + { GotoLine, /*USKStdAccel::GotoLine,*/ "go_goto_line", I18N_NOOP("&Go to Line..."), 0, 0 }, + { FirstPage, /*USKStdAccel::Home,*/ "go_first", I18N_NOOP("&First Page"), 0, "top" }, + { LastPage, /*USKStdAccel::End,*/ "go_last", I18N_NOOP("&Last Page"), 0, "bottom" }, + + { AddBookmark, /*USKStdAccel::AddBookmark,*/ "bookmark_add", I18N_NOOP("&Add Bookmark"), 0, "bookmark_add" }, + { EditBookmarks, /*USKStdAccel::AccelNone,*/ "bookmark_edit", I18N_NOOP("&Edit Bookmarks"), 0, "bookmark" }, + + { Spelling, /*USKStdAccel::AccelNone,*/ "tools_spelling", I18N_NOOP("&Spelling..."), 0, "spellcheck" }, + + { ShowMenubar, /*USKStdAccel::ShowMenubar,*/ "options_show_menubar", I18N_NOOP("Show &Menubar"), 0, "showmenu" }, + { ShowToolbar, /*USKStdAccel::AccelNone,*/ "options_show_toolbar", I18N_NOOP("Show &Toolbar"), 0, 0 }, + { ShowStatusbar, /*USKStdAccel::AccelNone,*/ "options_show_statusbar", I18N_NOOP("Show St&atusbar"), 0, 0 }, + { SaveOptions, /*USKStdAccel::AccelNone,*/ "options_save_options", I18N_NOOP("&Save Settings"), 0, 0 }, + { KeyBindings, /*USKStdAccel::AccelNone,*/ "options_configure_keybinding", I18N_NOOP("Configure S&hortcuts..."), 0,"configure_shortcuts" }, + { Preferences, /*USKStdAccel::AccelNone,*/ "options_configure", I18N_NOOP("&Configure %1..."), 0, "configure" }, + { ConfigureToolbars, /*USKStdAccel::AccelNone,*/ "options_configure_toolbars", I18N_NOOP("Configure Tool&bars..."), 0,"configure_toolbars" }, + { ConfigureNotifications, /*USKStdAccel::AccelNone,*/ "options_configure_notifications", I18N_NOOP("Configure &Notifications..."), 0, "knotify" }, + + { Help, /*USKStdAccel::Help,*/ "help", 0, 0, "help" }, + { HelpContents, /*USKStdAccel::AccelNone,*/ "help_contents", I18N_NOOP("%1 &Handbook"), 0, "contents" }, + { WhatsThis, /*USKStdAccel::WhatsThis,*/ "help_whats_this", I18N_NOOP("What's &This?"), 0, "contexthelp" }, + { TipofDay, /*USKStdAccel::AccelNone,*/ "help_show_tip", I18N_NOOP("Tip of the &Day"), 0, "idea" }, + { ReportBug, /*USKStdAccel::AccelNone,*/ "help_report_bug", I18N_NOOP("&Report Bug..."), 0, 0 }, + { AboutApp, /*USKStdAccel::AccelNone,*/ "help_about_app", I18N_NOOP("&About %1"), 0, 0 }, + { AboutKDE, /*USKStdAccel::AccelNone,*/ "help_about_kde", I18N_NOOP("About &KDE"), 0,"about_kde" }, + { ActionNone, /*USKStdAccel::AccelNone,*/ 0, 0, 0, 0 } +}; + +static const KStdActionInfo* infoPtr( StdAction id ) +{ + for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) { + if( g_rgActionInfo[i].id == id ) + return &g_rgActionInfo[i]; + } + return 0; +} + +QStringList stdNames() +{ + QStringList result; + + for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) + if (g_rgActionInfo[i].psLabel) + result.append(i18n(g_rgActionInfo[i].psLabel)); + return result; +} + +KAction* create( StdAction id, const char *name, const QObject *recvr, const char *slot, KActionCollection* parent ) +{ + KAction* pAction = 0; + const KStdActionInfo* pInfo = infoPtr( id ); + kdDebug(125) << "KStdAction::create( " << id << "=" << (pInfo ? pInfo->psName : (const char*)0) << ", " << parent << ", " << name << " )" << endl; // ellis + if( pInfo ) { + QString sLabel, iconName = pInfo->psIconName; + switch( id ) { + case Back: sLabel = i18n("go back", "&Back"); +//US if (QApplication::reverseLayout() ) +//US iconName = "forward"; + break; + + case Forward: sLabel = i18n("go forward", "&Forward"); +//US if (QApplication::reverseLayout() ) +//US iconName = "back"; + break; + + case Home: sLabel = i18n("beginning (of line)", "&Home"); break; + case Help: sLabel = i18n("show help", "&Help"); break; +//US case AboutApp: iconName = kapp->miniIconName(); + case Preferences: + case HelpContents: + { +//US const KAboutData *aboutData = KGlobal::instance()->aboutData(); +//US QString appName = (aboutData) ? aboutData->programName() : QString::fromLatin1(qApp->name()); + QString appName = QString::fromLatin1(KGlobal::getAppName()); + sLabel = i18n(pInfo->psLabel).arg(appName); + } + break; + default: sLabel = i18n(pInfo->psLabel); + } + +/*US if (QApplication::reverseLayout()){ + if (id == Prior) iconName = "next"; + if (id == Next ) iconName = "previous"; + } +*/ +//US KShortcut cut = KStdAccel::shortcut(pInfo->idAccel); + KShortcut cut; + switch( id ) { + case OpenRecent: + pAction = new KRecentFilesAction( sLabel, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + break; + case ShowMenubar: + case ShowToolbar: + case ShowStatusbar: + KToggleAction *ret; + ret = new KToggleAction( sLabel, pInfo->psIconName, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + ret->setChecked( true ); + pAction = ret; + break; + default: + pAction = new KAction( sLabel, iconName, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + break; + } + } + return pAction; +} + +const char* name( StdAction id ) +{ + const KStdActionInfo* pInfo = infoPtr( id ); + return (pInfo) ? pInfo->psName : 0; +} + +KAction *openNew( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( New, name, recvr, slot, parent ); } +KAction *open( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Open, name, recvr, slot, parent ); } +KRecentFilesAction *openRecent( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return (KRecentFilesAction*) KStdAction::create( OpenRecent, name, recvr, slot, parent ); } +KAction *save( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Save, name, recvr, slot, parent ); } +KAction *saveAs( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SaveAs, name, recvr, slot, parent ); } +KAction *revert( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Revert, name, recvr, slot, parent ); } +KAction *print( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Print, name, recvr, slot, parent ); } +KAction *printPreview( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( PrintPreview, name, recvr, slot, parent ); } +KAction *close( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Close, name, recvr, slot, parent ); } +KAction *mail( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Mail, name, recvr, slot, parent ); } +KAction *quit( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Quit, name, recvr, slot, parent ); } +KAction *undo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Undo, name, recvr, slot, parent ); } +KAction *redo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Redo, name, recvr, slot, parent ); } +KAction *cut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Cut, name, recvr, slot, parent ); } +KAction *copy( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Copy, name, recvr, slot, parent ); } +KAction *paste( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Paste, name, recvr, slot, parent ); } +KAction *selectAll( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SelectAll, name, recvr, slot, parent ); } +KAction *deselect( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Deselect, name, recvr, slot, parent ); } +KAction *find( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Find, name, recvr, slot, parent ); } +KAction *findNext( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FindNext, name, recvr, slot, parent ); } +KAction *findPrev( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FindPrev, name, recvr, slot, parent ); } +KAction *replace( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Replace, name, recvr, slot, parent ); } +KAction *actualSize( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ActualSize, name, recvr, slot, parent ); } +KAction *fitToPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToPage, name, recvr, slot, parent ); } +KAction *fitToWidth( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToWidth, name, recvr, slot, parent ); } +KAction *fitToHeight( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToHeight, name, recvr, slot, parent ); } +KAction *zoomIn( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ZoomIn, name, recvr, slot, parent ); } +KAction *zoomOut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ZoomOut, name, recvr, slot, parent ); } +KAction *zoom( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Zoom, name, recvr, slot, parent ); } +KAction *redisplay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Redisplay, name, recvr, slot, parent ); } +KAction *up( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Up, name, recvr, slot, parent ); } +KAction *back( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Back, name, recvr, slot, parent ); } +KAction *forward( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Forward, name, recvr, slot, parent ); } +KAction *home( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Home, name, recvr, slot, parent ); } +KAction *prior( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Prior, name, recvr, slot, parent ); } +KAction *next( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Next, name, recvr, slot, parent ); } +KAction *goTo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Goto, name, recvr, slot, parent ); } +KAction *gotoPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( GotoPage, name, recvr, slot, parent ); } +KAction *gotoLine( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( GotoLine, name, recvr, slot, parent ); } +KAction *firstPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FirstPage, name, recvr, slot, parent ); } +KAction *lastPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( LastPage, name, recvr, slot, parent ); } +KAction *addBookmark( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AddBookmark, name, recvr, slot, parent ); } +KAction *editBookmarks( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( EditBookmarks, name, recvr, slot, parent ); } +KAction *spelling( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Spelling, name, recvr, slot, parent ); } + +KToggleAction *showMenubar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show &Menubar"), "showmenu", /*US KStdAccel::shortcut(KStdAccel::ShowMenubar)*/0, recvr, slot, + parent, _name ? _name : name(ShowMenubar)); + ret->setChecked(true); + return ret; +} + +KToggleAction *showToolbar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show &Toolbar"), 0, recvr, slot, parent, + _name ? _name : name(ShowToolbar)); + ret->setChecked(true); + return ret; + +} + +KToggleToolBarAction *showToolbar( const char* toolBarName, KActionCollection* parent, const char *_name ) +{ + KToggleToolBarAction *ret; + ret = new KToggleToolBarAction(toolBarName, i18n("Show &Toolbar"), parent, + _name ? _name : name(ShowToolbar)); + return ret; +} + +KToggleAction *showStatusbar( const QObject *recvr, const char *slot, + KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show St&atusbar"), 0, recvr, slot, parent, + _name ? _name : name(ShowStatusbar)); + ret->setChecked(true); + return ret; +} + +KAction *saveOptions( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SaveOptions, name, recvr, slot, parent ); } +KAction *keyBindings( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( KeyBindings, name, recvr, slot, parent ); } +KAction *preferences( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Preferences, name, recvr, slot, parent ); } +KAction *configureToolbars( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ConfigureToolbars, name, recvr, slot, parent ); } +KAction *configureNotifications( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ConfigureNotifications, name, recvr, slot, parent ); } +KAction *help( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Help, name, recvr, slot, parent ); } +KAction *helpContents( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( HelpContents, name, recvr, slot, parent ); } +KAction *whatsThis( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( WhatsThis, name, recvr, slot, parent ); } +KAction *tipOfDay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( TipofDay, name, recvr, slot, parent ); } +KAction *reportBug( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ReportBug, name, recvr, slot, parent ); } +KAction *aboutApp( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AboutApp, name, recvr, slot, parent ); } +KAction *aboutKDE( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AboutKDE, name, recvr, slot, parent ); } + +} diff --git a/microkde/kdeui/kstdaction.h b/microkde/kdeui/kstdaction.h new file mode 100644 index 0000000..bc712b3 --- a/dev/null +++ b/microkde/kdeui/kstdaction.h @@ -0,0 +1,568 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org> + Copyright (C) 2001,2002 Ellis Whitehead <ellis@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSTDACTION_H +#define KSTDACTION_H + +class QObject; +class KAction; +class KActionCollection; +class KRecentFilesAction; +class KToggleAction; +class KToggleToolBarAction; + +#include <qstringlist.h> + +/** + * Convenience methods to access all standard KDE actions. + * + * These actions should be used instead of hardcoding menubar and + * toolbar items. Using these actions helps your application easily + * conform to the KDE UI Style Guide + * @see http://developer.kde.org/documentation/standards/kde/style/basics/index.html . + * + * All of the documentation for @ref KAction holds for KStdAction + * also. When in doubt on how things work, check the @ref KAction + * documention first. + * + * @sect Simple Example: + * + * In general, using standard actions should be a drop in replacement + * for regular actions. For example, if you previously had: + * + * <PRE> + * KAction *newAct = new KAction(i18n("&New"), QIconSet(BarIcon("filenew")), + * KStdAccel::key(KStdAccel::New), this, + * SLOT(fileNew()), actionCollection()); + * </PRE> + * + * You could drop that and replace it with: + * + * <PRE> + * KAction *newAct = KStdAction::openNew(this, SLOT(fileNew()), + * actionCollection()); + * </PRE> + * + * @sect Non-standard Usages + * + * It is possible to use the standard actions in various + * non-recommended ways. Say, for instance, you wanted to have a + * standard action (with the associated correct text and icon and + * accelerator, etc) but you didn't want it to go in the standard + * place (this is not recommended, by the way). One way to do this is + * to simply not use the XML UI framework and plug it into wherever + * you want. If you do want to use the XML UI framework (good!), then + * it is still possible. + * + * Basically, the XML building code matches names in the XML code with + * the internal names of the actions. You can find out the internal + * names of each of the standard actions by using the @ref stdName + * action like so: @ref KStdAction::stdName(KStdAction::Cut) would return + * 'edit_cut'. The XML building code will match 'edit_cut' to the + * attribute in the global XML file and place your action there. + * + * However, you can change the internal name. In this example, just + * do something like: + * + * <PRE> + * (void)KStdAction::cut(this, SLOT(editCut()), actionCollection(), "my_cut"); + * </PRE> + * + * Now, in your local XML resource file (e.g., yourappui.rc), simply + * put 'my_cut' where you want it to go. + * + * Another non-standard usage concerns getting a pointer to an + * existing action if, say, you want to enable or disable the action. + * You could do it the recommended way and just grab a pointer when + * you instantiate it as in the the 'openNew' example above... or you + * could do it the hard way: + * + * <pre> + * KAction *cut = actionCollection()->action(KStdAction::stdName(KStdAction::Cut)); + * </pre> + * + * Another non-standard usage concerns instantiating the action in the + * first place. Usually, you would use the member functions as + * shown above (e.g., KStdAction::cut(this, SLOT, parent)). You + * may, however, do this using the enums provided. This author can't + * think of a reason why you would want to, but, hey, if you do, + * here's how: + * + * <pre> + * (void)KStdAction::action(KStdAction::New, this, SLOT(fileNew()), actionCollection()); + * (void)KStdAction::action(KStdAction::Cut, this, SLOT(editCut()), actionCollection()); + * </pre> + * + * @author Kurt Granroth <granroth@kde.org> + */ +namespace KStdAction +{ + /** + * The standard menubar and toolbar actions. + */ + enum StdAction { + ActionNone, + + // File Menu + New, Open, OpenRecent, Save, SaveAs, Revert, Close, + Print, PrintPreview, Mail, Quit, + + // Edit Menu + Undo, Redo, Cut, Copy, Paste, SelectAll, Deselect, Find, FindNext, FindPrev, + Replace, + + // View Menu + ActualSize, FitToPage, FitToWidth, FitToHeight, ZoomIn, ZoomOut, + Zoom, Redisplay, + + // Go Menu + Up, Back, Forward, Home, Prior, Next, Goto, GotoPage, GotoLine, + FirstPage, LastPage, + + // Bookmarks Menu + AddBookmark, EditBookmarks, + + // Tools Menu + Spelling, + + // Settings Menu + ShowMenubar, ShowToolbar, ShowStatusbar, SaveOptions, KeyBindings, + Preferences, ConfigureToolbars, + + // Help Menu + Help, HelpContents, WhatsThis, ReportBug, AboutApp, AboutKDE, + TipofDay, ///< @since 3.1 + + // Another settings menu item + ConfigureNotifications + }; + + /** + * Creates an action corresponding to the + * @ref KStdAction::StdAction enum. + */ + KAction* create( StdAction id, const char *name, + const QObject *recvr, const char *slot, + KActionCollection* parent ); + + inline KAction* create( StdAction id, + const QObject *recvr, const char *slot, + KActionCollection* parent ) + { return KStdAction::create( id, 0, recvr, slot, parent ); } + + /** + * @obsolete. Creates an action corresponding to the + * @ref KStdAction::StdAction enum. + */ + inline KAction *action(StdAction act_enum, + const QObject *recvr, const char *slot, + KActionCollection *parent, const char *name = 0L ) + { return KStdAction::create( act_enum, name, recvr, slot, parent ); } + + /** + * This will return the internal name of a given standard action. + */ + const char* name( StdAction id ); + + /// @obsolete. Use #name + inline const char* stdName(StdAction act_enum) { return name( act_enum ); } + + /** + * Returns a list of all standard names. Used by @ref KAccelManager + * to give those heigher weight. + * @since 3.1 + */ + QStringList stdNames(); + + /** + * Create a new document or window. + */ + KAction *openNew(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Open an existing file. + */ + KAction *open(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Open a recently used document. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + */ + KRecentFilesAction *openRecent(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Save the current document. + */ + KAction *save(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Save the current document under a different name. + */ + KAction *saveAs(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Revert the current document to the last saved version + * (essentially will undo all changes). + */ + KAction *revert(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Close the current document. + */ + KAction *close(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Print the current document. + */ + KAction *print(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Show a print preview of the current document. + */ + KAction *printPreview(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Mail this document. + */ + KAction *mail(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Quit the program. + */ + KAction *quit(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Undo the last operation. + */ + KAction *undo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Redo the last operation. + */ + KAction *redo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Cut selected area and store it in the clipboard. + */ + KAction *cut(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Copy the selected area into the clipboard. + */ + KAction *copy(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Paste the contents of clipboard at the current mouse or cursor + * position. + */ + KAction *paste(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Select all elements in the current document. + */ + KAction *selectAll(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Deselect any selected elements in the current document. + */ + KAction *deselect(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Initiate a 'find' request in the current document. + */ + KAction *find(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find the next instance of a stored 'find'. + */ + KAction *findNext(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find a previous instance of a stored 'find'. + */ + KAction *findPrev(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find and replace matches. + */ + KAction *replace(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * View the document at its actual size. + */ + KAction *actualSize(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the size of the current window. + */ + KAction *fitToPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the width of the current window. + */ + KAction *fitToWidth(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the height of the current window. + */ + KAction *fitToHeight(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Zoom in. + */ + KAction *zoomIn(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Zoom out. + */ + KAction *zoomOut(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Popup a zoom dialog. + */ + KAction *zoom(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Redisplay or redraw the document. + */ + KAction *redisplay(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move up (web style menu). + */ + KAction *up(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move back (web style menu). + */ + KAction *back(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move forward (web style menu). + */ + KAction *forward(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to the "Home" position or document. + */ + KAction *home(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Scroll up one page. + */ + KAction *prior(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Scroll down one page. + */ + KAction *next(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to somewhere in general. + */ + KAction *goTo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + + /** + * Go to a specific page (dialog). + */ + KAction *gotoPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to a specific line (dialog). + */ + KAction *gotoLine(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Jump to the first page. + */ + KAction *firstPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Jump to the last page. + */ + KAction *lastPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Add the current page to the bookmarks tree. + */ + KAction *addBookmark(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Edit the application bookmarks. + */ + KAction *editBookmarks(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Pop up the spell checker. + */ + KAction *spelling(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + + /** + * Show/Hide the menubar. + */ + KToggleAction *showMenubar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * @obsolete. toolbar actions are created automatically now in the + * Settings menu. Don't use this anymore. + * See: @ref KMainWindow::createStandardStatusBarAction() + * Show/Hide the primary toolbar. + * @since 3.1 + */ + KToggleAction *showToolbar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + /** + * @obsolete. toolbar actions are created automatically now in the + * Settings menu. Don't use this anymore. + * See: @ref KMainWindow::setStandardToolBarMenuEnabled(bool); + * Show/Hide the primary toolbar. + */ + KToggleToolBarAction *showToolbar(const char* toolBarName, + KActionCollection* parent, const char *name = 0 ); + + /** + * Show/Hide the statusbar. + */ + KToggleAction *showStatusbar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the save options dialog. + */ + KAction *saveOptions(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the configure key bindings dialog. + */ + KAction *keyBindings(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the preferences/options dialog. + */ + KAction *preferences(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * The Customize Toolbar dialog. + */ + KAction *configureToolbars(const QObject *recvr, + const char *slot, + KActionCollection* parent, + const char *name = 0 ); + + /** + * The Configure Notifications dialo + * @since 3.1 + */ + KAction *configureNotifications(const QObject *recvr, + const char *slot, + KActionCollection *parent, + const char *name = 0); + + /** + * Display the help. + */ + KAction *help(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the help contents. + */ + KAction *helpContents(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Trigger the What's This cursor. + */ + KAction *whatsThis(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display "Tip of the Day" + * @since 3.1 + */ + KAction *tipOfDay(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Open up the Report Bug dialog. + */ + KAction *reportBug(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the application's About box. + */ + KAction *aboutApp(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the About KDE dialog. + */ + KAction *aboutKDE(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); +} + +#endif // KSTDACTION_H diff --git a/microkde/kdeui/ktoolbar.cpp b/microkde/kdeui/ktoolbar.cpp new file mode 100644 index 0000000..92cb8d2 --- a/dev/null +++ b/microkde/kdeui/ktoolbar.cpp @@ -0,0 +1,2260 @@ +/* This file is part of the KDE libraries + Copyright + (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 1999 Kurt Granroth (granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifdef KDE_USE_FINAL +#undef Always +#include <qdockwindow.h> +#endif + + + +#include "ktoolbar.h" +#include "kmainwindow.h" + +#include <string.h> + +#include <qpainter.h> +#include <qtooltip.h> +#include <qdrawutil.h> +#include <qstring.h> +#include <qrect.h> +#include <qobjectlist.h> +#include <qtimer.h> +#include <qstyle.h> +#include <qapplication.h> + +//US #include <config.h> + +#include "klineedit.h" +#include "kseparator.h" +#include <klocale.h> +#include <kapplication.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kiconloader.h> +#include <kcombobox.h> +//US #include <kpopupmenu.h> +//US #include <kanimwidget.h> +//US #include <kipc.h> +//US #include <kwin.h> +#include <kdebug.h> +#include <qlayout.h> + +#include "ktoolbarbutton.h" + +//US +#include "kconfigbase.h" + +#include <qpopupmenu.h> +#include <qmainwindow.h> + +enum { + CONTEXT_TOP = 0, + CONTEXT_LEFT = 1, + CONTEXT_RIGHT = 2, + CONTEXT_BOTTOM = 3, + CONTEXT_FLOAT = 4, + CONTEXT_FLAT = 5, + CONTEXT_ICONS = 6, + CONTEXT_TEXT = 7, + CONTEXT_TEXTRIGHT = 8, + CONTEXT_TEXTUNDER = 9, + CONTEXT_ICONSIZES = 50 // starting point for the icon size list, put everything else before +}; + +class KToolBarPrivate +{ +public: + KToolBarPrivate() { + m_iconSize = 0; + m_iconText = KToolBar::IconOnly; + m_highlight = true; + m_transparent = true; + m_honorStyle = false; + + m_enableContext = true; + + m_xmlguiClient = 0; + m_configurePlugged = false; + +//US oldPos = Qt::DockUnmanaged; + oldPos = QMainWindow::Unmanaged; + + modified = m_isHorizontal = positioned = FALSE; + + HiddenDefault = false; + IconSizeDefault = 0; + IconTextDefault = "IconOnly"; + IndexDefault = -1; + NewLineDefault = false; + OffsetDefault = -1; + PositionDefault = "Top"; + idleButtons.setAutoDelete(true); + } + + int m_iconSize; + KToolBar::IconText m_iconText; + bool m_highlight : 1; + bool m_transparent : 1; + bool m_honorStyle : 1; + bool m_isHorizontal : 1; + bool m_enableContext : 1; + bool m_configurePlugged : 1; + bool modified : 1; + bool positioned : 1; + + QWidget *m_parent; + + QMainWindow::ToolBarDock oldPos; + + KXMLGUIClient *m_xmlguiClient; + + struct ToolBarInfo + { +//US ToolBarInfo() : index( 0 ), offset( -1 ), newline( FALSE ), dock( Qt::DockTop ) {} + ToolBarInfo() : index( 0 ), offset( -1 ), newline( FALSE ), dock( QMainWindow::Top ) {} +//US ToolBarInfo( Qt::Dock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {} + ToolBarInfo( QMainWindow::ToolBarDock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {} + int index, offset; + bool newline; +//US Qt::Dock dock; + QMainWindow::ToolBarDock dock; + }; + + ToolBarInfo toolBarInfo; + QValueList<int> iconSizes; + QTimer repaintTimer; + + // Default Values. + bool HiddenDefault; + int IconSizeDefault; + QString IconTextDefault; + int IndexDefault; + bool NewLineDefault; + int OffsetDefault; + QString PositionDefault; + + QPtrList<QWidget> idleButtons; +}; + +KToolBarSeparator::KToolBarSeparator(Orientation o , bool l, QToolBar *parent, + const char* name ) + :QFrame( parent, name ), line( l ) +{ + connect( parent, SIGNAL(orientationChanged(Orientation)), + this, SLOT(setOrientation(Orientation)) ); + setOrientation( o ); + setBackgroundMode( parent->backgroundMode() ); + setBackgroundOrigin( ParentOrigin ); +} + +void KToolBarSeparator::setOrientation( Orientation o ) +{ + orient = o; + if ( line ) { + if ( orientation() == Vertical ) + setFrameStyle( HLine + Sunken ); + else + setFrameStyle( VLine + Sunken ); + } else { + setFrameStyle( NoFrame ); + } +} + +void KToolBarSeparator::styleChange( QStyle& ) +{ + setOrientation( orient ); +} + +QSize KToolBarSeparator::sizeHint() const +{ + return orientation() == Vertical ? QSize( 0, 6 ) : QSize( 6, 0 ); +} + +QSizePolicy KToolBarSeparator::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); +} + +KToolBar::KToolBar( QWidget *parent, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parent && parent->inherits( "QMainWindow" ) ? static_cast<QMainWindow*>(parent) : 0, + parent, FALSE, + name ? name : "mainToolBar") +#else + : QPEToolBar( parent && parent->inherits( "QMainWindow" ) ? static_cast<QMainWindow*>(parent) : 0, + QString::fromLatin1( name )) + + +#endif +{ + init( readConfig, honorStyle ); +} + +KToolBar::KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock, bool newLine, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parentWindow, dock, newLine, + name ? name : "mainToolBar") +#else + : QPEToolBar( parentWindow,QString::fromLatin1( name )) + + +#endif + +{ + init( readConfig, honorStyle ); +} + +KToolBar::KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parentWindow, dock, newLine, + name ? name : "mainToolBar") +#else + : QPEToolBar( parentWindow,QString::fromLatin1( name )) + + +#endif + +{ + init( readConfig, honorStyle ); +} + +KToolBar::~KToolBar() +{ + inshutdownprocess = true; + emit toolbarDestroyed(); + delete d; +} + +void KToolBar::init( bool readConfig, bool honorStyle ) +{ + inshutdownprocess = false; + d = new KToolBarPrivate; + setFullSize( TRUE ); + d->m_honorStyle = honorStyle; + context = 0; + layoutTimer = new QTimer( this ); + connect( layoutTimer, SIGNAL( timeout() ), + this, SLOT( rebuildLayout() ) ); + connect( &(d->repaintTimer), SIGNAL( timeout() ), + this, SLOT( slotRepaint() ) ); +/*US + if ( kapp ) { // may be null when started inside designer + connect(kapp, SIGNAL(toolbarAppearanceChanged(int)), this, SLOT(slotAppearanceChanged())); + // request notification of changes in icon style + kapp->addKipcEventMask(KIPC::IconChanged); + connect(kapp, SIGNAL(iconChanged(int)), this, SLOT(slotIconChanged(int))); + } +*/ + // finally, read in our configurable settings + if ( readConfig ) + slotReadConfig(); + + if ( mainWindow() ) + connect( mainWindow(), SIGNAL( toolBarPositionChanged( QToolBar * ) ), + this, SLOT( toolBarPosChanged( QToolBar * ) ) ); + + // Hack to make sure we recalculate our size when we dock. +//US connect( this, SIGNAL(placeChanged(QDockWindow::Place)), SLOT(rebuildLayout()) ); +} + +int KToolBar::insertButton(const QString& icon, int id, bool enabled, + const QString& text, int index/*US, KInstance *_instance*/ ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text/*US, _instance*/ ); + + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QString& icon, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled, const QString& text, int index/*US, KInstance *_instance*/ ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text/*US, _instance*/); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + connect( button, signal, receiver, slot ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QPixmap& pixmap, int id, bool enabled, + const QString& text, int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + doConnections( button ); + return index; +} +#if 0 + bar->insertButton( icon, id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index/*US, instance*/ ); +#endif + +int KToolBar::insertButton(const QPixmap& pixmap, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled, const QString& text, + int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + connect( button, signal, receiver, slot ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QString& icon, int id, QPopupMenu *popup, + bool enabled, const QString &text, int index ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text ); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + button->setPopup( popup ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup, + bool enabled, const QString &text, int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text ); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + button->setPopup( popup ); + doConnections( button ); + return index; +} + + +int KToolBar::insertLined (const QString& text, int id, + const char *signal, + const QObject *receiver, const char *slot, + bool enabled , + const QString& toolTipText, + int size, int index ) +{ + KLineEdit *lined = new KLineEdit ( this, 0 ); + if ( !toolTipText.isEmpty() ) + QToolTip::add( lined, toolTipText ); + if ( size > 0 ) + lined->setMinimumWidth( size ); + insertWidgetInternal( lined, index, id ); + connect( lined, signal, receiver, slot ); + lined->setText(text); + lined->setEnabled( enabled ); + return index; +} + +int KToolBar::insertCombo (const QStringList &list, int id, bool writable, + const char *signal, const QObject *receiver, + const char *slot, bool enabled, + const QString& tooltiptext, + int size, int index, + QComboBox::Policy policy ) +{ +//US KComboBox *combo = new KComboBox ( writable, this ); + KComboBox *combo = new KComboBox ( this ); + combo->setEditable(writable); + + insertWidgetInternal( combo, index, id ); + combo->insertStringList (list); + combo->setInsertionPolicy(policy); + combo->setEnabled( enabled ); + if ( !tooltiptext.isEmpty() ) + QToolTip::add( combo, tooltiptext ); + if ( size > 0 ) + combo->setMinimumWidth( size ); + if (!tooltiptext.isNull()) + QToolTip::add( combo, tooltiptext ); + + if ( signal && receiver && slot ) + connect ( combo, signal, receiver, slot ); + return index; +} + + +int KToolBar::insertCombo (const QString& text, int id, bool writable, + const char *signal, QObject *receiver, + const char *slot, bool enabled, + const QString& tooltiptext, + int size, int index, + QComboBox::Policy policy ) +{ +//US KComboBox *combo = new KComboBox ( writable, this ); + KComboBox *combo = new KComboBox ( this ); + combo->setEditable(writable); + + insertWidgetInternal( combo, index, id ); + combo->insertItem (text); + combo->setInsertionPolicy(policy); + combo->setEnabled( enabled ); + if ( !tooltiptext.isEmpty() ) + QToolTip::add( combo, tooltiptext ); + if ( size > 0 ) + combo->setMinimumWidth( size ); + if (!tooltiptext.isNull()) + QToolTip::add( combo, tooltiptext ); + connect (combo, signal, receiver, slot); + return index; +} + +int KToolBar::insertSeparator(int index, int id) +{ + QWidget *w = new KToolBarSeparator( orientation(), FALSE, this, "tool bar separator" ); + insertWidgetInternal( w, index, id ); + return index; +} + +int KToolBar::insertLineSeparator(int index, int id) +{ + QWidget *w = new KToolBarSeparator( orientation(), TRUE, this, "tool bar separator" ); + insertWidgetInternal( w, index, id ); + return index; +} + + +int KToolBar::insertWidget(int id, int /*width*/, QWidget *widget, int index) +{ + // removeWidgetInternal( widget ); // in case we already have it ? + insertWidgetInternal( widget, index, id ); + return index; +} +/*US +int KToolBar::insertAnimatedWidget(int id, QObject *receiver, const char *slot, + const QString& icons, int index ) +{ + KAnimWidget *anim = new KAnimWidget( icons, d->m_iconSize, this ); + insertWidgetInternal( anim, index, id ); + + if ( receiver ) + connect( anim, SIGNAL(clicked()), receiver, slot); + + return index; +} + +KAnimWidget *KToolBar::animatedWidget( int id ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; + if ( (*it) && (*it)->inherits( "KAnimWidget" ) ) + return (KAnimWidget*)(*it); + QObjectList *l = queryList( "KAnimWidget" ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + + for ( QObject *o = l->first(); o; o = l->next() ) { + if ( o->inherits( "KAnimWidget" ) ) + { + delete l; + return (KAnimWidget*)o; + } + } + + delete l; + return 0; +} +*/ + +void KToolBar::addConnection (int id, const char *signal, + const QObject *receiver, const char *slot) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( (*it) ) + connect( (*it), signal, receiver, slot ); +} + +void KToolBar::setItemEnabled( int id, bool enabled ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( (*it) ) + (*it)->setEnabled( enabled ); +} + + +void KToolBar::setButtonPixmap( int id, const QPixmap& _pixmap ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setPixmap( _pixmap ); +} + + +void KToolBar::setButtonIcon( int id, const QString& _icon ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setIcon( _icon ); +} + +void KToolBar::setButtonIconSet( int id, const QIconSet& iconset ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setIconSet( iconset ); +} + + +void KToolBar::setDelayedPopup (int id , QPopupMenu *_popup, bool toggle ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setDelayedPopup( _popup, toggle ); +} + + +void KToolBar::setAutoRepeat (int id, bool flag) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setAutoRepeat( flag ); +} + + +void KToolBar::setToggle (int id, bool flag ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setToggle( flag ); +} + + +void KToolBar::toggleButton (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->toggle(); +} + + +void KToolBar::setButton (int id, bool flag) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->on( flag ); +} + + +bool KToolBar::isButtonOn (int id) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return false; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + return button ? button->isOn() : false; +} + + +void KToolBar::setLinedText (int id, const QString& text) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QLineEdit * lineEdit = dynamic_cast<QLineEdit *>( *it ); + QLineEdit * lineEdit = (QLineEdit *)( *it ); + if ( lineEdit ) + lineEdit->setText( text ); +} + + +QString KToolBar::getLinedText (int id) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return QString::null; +//US QLineEdit * lineEdit = dynamic_cast<QLineEdit *>( *it ); + QLineEdit * lineEdit = (QLineEdit *)( *it ); + return lineEdit ? lineEdit->text() : QString::null; +} + + +void KToolBar::insertComboItem (int id, const QString& text, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->insertItem( text, index ); +} + +void KToolBar::insertComboList (int id, const QStringList &list, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->insertStringList( list, index ); +} + + +void KToolBar::removeComboItem (int id, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->removeItem( index ); +} + + +void KToolBar::setCurrentComboItem (int id, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->setCurrentItem( index ); +} + + +void KToolBar::changeComboItem (int id, const QString& text, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->changeItem( text, index ); +} + + +void KToolBar::clearCombo (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->clear(); +} + + +QString KToolBar::getComboItem (int id, int index) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return QString::null; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + return comboBox ? comboBox->text( index ) : QString::null; +} + + +KComboBox * KToolBar::getCombo(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KComboBox *>( *it ); + return (KComboBox *)( *it ); +} + + +KLineEdit * KToolBar::getLined (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KLineEdit *>( *it ); + return (KLineEdit *)( *it ); +} + + +KToolBarButton * KToolBar::getButton (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KToolBarButton *>( *it ); + return (KToolBarButton *)( *it ); +} + + +void KToolBar::alignItemRight (int id, bool right ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( rightAligned && !right && (*it) == rightAligned ) + rightAligned = 0; + if ( (*it) && right ) + rightAligned = (*it); +} + + +QWidget *KToolBar::getWidget (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + return ( it == id2widget.end() ) ? 0 : (*it); +} + + +void KToolBar::setItemAutoSized (int id, bool yes ) +{ + QWidget *w = getWidget(id); + if ( w && yes ) + setStretchableWidget( w ); +} + + +void KToolBar::clear () +{ + QToolBar::clear(); + widget2id.clear(); + id2widget.clear(); +} + + +void KToolBar::removeItem(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + { + kdDebug(220) << "KToolBar::removeItem item " << id << " not found" << endl; + return; + } + QWidget * w = (*it); + id2widget.remove( id ); + widget2id.remove( w ); + widgets.removeRef( w ); + delete w; +} + + +void KToolBar::removeItemDelayed(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + { + kdDebug(220) << "KToolBar::removeItem item " << id << " not found" << endl; + return; + } + QWidget * w = (*it); + id2widget.remove( id ); + widget2id.remove( w ); + widgets.removeRef( w ); + + w->blockSignals(true); + d->idleButtons.append(w); + layoutTimer->start( 50, TRUE ); +} + + +void KToolBar::hideItem (int id) +{ + QWidget *w = getWidget(id); + if ( w ) + w->hide(); +} + + +void KToolBar::showItem (int id) +{ + QWidget *w = getWidget(id); + if ( w ) + w->show(); +} + + +int KToolBar::itemIndex (int id) +{ + QWidget *w = getWidget(id); + return w ? widgets.findRef(w) : -1; +} + + +void KToolBar::setFullSize(bool flag ) +{ + setHorizontalStretchable( flag ); + setVerticalStretchable( flag ); +} + + +bool KToolBar::fullSize() const +{ + return isHorizontalStretchable() || isVerticalStretchable(); +} + + +void KToolBar::enableMoving(bool flag ) +{ +//US setMovingEnabled(flag); + this->mainWindow()->setToolBarsMovable(flag); +} + + +void KToolBar::setBarPos (BarPosition bpos) +{ + if ( !mainWindow() ) + return; +//US mainWindow()->moveDockWindow( this, (Dock)bpos ); + mainWindow()->moveToolBar( this, (QMainWindow::ToolBarDock)bpos ); +} + + +KToolBar::BarPosition KToolBar::barPos() +{ + if ( !(QMainWindow*)mainWindow() ) + return KToolBar::Top; +//US Dock dock; + QMainWindow::ToolBarDock dock; + int dm1, dm2; + bool dm3; + ((QMainWindow*)mainWindow())->getLocation( (QToolBar*)this, dock, dm1, dm3, dm2 ); +//US if ( dock == DockUnmanaged ) { + if ( dock == QMainWindow::Unmanaged ) { + return (KToolBar::BarPosition)Top; + } + return (BarPosition)dock; +} + + +bool KToolBar::enable(BarStatus stat) +{ + bool mystat = isVisible(); + + if ( (stat == Toggle && mystat) || stat == Hide ) + hide(); + else + show(); + + return isVisible() == mystat; +} + + +void KToolBar::setMaxHeight ( int h ) +{ + setMaximumHeight( h ); +} + +int KToolBar::maxHeight() +{ + return maximumHeight(); +} + + +void KToolBar::setMaxWidth (int dw) +{ + setMaximumWidth( dw ); +} + + +int KToolBar::maxWidth() +{ + return maximumWidth(); +} + + +void KToolBar::setTitle (const QString& _title) +{ + setLabel( _title ); +} + + +void KToolBar::enableFloating (bool ) +{ +} + + +void KToolBar::setIconText(IconText it) +{ + setIconText( it, true ); +} + + +void KToolBar::setIconText(IconText icontext, bool update) +{ + bool doUpdate=false; + + if (icontext != d->m_iconText) { + d->m_iconText = icontext; + doUpdate=true; + } + + if (update == false) + return; + + if (doUpdate) + emit modechange(); // tell buttons what happened + + // ugly hack to force a QMainWindow::triggerLayout( TRUE ) + if ( mainWindow() ) { + QMainWindow *mw = mainWindow(); + mw->setUpdatesEnabled( FALSE ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setUpdatesEnabled( TRUE ); + } +} + + +KToolBar::IconText KToolBar::iconText() const +{ + return d->m_iconText; +} + + +void KToolBar::setIconSize(int size) +{ + setIconSize( size, true ); +} + +void KToolBar::setIconSize(int size, bool update) +{ + bool doUpdate=false; + + if ( size != d->m_iconSize ) { + d->m_iconSize = size; + doUpdate=true; + } + + if (update == false) + return; + + if (doUpdate) + emit modechange(); // tell buttons what happened + + // ugly hack to force a QMainWindow::triggerLayout( TRUE ) + if ( mainWindow() ) { + QMainWindow *mw = mainWindow(); + mw->setUpdatesEnabled( FALSE ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setUpdatesEnabled( TRUE ); + } +} + + +int KToolBar::iconSize() const +{ +/*US + if ( !d->m_iconSize ) // default value? + { + if (!::qstrcmp(QObject::name(), "mainToolBar")) + return KGlobal::iconLoader()->currentSize(KIcon::MainToolbar); + else + return KGlobal::iconLoader()->currentSize(KIcon::Toolbar); + } + return d->m_iconSize; +*/ + int ret = 18; + if ( QApplication::desktop()->width() > 320 && QApplication::desktop()->width() < 650 ) + ret = 30; + return ret; +} + + +void KToolBar::setEnableContextMenu(bool enable ) +{ + d->m_enableContext = enable; +} + + +bool KToolBar::contextMenuEnabled() const +{ + return d->m_enableContext; +} + + +void KToolBar::setItemNoStyle(int id, bool no_style ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if (button) + button->setNoStyle( no_style ); +} + + +void KToolBar::setFlat (bool flag) +{ + if ( !mainWindow() ) + return; + if ( flag ) +//US mainWindow()->moveDockWindow( this, DockMinimized ); + mainWindow()->moveToolBar( this, QMainWindow::Minimized ); + else +//US mainWindow()->moveDockWindow( this, DockTop ); + mainWindow()->moveToolBar( this, QMainWindow::Top ); + // And remember to save the new look later +/*US + if ( mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + + +int KToolBar::count() const +{ + return id2widget.count(); +} + + +void KToolBar::saveState() +{ +/*US + // first, try to save to the xml file + if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() ) { + // go down one level to get to the right tags + QDomElement elem = d->m_xmlguiClient->domDocument().documentElement().toElement(); + elem = elem.firstChild().toElement(); + QString barname(!::qstrcmp(name(), "unnamed") ? "mainToolBar" : name()); + QDomElement current; + // now try to find our toolbar + d->modified = false; + for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) { + current = elem; + + if ( current.tagName().lower() != "toolbar" ) + continue; + + QString curname(current.attribute( "name" )); + + if ( curname == barname ) { + saveState( current ); + break; + } + } + // if we didn't make changes, then just return + if ( !d->modified ) + return; + + // now we load in the (non-merged) local file + QString local_xml(KXMLGUIFactory::readConfigFile(d->m_xmlguiClient->xmlFile(), true, d->m_xmlguiClient->instance())); + QDomDocument local; + local.setContent(local_xml); + + // make sure we don't append if this toolbar already exists locally + bool just_append = true; + elem = local.documentElement().toElement(); + KXMLGUIFactory::removeDOMComments( elem ); + elem = elem.firstChild().toElement(); + for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) { + if ( elem.tagName().lower() != "toolbar" ) + continue; + + QString curname(elem.attribute( "name" )); + + if ( curname == barname ) { + just_append = false; + local.documentElement().replaceChild( current, elem ); + break; + } + } + + if (just_append) + local.documentElement().appendChild( current ); + + KXMLGUIFactory::saveConfigFile(local, d->m_xmlguiClient->localXMLFile(), d->m_xmlguiClient->instance() ); + + return; + } +*/ + // if that didn't work, we save to the config file + KConfig *config = KGlobal::config(); + saveSettings(config, QString::null); + config->sync(); +} + +QString KToolBar::settingsGroup() +{ + QString configGroup; + if (!::qstrcmp(name(), "unnamed") || !::qstrcmp(name(), "mainToolBar")) + configGroup = "Toolbar style"; + else + configGroup = QString(name()) + " Toolbar style"; + if ( this->mainWindow() ) + { + configGroup.prepend(" "); + configGroup.prepend( this->mainWindow()->name() ); + } + return configGroup; +} + +void KToolBar::saveSettings(KConfig *config, const QString &_configGroup) +{ + QString configGroup = _configGroup; + if (configGroup.isEmpty()) + configGroup = settingsGroup(); + //kdDebug(220) << "KToolBar::saveSettings group=" << _configGroup << " -> " << configGroup << endl; + + QString position, icontext; + int index; + getAttributes( position, icontext, index ); + + //kdDebug(220) << "KToolBar::saveSettings " << name() << " newLine=" << newLine << endl; + + KConfigGroupSaver saver(config, configGroup); + + if ( position != d->PositionDefault ) + config->writeEntry("Position", position); + else + config->deleteEntry("Position"); + + if ( icontext != d->IconTextDefault ) + config->writeEntry("IconText", icontext); + else + config->deleteEntry("IconText"); + + if ( iconSize() != d->IconSizeDefault ) + config->writeEntry("IconSize", iconSize()); + else + config->deleteEntry("IconSize"); + + if ( isHidden() != d->HiddenDefault ) + config->writeEntry("Hidden", isHidden()); + else + config->deleteEntry("Hidden"); + + if ( index != d->IndexDefault ) + config->writeEntry( "Index", index ); + else + config->deleteEntry("Index"); +//US the older version of KDE (used on the Zaurus) has no Offset property +/* if ( offset() != d->OffsetDefault ) + config->writeEntry( "Offset", offset() ); + else +*/ + config->deleteEntry("Offset"); + +//US the older version of KDE (used on the Zaurus) has no NewLine property +/* + if ( newLine() != d->NewLineDefault ) + config->writeEntry( "NewLine", newLine() ); + else +*/ + config->deleteEntry("NewLine"); +} + +void KToolBar::setXMLGUIClient( KXMLGUIClient *client ) +{ + d->m_xmlguiClient = client; +} + +void KToolBar::setText( const QString & txt ) +{ +//US setLabel( txt + " ( " + kapp->caption() + " ) " ); + setLabel( txt + " ( " + KGlobal::getAppName() + " ) " ); +} + + +QString KToolBar::text() const +{ + return label(); +} + + +void KToolBar::doConnections( KToolBarButton *button ) +{ + connect(button, SIGNAL(clicked(int)), this, SIGNAL( clicked( int ) ) ); + connect(button, SIGNAL(doubleClicked(int)), this, SIGNAL( doubleClicked( int ) ) ); + connect(button, SIGNAL(released(int)), this, SIGNAL( released( int ) ) ); + connect(button, SIGNAL(pressed(int)), this, SIGNAL( pressed( int ) ) ); + connect(button, SIGNAL(toggled(int)), this, SIGNAL( toggled( int ) ) ); + connect(button, SIGNAL(highlighted(int, bool)), this, SIGNAL( highlighted( int, bool ) ) ); +} + +void KToolBar::mousePressEvent ( QMouseEvent *m ) +{ + if ( !mainWindow() ) + return; + QMainWindow *mw = mainWindow(); + if ( mw->toolBarsMovable() && d->m_enableContext ) { + if ( m->button() == RightButton ) { + int i = contextMenu()->exec( m->globalPos(), 0 ); + switch ( i ) { + case -1: + return; // popup cancelled + case CONTEXT_LEFT: +//US mw->moveDockWindow( this, DockLeft ); + mw->moveToolBar( this, QMainWindow::Left ); + break; + case CONTEXT_RIGHT: +//US mw->moveDockWindow( this, DockRight ); + mw->moveToolBar( this, QMainWindow::Right ); + break; + case CONTEXT_TOP: +//US mw->moveDockWindow( this, DockTop ); + mw->moveToolBar( this, QMainWindow::Top ); + break; + case CONTEXT_BOTTOM: +//US mw->moveDockWindow( this, DockBottom ); + mw->moveToolBar( this, QMainWindow::Bottom ); + break; + case CONTEXT_FLOAT: + break; + case CONTEXT_FLAT: +//US mw->moveDockWindow( this, DockMinimized ); + mw->moveToolBar( this, QMainWindow::Minimized ); + break; + case CONTEXT_ICONS: + setIconText( IconOnly ); + break; + case CONTEXT_TEXTRIGHT: + setIconText( IconTextRight ); + break; + case CONTEXT_TEXT: + setIconText( TextOnly ); + break; + case CONTEXT_TEXTUNDER: + setIconText( IconTextBottom ); + break; + default: + if ( i >= CONTEXT_ICONSIZES ) + setIconSize( i - CONTEXT_ICONSIZES ); + else + return; // assume this was an action handled elsewhere, no need for setSettingsDirty() + } +/*US + if ( mw->inherits("KMainWindow") ) + static_cast<KMainWindow *>(mw)->setSettingsDirty(); +*/ + } + } +} + + +void KToolBar::rebuildLayout() +{ + + for(QWidget *w=d->idleButtons.first(); w; w=d->idleButtons.next()) + w->blockSignals(false); + d->idleButtons.clear(); + + layoutTimer->stop(); + QApplication::sendPostedEvents( this, QEvent::ChildInserted ); + QBoxLayout *l = boxLayout(); + l->setMargin( 1 ); + // clear the old layout + QLayoutIterator it = l->iterator(); + + while ( it.current() ) { + it.deleteCurrent(); + } + for ( QWidget *w = widgets.first(); w; w = widgets.next() ) { + if ( w == rightAligned ) { + continue; + } + if ( w->inherits( "KToolBarSeparator" ) && + !( (KToolBarSeparator*)w )->showLine() ) { + l->addSpacing( 6 ); + w->hide(); + continue; + } + if ( w->inherits( "QPopupMenu" ) ) + continue; + l->addWidget( w ); + w->show(); + } + if ( rightAligned ) { + l->addStretch(); + l->addWidget( rightAligned ); + rightAligned->show(); + } + + if ( fullSize() ) { + // This code sucks. It makes the last combo in a toolbar VERY big (e.g. zoom combo in kword). + //if ( !stretchableWidget && widgets.last() && + // !widgets.last()->inherits( "QButton" ) && !widgets.last()->inherits( "KAnimWidget" ) ) + // setStretchableWidget( widgets.last() ); + if ( !rightAligned ) + l->addStretch(); + if ( stretchableWidget ) + l->setStretchFactor( stretchableWidget, 10 ); + } + l->invalidate(); + QApplication::postEvent( this, new QEvent( QEvent::LayoutHint ) ); + //#endif //DESKTOP_VERSION +} + +void KToolBar::childEvent( QChildEvent *e ) +{ + + if ( e->child()->isWidgetType() ) { + QWidget * w = (QWidget*)e->child(); + if ( e->type() == QEvent::ChildInserted ) { + if ( !e->child()->inherits( "QPopupMenu" ) && + ::qstrcmp( "qt_dockwidget_internal", e->child()->name() ) != 0 ) { + + // prevent items that have been explicitly inserted by insert*() from + // being inserted again + if ( !widget2id.contains( w ) ) + { + int dummy = -1; + insertWidgetInternal( w, dummy, -1 ); + } + } + } else { + removeWidgetInternal( w ); + } + if ( isVisibleTo( 0 ) ) + { + QBoxLayout *l = boxLayout(); + // QLayout *l = layout(); + + // clear the old layout so that we don't get unnecassery layout + // changes till we have rebuild the thing + QLayoutIterator it = l->iterator(); + while ( it.current() ) { + it.deleteCurrent(); + } + layoutTimer->start( 50, TRUE ); + } + } + QToolBar::childEvent( e ); +} + +void KToolBar::insertWidgetInternal( QWidget *w, int &index, int id ) +{ + // we can't have it in widgets, or something is really wrong + //widgets.removeRef( w ); + + connect( w, SIGNAL( destroyed() ), + this, SLOT( widgetDestroyed() ) ); + if ( index == -1 || index > (int)widgets.count() ) { + widgets.append( w ); + index = (int)widgets.count(); + } + else + widgets.insert( index, w ); + if ( id == -1 ) + id = id2widget.count(); + id2widget.insert( id, w ); + widget2id.insert( w, id ); +} + +void KToolBar::showEvent( QShowEvent *e ) +{ + QToolBar::showEvent( e ); + rebuildLayout(); +} + +void KToolBar::setStretchableWidget( QWidget *w ) +{ + QToolBar::setStretchableWidget( w ); + stretchableWidget = w; +} + +QSizePolicy KToolBar::sizePolicy() const +{ + if ( orientation() == Horizontal ) + return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + else + return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ); +} + +QSize KToolBar::sizeHint() const +{ + return QToolBar::sizeHint(); +#if 0 + QWidget::polish(); + static int iii = 0; + ++iii; + qDebug("++++++++ KToolBar::sizeHint() %d ", iii ); + int margin = static_cast<QWidget*>(ncThis)->layout()->margin(); + switch( barPos() ) + { + case KToolBar::Top: + case KToolBar::Bottom: + for ( QWidget *w = widgets.first(); w; w =widgets.next() ) + { + if ( w->inherits( "KToolBarSeparator" ) && + !( static_cast<KToolBarSeparator*>(w)->showLine() ) ) + { + minSize += QSize(6, 0); + } + else + { + QSize sh = w->sizeHint(); + if (!sh.isValid()) + sh = w->minimumSize(); + minSize = minSize.expandedTo(QSize(0, sh.height())); + minSize += QSize(sh.width()+1, 0); + } + } +/*US + minSize += QSize(QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent ), 0); +*/ + minSize += QSize(margin*2, margin*2); + break; + + case KToolBar::Left: + case KToolBar::Right: + for ( QWidget *w = widgets.first(); w; w = widgets.next() ) + { + if ( w->inherits( "KToolBarSeparator" ) && + !( static_cast<KToolBarSeparator*>(w)->showLine() ) ) + { + minSize += QSize(0, 6); + } + else + { + QSize sh = w->sizeHint(); + if (!sh.isValid()) + sh = w->minimumSize(); + minSize = minSize.expandedTo(QSize(sh.width(), 0)); + minSize += QSize(0, sh.height()+1); + } + } +/*US + minSize += QSize(0, QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); +*/ + minSize += QSize(margin*2, margin*2); + break; + + default: + minSize = QToolBar::sizeHint(); + break; + } + return minSize; +#endif +} + +QSize KToolBar::minimumSize() const +{ + return minimumSizeHint(); +} + +QSize KToolBar::minimumSizeHint() const +{ + return sizeHint(); +} + +bool KToolBar::highlight() const +{ + return d->m_highlight; +} + +void KToolBar::hide() +{ + QToolBar::hide(); +} + +void KToolBar::show() +{ + QToolBar::show(); +} + +void KToolBar::resizeEvent( QResizeEvent *e ) +{ + bool b = isUpdatesEnabled(); + setUpdatesEnabled( FALSE ); + QToolBar::resizeEvent( e ); + if (b) + d->repaintTimer.start( 100, true ); +} + +void KToolBar::slotIconChanged(int group) +{ + if ((group != KIcon::Toolbar) && (group != KIcon::MainToolbar)) + return; + if ((group == KIcon::MainToolbar) != !::qstrcmp(name(), "mainToolBar")) + return; + + emit modechange(); + if (isVisible()) + updateGeometry(); +} + +void KToolBar::slotReadConfig() +{ + //kdDebug(220) << "KToolBar::slotReadConfig" << endl; + // Read appearance settings (hmm, we used to do both here, + // but a well behaved application will call applyMainWindowSettings + // anyway, right ?) + applyAppearanceSettings(KGlobal::config(), QString::null ); +} + +void KToolBar::slotAppearanceChanged() +{ + // Read appearance settings from global file. + applyAppearanceSettings(KGlobal::config(), QString::null, true /* lose local settings */ ); + // And remember to save the new look later +/*US + if ( mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + +//static +bool KToolBar::highlightSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + return KGlobal::config()->readBoolEntry(QString::fromLatin1("Highlighting"),true); +} + +//static +bool KToolBar::transparentSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + return KGlobal::config()->readBoolEntry(QString::fromLatin1("TransparentMoving"),true); +} + +//static +KToolBar::IconText KToolBar::iconTextSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + QString icontext = KGlobal::config()->readEntry(QString::fromLatin1("IconText"),QString::fromLatin1("IconOnly")); + if ( icontext == "IconTextRight" ) + return IconTextRight; + else if ( icontext == "IconTextBottom" ) + return IconTextBottom; + else if ( icontext == "TextOnly" ) + return TextOnly; + else + return IconOnly; +} + +void KToolBar::applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal) +{ + QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup; + //kdDebug(220) << "KToolBar::applyAppearanceSettings: configGroup=" << configGroup << endl; + // We have application-specific settings in the XML file, + // and nothing in the application's config file + // -> don't apply the global defaults, the XML ones are preferred + // See applySettings for a full explanation +/*US :we do not support xml files + if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() && + !config->hasGroup(configGroup) ) + { + //kdDebug(220) << "skipping global defaults, using XML ones instead" << endl; + return; + } +*/ + if ( !config->hasGroup(configGroup) ) + { + //kdDebug(220) << "skipping global defaults, using XML ones instead" << endl; + return; + } + + + KConfig *gconfig = KGlobal::config(); +/*US + static const QString &attrIconText = KGlobal::staticQString("IconText"); + static const QString &attrHighlight = KGlobal::staticQString("Highlighting"); + static const QString &attrTrans = KGlobal::staticQString("TransparentMoving"); + static const QString &attrSize = KGlobal::staticQString("IconSize"); +*/ + // we actually do this in two steps. + // First, we read in the global styles [Toolbar style] (from the KControl module). + // Then, if the toolbar is NOT 'mainToolBar', we will also try to read in [barname Toolbar style] + bool highlight; + int transparent; + QString icontext; + int iconsize = 0; + + // this is the first iteration + QString grpToolbar(QString::fromLatin1("Toolbar style")); + { // start block for KConfigGroupSaver + KConfigGroupSaver saver(gconfig, grpToolbar); + + // first, get the generic settings +//US highlight = gconfig->readBoolEntry(attrHighlight, true); + highlight = gconfig->readBoolEntry("Highlighting", true); +//US transparent = gconfig->readBoolEntry(attrTrans, true); + transparent = gconfig->readBoolEntry("TransparentMoving", true); + + // we read in the IconText property *only* if we intend on actually + // honoring it + if (d->m_honorStyle) +//US d->IconTextDefault = gconfig->readEntry(attrIconText, d->IconTextDefault); + d->IconTextDefault = gconfig->readEntry("IconText", d->IconTextDefault); + else + d->IconTextDefault = "IconOnly"; + + // Use the default icon size for toolbar icons. +//US d->IconSizeDefault = gconfig->readNumEntry(attrSize, d->IconSizeDefault); + d->IconSizeDefault = gconfig->readNumEntry("IconSize", d->IconSizeDefault); + + if ( !forceGlobal && config->hasGroup(configGroup) ) + { + config->setGroup(configGroup); + + // first, get the generic settings +//US highlight = config->readBoolEntry(attrHighlight, highlight); + highlight = config->readBoolEntry("Highlighting", highlight); +//US transparent = config->readBoolEntry(attrTrans, transparent); + transparent = config->readBoolEntry("TransparentMoving", transparent); + // now we always read in the IconText property +//US icontext = config->readEntry(attrIconText, d->IconTextDefault); + icontext = config->readEntry("IconText", d->IconTextDefault); + + // now get the size +//US iconsize = config->readNumEntry(attrSize, d->IconSizeDefault); + iconsize = config->readNumEntry("IconSize", d->IconSizeDefault); + } + else + { + iconsize = d->IconSizeDefault; + icontext = d->IconTextDefault; + } + + // revert back to the old group + } // end block for KConfigGroupSaver + + bool doUpdate = false; + + IconText icon_text; + if ( icontext == "IconTextRight" ) + icon_text = IconTextRight; + else if ( icontext == "IconTextBottom" ) + icon_text = IconTextBottom; + else if ( icontext == "TextOnly" ) + icon_text = TextOnly; + else + icon_text = IconOnly; + + // check if the icon/text has changed + if (icon_text != d->m_iconText) { + //kdDebug(220) << "KToolBar::applyAppearanceSettings setIconText " << icon_text << endl; + setIconText(icon_text, false); + doUpdate = true; + } + + // ...and check if the icon size has changed + if (iconsize != d->m_iconSize) { + setIconSize(iconsize, false); + doUpdate = true; + } + + QMainWindow *mw = mainWindow(); + + // ...and if we should highlight + if ( highlight != d->m_highlight ) { + d->m_highlight = highlight; + doUpdate = true; + } + + // ...and if we should move transparently + if ( mw && transparent != (!mw->opaqueMoving()) ) { + mw->setOpaqueMoving( !transparent ); + } + + if (doUpdate) + emit modechange(); // tell buttons what happened + if (isVisible ()) + updateGeometry(); +} + +void KToolBar::applySettings(KConfig *config, const QString &_configGroup) +{ + //kdDebug(220) << "KToolBar::applySettings group=" << _configGroup << endl; + + QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup; + + /* + Let's explain this a bit more in details. + The order in which we apply settings is : + Global config / <appnamerc> user settings if no XMLGUI is used + Global config / App-XML attributes / <appnamerc> user settings if XMLGUI is used + + So in the first case, we simply read everything from KConfig as below, + but in the second case we don't do anything here if there is no app-specific config, + and the XMLGUI uses the static methods of this class to get the global defaults. + + Global config doesn't include position (index, offset, newline and hidden/shown). + */ + + // First the appearance stuff - the one which has a global config + applyAppearanceSettings( config, _configGroup ); + + // ...and now the position stuff + if ( config->hasGroup(configGroup) ) + { + KConfigGroupSaver cgs(config, configGroup); +/*US + static const QString &attrPosition = KGlobal::staticQString("Position"); + static const QString &attrIndex = KGlobal::staticQString("Index"); + static const QString &attrOffset = KGlobal::staticQString("Offset"); + static const QString &attrNewLine = KGlobal::staticQString("NewLine"); + static const QString &attrHidden = KGlobal::staticQString("Hidden"); + + QString position = config->readEntry(attrPosition, d->PositionDefault); + int index = config->readNumEntry(attrIndex, d->IndexDefault); + int offset = config->readNumEntry(attrOffset, d->OffsetDefault); + bool newLine = config->readBoolEntry(attrNewLine, d->NewLineDefault); + bool hidden = config->readBoolEntry(attrHidden, d->HiddenDefault); +*/ + + QString position = config->readEntry("Position", d->PositionDefault); + int index = config->readNumEntry("Index", d->IndexDefault); + int offset = config->readNumEntry("Offset", d->OffsetDefault); + bool newLine = config->readBoolEntry("NewLine", d->NewLineDefault); + bool hidden = config->readBoolEntry("Hidden", d->HiddenDefault); + +/*US Dock pos(DockTop); + if ( position == "Top" ) + pos = DockTop; + else if ( position == "Bottom" ) + pos = DockBottom; + else if ( position == "Left" ) + pos = DockLeft; + else if ( position == "Right" ) + pos = DockRight; + else if ( position == "Floating" ) + pos = DockTornOff; + else if ( position == "Flat" ) + pos = DockMinimized; +*/ + QMainWindow::ToolBarDock pos(QMainWindow::Top); + if ( position == "Top" ) + pos = QMainWindow::Top; + else if ( position == "Bottom" ) + pos = QMainWindow::Bottom; + else if ( position == "Left" ) + pos = QMainWindow::Left; + else if ( position == "Right" ) + pos = QMainWindow::Right; + else if ( position == "Floating" ) + pos = QMainWindow::TornOff; + else if ( position == "Flat" ) + pos = QMainWindow::Minimized; + + //kdDebug(220) << "KToolBar::applySettings hidden=" << hidden << endl; + if (hidden) + hide(); + else + show(); + + if ( mainWindow() ) + { + QMainWindow *mw = mainWindow(); + + //kdDebug(220) << "KToolBar::applySettings updating ToolbarInfo" << endl; + d->toolBarInfo = KToolBarPrivate::ToolBarInfo( pos, index, newLine, offset ); + + // moveDockWindow calls QDockArea which does a reparent() on us with + // showIt = true, so we loose our visibility status + bool doHide = isHidden(); + +//US mw->moveDockWindow( this, pos, newLine, index, offset ); + mw->moveToolBar( this, pos, newLine, index, offset ); + + //kdDebug(220) << "KToolBar::applySettings " << name() << " moveDockWindow with pos=" << pos << " newLine=" << newLine << " idx=" << index << " offs=" << offset << endl; + if ( doHide ) + hide(); + } + if (isVisible ()) + updateGeometry(); + } +} + +bool KToolBar::event( QEvent *e ) +{ + if ( (e->type() == QEvent::LayoutHint) && isUpdatesEnabled() ) + d->repaintTimer.start( 100, true ); + + if (e->type() == QEvent::ChildInserted ) + { + // By pass QToolBar::event, + // it will show() the inserted child and we don't want to + // do that until we have rebuild the layout. + childEvent((QChildEvent *)e); + return true; + } + + return QToolBar::event( e ); +} + +void KToolBar::slotRepaint() +{ + setUpdatesEnabled( FALSE ); + // Send a resizeEvent to update the "toolbar extension arrow" + // (The button you get when your toolbar-items don't fit in + // the available space) + QResizeEvent ev(size(), size()); + resizeEvent(&ev); + //#ifdef DESKTOP_VERSION + QApplication::sendPostedEvents( this, QEvent::LayoutHint ); + //#endif //DESKTOP_VERSION + setUpdatesEnabled( TRUE ); + repaint( TRUE ); +} + +void KToolBar::toolBarPosChanged( QToolBar *tb ) +{ + if ( tb != this ) + return; +//US if ( d->oldPos == DockMinimized ) + if ( d->oldPos == QMainWindow::Minimized ) + rebuildLayout(); + d->oldPos = (QMainWindow::ToolBarDock)barPos(); +/*US + if ( mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + +/*US +void KToolBar::loadState( const QDomElement &element ) +{ + //kdDebug(220) << "KToolBar::loadState " << this << endl; + if ( !mainWindow() ) + return; + + { + QCString text = element.namedItem( "text" ).toElement().text().utf8(); + if ( text.isEmpty() ) + text = element.namedItem( "Text" ).toElement().text().utf8(); + if ( !text.isEmpty() ) + setText( i18n( text ) ); + } + + { + QCString attrFullWidth = element.attribute( "fullWidth" ).lower().latin1(); + if ( !attrFullWidth.isEmpty() ) + setFullSize( attrFullWidth == "true" ); + } + + Dock dock = DockTop; + { + QCString attrPosition = element.attribute( "position" ).lower().latin1(); + //kdDebug(220) << "KToolBar::loadState attrPosition=" << attrPosition << endl; + if ( !attrPosition.isEmpty() ) { + if ( attrPosition == "top" ) + dock = DockTop; + else if ( attrPosition == "left" ) + dock = DockLeft; + else if ( attrPosition == "right" ) + dock = DockRight; + else if ( attrPosition == "bottom" ) + dock = DockBottom; + else if ( attrPosition == "floating" ) + dock = DockTornOff; + else if ( attrPosition == "flat" ) + dock = DockMinimized; + } + } + + { + QCString attrIconText = element.attribute( "iconText" ).lower().latin1(); + if ( !attrIconText.isEmpty() ) { + //kdDebug(220) << "KToolBar::loadState attrIconText=" << attrIconText << endl; + if ( attrIconText == "icontextright" ) + setIconText( KToolBar::IconTextRight ); + else if ( attrIconText == "textonly" ) + setIconText( KToolBar::TextOnly ); + else if ( attrIconText == "icontextbottom" ) + setIconText( KToolBar::IconTextBottom ); + else if ( attrIconText == "icononly" ) + setIconText( KToolBar::IconOnly ); + } else + // Use global setting + setIconText( iconTextSetting() ); + } + + { + QString attrIconSize = element.attribute( "iconSize" ).lower(); + if ( !attrIconSize.isEmpty() ) + d->IconSizeDefault = attrIconSize.toInt(); + setIconSize( d->IconSizeDefault ); + } + + { + QString attrIndex = element.attribute( "index" ).lower(); + if ( !attrIndex.isEmpty() ) + d->IndexDefault = attrIndex.toInt(); + } + + { + QString attrOffset = element.attribute( "offset" ).lower(); + if ( !attrOffset.isEmpty() ) + d->OffsetDefault = attrOffset.toInt(); + } + + { + QString attrNewLine = element.attribute( "newline" ).lower(); + if ( !attrNewLine.isEmpty() ) + d->NewLineDefault = attrNewLine == "true"; + } + + { + QString attrHidden = element.attribute( "hidden" ).lower(); + if ( !attrHidden.isEmpty() ) + d->HiddenDefault = attrHidden == "true"; + } + + d->toolBarInfo = KToolBarPrivate::ToolBarInfo( dock, d->IndexDefault, d->NewLineDefault, d->OffsetDefault ); + mainWindow()->addDockWindow( this, dock, d->NewLineDefault ); +//US mainWindow()->moveDockWindow( this, dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + mainWindow()->moveToolBar( this, dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + + // Apply the highlight button setting + d->m_highlight = highlightSetting(); + + // Apply transparent-toolbar-moving setting (ok, this is global to the mainwindow, + // but we do it only if there are toolbars...) + if ( transparentSetting() != !mainWindow()->opaqueMoving() ) + mainWindow()->setOpaqueMoving( !transparentSetting() ); + + if ( d->HiddenDefault ) + hide(); + else + show(); + + getAttributes( d->PositionDefault, d->IconTextDefault, d->IndexDefault ); +} +*/ + +void KToolBar::getAttributes( QString &position, QString &icontext, int &index ) +{ + // get all of the stuff to save + switch ( barPos() ) { + case KToolBar::Flat: + position = "Flat"; + break; + case KToolBar::Bottom: + position = "Bottom"; + break; + case KToolBar::Left: + position = "Left"; + break; + case KToolBar::Right: + position = "Right"; + break; + case KToolBar::Floating: + position = "Floating"; + break; + case KToolBar::Top: + default: + position = "Top"; + break; + } + + if ( mainWindow() ) { + QMainWindow::ToolBarDock dock; + bool newLine; + int offset; + mainWindow()->getLocation( this, dock, index, newLine, offset ); + } + + switch (d->m_iconText) { + case KToolBar::IconTextRight: + icontext = "IconTextRight"; + break; + case KToolBar::IconTextBottom: + icontext = "IconTextBottom"; + break; + case KToolBar::TextOnly: + icontext = "TextOnly"; + break; + case KToolBar::IconOnly: + default: + icontext = "IconOnly"; + break; + } +} +/*US +void KToolBar::saveState( QDomElement ¤t ) +{ + QString position, icontext; + int index = -1; + getAttributes( position, icontext, index ); + + current.setAttribute( "noMerge", "1" ); + current.setAttribute( "position", position ); + current.setAttribute( "iconText", icontext ); + current.setAttribute( "index", index ); + current.setAttribute( "offset", offset() ); + current.setAttribute( "newline", newLine() ); + if ( isHidden() ) + current.setAttribute( "hidden", "true" ); + d->modified = true; +} +*/ + +void KToolBar::positionYourself( bool force ) +{ + if (force) + d->positioned = false; + + if ( d->positioned || !mainWindow() ) + { + //kdDebug(220) << "KToolBar::positionYourself d->positioned=true ALREADY DONE" << endl; + return; + } + // we can't test for ForceHide after moveDockWindow because QDockArea + // does a reparent() with showIt == true + bool doHide = isHidden(); + //kdDebug(220) << "positionYourself " << name() << " dock=" << d->toolBarInfo.dock << " newLine=" << d->toolBarInfo.newline << " offset=" << d->toolBarInfo.offset << endl; +/*US mainWindow()->moveDockWindow( this, d->toolBarInfo.dock, + d->toolBarInfo.newline, + d->toolBarInfo.index, + d->toolBarInfo.offset ); +*/ + mainWindow()->moveToolBar( this, d->toolBarInfo.dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + + if ( doHide ) + hide(); + // This method can only have an effect once - unless force is set + d->positioned = TRUE; +} + +//US KPopupMenu *KToolBar::contextMenu() +QPopupMenu *KToolBar::contextMenu() +{ + if ( context ) + return context; + + // Construct our context popup menu. Name it qt_dockwidget_internal so it + // won't be deleted by QToolBar::clear(). +//US context = new KPopupMenu( this, "qt_dockwidget_internal" ); + context = new QPopupMenu( this, "qt_dockwidget_internal" ); +//US context->insertTitle(i18n("Toolbar Menu")); + +//US KPopupMenu *orient = new KPopupMenu( context, "orient" ); + QPopupMenu *orient = new QPopupMenu( context, "orient" ); + orient->insertItem( i18n("toolbar position string","Top"), CONTEXT_TOP ); + orient->insertItem( i18n("toolbar position string","Left"), CONTEXT_LEFT ); + orient->insertItem( i18n("toolbar position string","Right"), CONTEXT_RIGHT ); + orient->insertItem( i18n("toolbar position string","Bottom"), CONTEXT_BOTTOM ); + orient->insertSeparator(-1); + //orient->insertItem( i18n("toolbar position string","Floating"), CONTEXT_FLOAT ); + orient->insertItem( i18n("min toolbar", "Flat"), CONTEXT_FLAT ); + +//US KPopupMenu *mode = new KPopupMenu( context, "mode" ); + QPopupMenu *mode = new QPopupMenu( context, "mode" ); + mode->insertItem( i18n("Icons Only"), CONTEXT_ICONS ); + mode->insertItem( i18n("Text Only"), CONTEXT_TEXT ); + mode->insertItem( i18n("Text Alongside Icons"), CONTEXT_TEXTRIGHT ); + mode->insertItem( i18n("Text Under Icons"), CONTEXT_TEXTUNDER ); + +//US KPopupMenu *size = new KPopupMenu( context, "size" ); + QPopupMenu *size = new QPopupMenu( context, "size" ); + size->insertItem( i18n("Default"), CONTEXT_ICONSIZES ); + // Query the current theme for available sizes + QValueList<int> avSizes; +/*US + KIconTheme *theme = KGlobal::instance()->iconLoader()->theme(); + if (!::qstrcmp(QObject::name(), "mainToolBar")) + avSizes = theme->querySizes( KIcon::MainToolbar); + else + avSizes = theme->querySizes( KIcon::Toolbar); +*/ + avSizes << 16; + avSizes << 32; + + d->iconSizes = avSizes; + + QValueList<int>::Iterator it; + for (it=avSizes.begin(); it!=avSizes.end(); it++) { + QString text; + if ( *it < 19 ) + text = i18n("Small (%1x%2)").arg(*it).arg(*it); + else if (*it < 25) + text = i18n("Medium (%1x%2)").arg(*it).arg(*it); + else + text = i18n("Large (%1x%2)").arg(*it).arg(*it); + //we use the size as an id, with an offset + size->insertItem( text, CONTEXT_ICONSIZES + *it ); + } + + context->insertItem( i18n("Orientation"), orient ); + orient->setItemChecked(CONTEXT_TOP, true); + context->insertItem( i18n("Text Position"), mode ); + context->setItemChecked(CONTEXT_ICONS, true); + context->insertItem( i18n("Icon Size"), size ); + +/*US + if (mainWindow()->inherits("KMainWindow")) + { + if ( (static_cast<KMainWindow*>(mainWindow())->toolBarMenuAction()) && + (static_cast<KMainWindow*>(mainWindow())->hasMenuBar()) ) + + (static_cast<KMainWindow*>(mainWindow()))->toolBarMenuAction()->plug(context); + } +*/ + + connect( context, SIGNAL( aboutToShow() ), this, SLOT( slotContextAboutToShow() ) ); + return context; +} + +void KToolBar::slotContextAboutToShow() +{ + if (!d->m_configurePlugged) + { + // try to find "configure toolbars" action + + KXMLGUIClient *xmlGuiClient = d->m_xmlguiClient; + if ( !xmlGuiClient && mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + xmlGuiClient = (KXMLGUIClient *)mainWindow(); + if ( xmlGuiClient ) + { + KAction *configureAction = xmlGuiClient->actionCollection()->action(KStdAction::stdName(KStdAction::ConfigureToolbars)); + if ( configureAction ) + { + configureAction->plug(context); + d->m_configurePlugged = true; + } + } + } + + for(int i = CONTEXT_ICONS; i <= CONTEXT_TEXTUNDER; ++i) + context->setItemChecked(i, false); + + switch( d->m_iconText ) + { + case IconOnly: + default: + context->setItemChecked(CONTEXT_ICONS, true); + break; + case IconTextRight: + context->setItemChecked(CONTEXT_TEXTRIGHT, true); + break; + case TextOnly: + context->setItemChecked(CONTEXT_TEXT, true); + break; + case IconTextBottom: + context->setItemChecked(CONTEXT_TEXTUNDER, true); + break; + } + + QValueList<int>::ConstIterator iIt = d->iconSizes.begin(); + QValueList<int>::ConstIterator iEnd = d->iconSizes.end(); + for (; iIt != iEnd; ++iIt ) + context->setItemChecked( CONTEXT_ICONSIZES + *iIt, false ); + + context->setItemChecked( CONTEXT_ICONSIZES, false ); + + context->setItemChecked( CONTEXT_ICONSIZES + d->m_iconSize, true ); + + for ( int i = CONTEXT_TOP; i <= CONTEXT_FLAT; ++i ) + context->setItemChecked( i, false ); + + switch ( barPos() ) + { + case KToolBar::Flat: + context->setItemChecked( CONTEXT_FLAT, true ); + break; + case KToolBar::Bottom: + context->setItemChecked( CONTEXT_BOTTOM, true ); + break; + case KToolBar::Left: + context->setItemChecked( CONTEXT_LEFT, true ); + break; + case KToolBar::Right: + context->setItemChecked( CONTEXT_RIGHT, true ); + break; + case KToolBar::Floating: + context->setItemChecked( CONTEXT_FLOAT, true ); + break; + case KToolBar::Top: + context->setItemChecked( CONTEXT_TOP, true ); + break; + default: break; + } +} + +void KToolBar::widgetDestroyed() +{ + removeWidgetInternal( (QWidget*)sender() ); +} + +void KToolBar::removeWidgetInternal( QWidget * w ) +{ + if ( inshutdownprocess ) + return; + widgets.removeRef( w ); + QMap< QWidget*, int >::Iterator it = widget2id.find( w ); + if ( it == widget2id.end() ) + return; + id2widget.remove( *it ); + widget2id.remove( it ); +} + +void KToolBar::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ktoolbar.moc" + diff --git a/microkde/kdeui/ktoolbar.h b/microkde/kdeui/ktoolbar.h new file mode 100644 index 0000000..2c061b5 --- a/dev/null +++ b/microkde/kdeui/ktoolbar.h @@ -0,0 +1,1107 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999, 2000 Kurt Granroth (granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +#ifndef KTOOLBAR_H +#define KTOOLBAR_H + +#ifndef DESKTOP_VERSION +#define private public +#include <qtoolbar.h> +#undef private +#include <qpe/qpetoolbar.h> +#else +#include <qtoolbar.h> +#endif + + +#include <qmainwindow.h> +#include <qcombobox.h> +#include <qmap.h> +#include <qptrlist.h> +#include <kglobal.h> +#include <qguardedptr.h> +#include <qframe.h> +#include <qiconset.h> + +class QDomElement; +class QSize; +class QPixmap; +class QPopupMenu; +class QStringList; +class QDomDocument; +class QTimer; + +class KLineEdit; +class KToolBar; +class KToolBarButton; +class KToolBoxManager; +//US class KAnimWidget; +//US class KPopupMenu; +//US class KInstance; +class KComboBox; +class KXMLGUIClient; + +class KToolBarPrivate; + +class KToolBarSeparator : public QFrame +{ + Q_OBJECT +public: + KToolBarSeparator( Orientation, bool l, QToolBar *parent, const char* name=0 ); + + QSize sizeHint() const; + Orientation orientation() const { return orient; } + QSizePolicy sizePolicy() const; + bool showLine() const { return line; } +public slots: + void setOrientation( Orientation ); +protected: + void styleChange( QStyle& ); +private: + Orientation orient; + bool line; +}; + + + /** + * A KDE-style toolbar. + * + * KToolBar can be dragged around in and between different docks. + * + * A KToolBar can contain all sorts of widgets. + * + * KToolBar can be used as a standalone widget, but @ref KMainWindow + * provides easy factories and management of one or more toolbars. + * Once you have a KToolBar object, you can insert items into it with the + * insert... methods, or remove them with the @ref removeItem() method. This + * can be done at any time; the toolbar will be automatically updated. + * There are also many methods to set per-child properties like alignment + * and toggle behaviour. + * + * KToolBar uses a global config group to load toolbar settings on + * construction. It will reread this config group on a + * @ref KApplication::appearanceChanged() signal. + * + * @short Floatable toolbar with auto resize. + * @version $Id$ + * @author Reginald Stadlbauer <reggie@kde.org>, Stephan Kulow <coolo@kde.org>, Sven Radej <radej@kde.org>. + */ + +// strange things are happening ... so I have to use strange define methods ... +// porting KToolBar back to Qt2 really needs some strange hacks + +#ifndef DESKTOP_VERSION +#define QToolBar QPEToolBar +#endif + + class KToolBar : public QToolBar +{ + Q_OBJECT + + + Q_ENUMS( IconText BarPosition ) + + Q_PROPERTY( IconText iconText READ iconText WRITE setIconText ) + Q_PROPERTY( BarPosition barPos READ barPos WRITE setBarPos ) + Q_PROPERTY( bool fullSize READ fullSize WRITE setFullSize ) + Q_PROPERTY( int iconSize READ iconSize WRITE setIconSize ) + Q_PROPERTY( QString text READ text WRITE setText ) +#ifndef DESKTOP_VERSION +#undef QToolBar +#endif +public: + enum IconText{IconOnly = 0, IconTextRight, TextOnly, IconTextBottom}; + /** + * The state of the status bar. + * @deprecated + **/ + enum BarStatus{Toggle, Show, Hide}; + /** + * Possible bar positions. + **/ + enum BarPosition{ Unmanaged, Floating, Top, Bottom, Right, Left, Flat}; + + /** + * Constructor. + * This constructor is used by the XML-GUI. If you use it, you need + * to call QMainWindow::addToolBar to specify the position of the toolbar. + * So it's simpler to use the other constructor. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parent The standard toolbar parent (usually a + * @ref KMainWindow) + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QWidget *parent, const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + /** + * Constructor for non-XML-GUI applications. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parentWindow The window that should be the parent of this toolbar + * @param dock The position of the toolbar. Usually QMainWindow::Top. + * @param newLine If true, start a new line in the dock for this toolbar. + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock /*= QMainWindow::Top*/, bool newLine = false, + const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + /** + * Constructor for non-XML-GUI applications. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parentWindow The window that should be the parent of this toolbar + * @param dock Another widget than the mainwindow to dock toolbar to. + * @param newLine If true, start a new line in the dock for this toolbar. + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine = false, + const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + virtual ~KToolBar(); + + /** + * Insert a button (a @ref KToolBarButton) with a pixmap. The + * pixmap is loaded by the button itself based on the global icon + * settings. + * + * You should connect to one or more signals in KToolBar: + * @ref clicked() , @ref pressed() , @ref released() , or + * @ref highlighted() and if the button is a toggle button + * (@ref setToggle() ) @ref toggled() . Those signals have @p id + * of a button that caused the signal. If you want to bind a popup + * to button, see @ref setButton(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QString& icon, int id, bool enabled = true, + const QString& text = QString::null, int index=-1/*US , + KInstance *_instance = KGlobal::instance()*/); + + /** + * This is the same as above, but with specified signals and + * slots to which this button will be connected. + * + * You can add more signals with @ref addConnection(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param signal The signal to connect to + * @param receiver The slot's parent + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QString& icon, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, const QString& text = QString::null, + int index=-1/*US, KInstance *_instance = KGlobal::instance()*/ ); + + /** + * Inserts a button (a @ref KToolBarButton) with the specified + * pixmap. This pixmap will be used as the "active" one and the + * disabled and default ones will be autogenerated. + * + * It is recommended that you use the insertButton function that + * allows you to specify the icon name rather then the pixmap + * itself. Specifying the icon name is much more flexible. + * + * You should connect to one or more signals in KToolBar: + * @ref clicked() , @ref pressed() , @ref released() , or + * @ref highlighted() and if the button is a toggle button + * (@ref setToggle() ) @ref toggled() . Those signals have @p id + * of a button that caused the signal. If you want to bind a popup + * to button, see @ref setButton(). + * + * @param pixmap The active pixmap + * @param id The id of this button + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QPixmap& pixmap, int id, bool enabled = true, + const QString& text = QString::null, int index=-1 ); + + /** + * This is the same as above, but with specified signals and + * slots to which this button will be connected. + * + * You can add more signals with @ref addConnection(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param signal The signal to connect to + * @param receiver The slot's parent + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QPixmap& pixmap, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, const QString& text = QString::null, + int index=-1 ); + + /** + * Inserts a button with popupmenu. + * + * Button will have small + * triangle. You have to connect to popup's signals. The + * signals @ref KButton::pressed(), @ref KButton::released(), + * @ref KButton::clicked() or @ref KButton::doubleClicked() are @p not + * emmited by + * this button (see @ref setDelayedPopup() for that). + * You can add custom popups which inherit @ref QPopupMenu to get popups + * with tables, drawings etc. Just don't fiddle with events there. + */ + int insertButton(const QString& icon, int id, QPopupMenu *popup, + bool enabled, const QString&_text, int index=-1); + + /** + * Inserts a button with popupmenu. + * + * Button will have small + * triangle. You have to connect to popup's signals. The + * signals @ref KButton::pressed(), @ref KButton::released(), + * @ref KButton::clicked() or @ref KButton::doubleClicked() are @p not + * emmited by + * this button (see @ref setDelayedPopup() for that). + * You can add custom popups which inherit @ref QPopupMenu to get popups + * with tables, drawings etc. Just don't fiddle with events there. + */ + int insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup, + bool enabled, const QString&_text, int index=-1); + + /** + * Inserts a @ref KLineEdit. You have to specify signals and slots to + * which KLineEdit will be connected. KLineEdit has all slots QLineEdit + * has, plus signals @ref KLineEdit::completion and @ref KLineEdit::textRotation + * KLineEdit can be set to autoresize itself to full free width + * in toolbar, that is to last right aligned item. For that, + * toolbar must be set to full width (which it is by default). + * @see setFullWidth() + * @see setItemAutoSized() + * @see KLineEdit + * @return Item index. + */ + int insertLined (const QString& text, int id, + const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, + const QString& toolTipText = QString::null, + int size = 70, int index =-1); + + /** + * Inserts a @ref KComboBox with list. + * + * Can be writable, but cannot contain + * pixmaps. By default inserting policy is AtBottom, i.e. typed items + * are placed at the bottom of the list. Can be autosized. If the size + * argument is specified as -1, the width of the combobox is automatically + * computed. + * + * @see setFullWidth() + * @see setItemAutoSized() + * @see KComboBox + * @return Item index. + */ + int insertCombo (const QStringList &list, int id, bool writable, + const char *signal, const QObject *receiver, + const char *slot, bool enabled=true, + const QString& tooltiptext=QString::null, + int size=70, int index=-1, + QComboBox::Policy policy = QComboBox::AtBottom); + + /** + * Insert a @ref KComboBox with text. + * + * The rest is the same as above. + * @see setItemAutoSized() + * + * @see KComboBox + * @return Item index. + */ + int insertCombo (const QString& text, int id, bool writable, + const char *signal, QObject *recevier, + const char *slot, bool enabled=true, + const QString& tooltiptext=QString::null, + int size=70, int index=-1, + QComboBox::Policy policy = QComboBox::AtBottom); + + /** + * Inserts a separator into the toolbar with the given id. + * Returns the separator's index + */ + int insertSeparator( int index = -1, int id = -1 ); + + /** + * Inserts a line separator into the toolbar with the given id. + * Returns the separator's index + */ + int insertLineSeparator( int index = -1, int id = -1 ); + + /** + * Inserts a user-defined widget. The widget @p must have this + * toolbar as its parent. + * + * Widget must have a QWidget for base class. Widget can be + * autosized to full width. If you forget about it, you can get a + * pointer to this widget with @ref getWidget(). + * @see setItemAutoSized() + * @return Item index. + */ + int insertWidget(int id, int width, QWidget *_widget, int index=-1); + + /** + * Inserts an animated widget. A @ref KAnimWidget will be created + * internally using the icon name you provide. + * This will emit a signal (clicked()) whenever the + * animation widget is clicked. + * + * @see animatedWidget() + * + * @param id The id for this toolbar item + * @param receiver The parent of your slot + * @param slot The slot to receive the clicked() signal + * @param icons The name of the animation icon group to use + * @param index The item index + * + * @return The item index + */ +/*US + int insertAnimatedWidget(int id, QObject *receiver, const char *slot, + const QString& icons, int index = -1); +*/ + /** + * This will return a pointer to the given animated widget, if it + * exists. + * + * @see insertAnimatedWidget + * + * @param id The id for the widget you want to get a pointer to + * + * @return A pointer to the current animated widget or 0L + */ +//US KAnimWidget *animatedWidget( int id ); + + /** + * Adds connections to items. + * + * It is important that you + * know the @p id of particular item. Nothing happens if you forget @p id. + */ + void addConnection (int id, const char *signal, + const QObject *receiver, const char *slot); + /** + * Enables/disables item. + */ + void setItemEnabled( int id, bool enabled ); + + /** + * Sets the icon for a button. + * + * Can be used while button is visible. + */ + void setButtonIcon( int id, const QString& _icon ); + + /** + * Sets button pixmap. + * + * Can be used while button is visible. + */ + void setButtonPixmap( int id, const QPixmap& _pixmap ); + + /** + * Sets a button icon from a QIconSet. + * + * Can be used while button is visible. + */ + void setButtonIconSet( int id, const QIconSet& iconset ); + + /** + * Sets a delayed popup for a button. + * + * Delayed popup is what you see in + * Netscape Navigator's Previous and Next buttons: If you click them you + * go back + * or forth. If you press them long enough, you get a history-menu. + * This is exactly what we do here. + * + * You will insert normal a button with connection (or use signals from + * toolbar): + * <pre> + * bar->insertButton(icon, id, SIGNAL(clicked ()), this, + * SLOT (slotClick()), true, "click or wait for popup"); + * </pre> And then add a delayed popup: + * <pre> + * bar->setDelayedPopup (id, historyPopup); </pre> + * + * Don't add delayed popups to buttons which have normal popups. + * + * You may add popups which are derived from @ref QPopupMenu. You may + * add popups that are already in the menu bar or are submenus of + * other popups. + */ + void setDelayedPopup (int id , QPopupMenu *_popup, bool toggle = false); + + /** + * Turns a button into an autorepeat button. + * + * Toggle buttons, buttons with menus, or + * buttons with delayed menus cannot be made into autorepeat buttons. + * Moreover, you can and will receive + * only the signal clicked(), but not pressed() or released(). + * When the user presses this button, you will receive the signal clicked(), + * and if the button is still pressed after some time, + * you will receive more clicked() signals separated by regular + * intervals. Since this uses @ref QButton::setAutoRepeat() , + * I can't quantify 'some'. + */ + void setAutoRepeat (int id, bool flag=true); + + + /** + * Turns button into a toggle button if @p flag is true. + */ + void setToggle (int id, bool flag = true); + + /** + * Toggles a togglebutton. + * + * If the button is a toggle button (see @ref setToggle()) + * the button state will be toggled. This will also cause the toolbar to + * emit the signal @ref KButton::toggled() with parameter @p id. You must connect to + * this signal, or use @ref addConnection() to connect directly to the + * button signal @ref KButton::toggled(). + */ + void toggleButton (int id); + + /** + * Sets a toggle button state. + * + * If the button is a toggle button (see @ref setToggle()) + * this will set its state flag. This will also emit the signal + * @ref KButton::toggled(). + * + * @see setToggle() + */ + void setButton (int id, bool flag); + + /** + * @return @p true if button is on, @p false if button is off or if the + * button is not a toggle button. + * @see setToggle() + */ + bool isButtonOn (int id) const; + + /** + * Sets the text of a line editor. + * + * Cursor is set at end of text. + */ + void setLinedText (int id, const QString& text); + + /** + * Returns a line editor text. + */ + QString getLinedText (int id) const; + + /** + * Inserts @p text in combobox @p id at position @p index. + */ + void insertComboItem (int id, const QString& text, int index); + + /** + * Inserts @p list in combobox @p id at position @p index. + */ + void insertComboList (int id, const QStringList &list, int index); + + /** + * Removes item @p index from combobox @p id. + */ + void removeComboItem (int id, int index); + + /** + * Sets item @p index to be current item in combobox @p id. + */ + void setCurrentComboItem (int id, int index); + + /** + * Changes item @p index in combobox @p id to text. + * + * @p index = -1 refers current item (one displayed in the button). + */ + void changeComboItem (int id, const QString& text, int index=-1); + + /** + * Clears the combobox @p id. + * + * Does not delete it or hide it. + */ + void clearCombo (int id); + + /** + * Returns text of item @p index from combobox @p id. + * + * @p index = -1 refers to current item. + */ + + QString getComboItem (int id, int index=-1) const; + + /** + * Returns a pointer to the combobox. + * + * Example: + * <pre> + * KComboBox *combo = toolbar->getCombo(combo_id); + * </pre> + * That way you can get access to other public methods + * that @ref KComboBox provides. + */ + KComboBox * getCombo(int id); + + /** + * Returns a pointer to KToolBarLined. + * + * Example: + * <pre> + * KLineEdit * lined = toolbar->getKToolBarLined(lined_id); + * </pre> + * That way you can get access to other public methods + * that @ref KLineEdit provides. @ref KLineEdit is the same thing + * as @ref QLineEdit plus completion signals. + */ + KLineEdit * getLined (int id); + + /** + * Returns a pointer to KToolBarButton. + * + * Example: + * <pre> + * KToolBarButton * button = toolbar->getButton(button_id); + * </pre> + * That way you can get access to other public methods + * that @ref KToolBarButton provides. + * + * Using this method is not recommended. + */ + KToolBarButton * getButton (int id); + + /** + * Align item to the right. + * + * This works only if toolbar is set to full width. + * @see setFullWidth() + */ + void alignItemRight (int id, bool right = true); + + /** + * Returns a pointer to an inserted widget. + * + * Wrong ids are not tested. + * You can do with this whatever you want, + * except change its height (hardcoded). If you change its width + * you will probably have to call QToolBar::updateRects(true) + * @see QWidget + * @see updateRects() + * + * KDE4: make this const! + */ + QWidget *getWidget (int id); + + /** + * Set item autosized. + * + * This works only if the toolbar is set to full width. + * Only @p one item can be autosized, and it has to be + * the last left-aligned item. Items that come after this must be right + * aligned. Items that can be right aligned are Lineds, Frames, Widgets and + * Combos. An autosized item will resize itself whenever the toolbar geometry + * changes to the last right-aligned item (or to end of toolbar if there + * are no right-aligned items.) + * @see setFullWidth() + * @see alignItemRight() + */ + void setItemAutoSized (int id, bool yes = true); + + /** + * Remove all items. + * + * The toolbar is redrawn after it. + */ + void clear (); + + /** + * Remove item @p id. + * + * Item is deleted. Toolbar is redrawn after it. + */ + void removeItem (int id); + + /** + * Remove item @p id. + * + * Item is deleted when toolbar is redrawn. + */ + void removeItemDelayed (int id); + + /** + * Hide item. + */ + void hideItem (int id); + + /** + * Show item. + */ + void showItem (int id); + + /** + * Returns the index of the given item. + * + * KDE4: make this const! + */ + int itemIndex (int id); + + /** + * Set toolbar to full parent size (default). + * + * In full size mode the bar + * extends over the parent's full width or height. If the mode is disabled + * the toolbar tries to take as much space as it needs without wrapping, but + * it does not exceed the parent box. You can force a certain width or + * height with @ref setMaxWidth() or @ref setMaxHeight(). + * + * If you want to use right-aligned items or auto-sized items you must use + * full size mode. + */ + void setFullSize(bool flag = true); + + /** + * @return @p true if the full-size mode is enabled. Otherwise + * it returns @false. + */ + bool fullSize() const; + + /** + * @deprecated use setMovingEnabled(bool) instead. + * Enable or disable moving of toolbar. + */ + void enableMoving(bool flag = true); + + /** + * Set position of toolbar. + * @see BarPosition() + */ + void setBarPos (BarPosition bpos); + + /** + * Returns position of toolbar. + */ + BarPosition barPos(); + + /** + * @deprecated + * Show, hide, or toggle toolbar. + * + * This method is provided for compatibility only, + * please use show() and/or hide() instead. + * @see BarStatus + */ + bool enable(BarStatus stat); + + /** + * @deprecated + * Use setMaximumHeight() instead. + */ + void setMaxHeight (int h); // Set max height for vertical toolbars + + /** + * @deprecated + * Use maximumHeight() instead. + * Returns the value that was set with @ref setMaxHeight(). + */ + int maxHeight(); + + /** + * @deprecated + * Use setMaximumWidth() instead. + * Set maximal width of horizontal (top or bottom) toolbar. + */ + void setMaxWidth (int dw); + + /** + * @deprecated + * Use maximumWidth() instead. + * Returns the value that was set with @ref setMaxWidth(). + */ + int maxWidth(); + + /** + * Set title for toolbar when it floats. + * + * Titles are however not (yet) + * visible. You can't change toolbar's title while it's floating. + */ + void setTitle (const QString& _title); + + /** + * @deprecated + * Use enableMoving() instead. + */ + void enableFloating (bool arrrrrrgh); + + /** + * Set the kind of painting for buttons. + * + * Choose from: + * @li IconOnly (only icons), + * @li IconTextRight (icon and text, text is left from icons), + * @li TextOnly (only text), + * @li IconTextBottom (icons and text, text is under icons). + * @see IconText + * + */ + void setIconText(IconText it); + // Note: don't merge with the next one, it breaks Qt properties + + /** + * Similar to @ref setIconText(IconText it) but allows you to + * disable or enable updating. If @p update is false, then the + * buttons will not be updated. This is useful only if you know + * that you will be forcing an update later. + */ + void setIconText(IconText it, bool update); + + /** + * @return The current text style for buttons. + */ + IconText iconText() const; + + /** + * Set the icon size to load. Usually you should not call + * this, the icon size is taken care of by KIconLoader + * and globally configured. + * By default, the toolbar will load icons of size 32 for main + * toolbars and 22 for other toolbars + * @see KIconLoader. + * + * @param size The size to use + */ + void setIconSize(int size); + // Note: don't merge with the next one, it breaks Qt properties + + /** + * Same as @ref setIconText(int size) but allows you + * to disable the toolbar update. + * + * @param size The size to use + * @param update If true, then the toolbar will be updated after + * this + */ + void setIconSize(int size, bool update); + + /** + * @return The current icon size for buttons. + */ + int iconSize() const; + + /** + * This allows you to enable or disable the context menu. + * + * @param enable If false, then the context menu will be disabled + */ + void setEnableContextMenu(bool enable = true); + + /** + * Returns whether or not the context menu is disabled + * + * @return The context menu state + */ + bool contextMenuEnabled() const; + + /** + * This will inform a toolbar button to ignore certain style + * changes. Specifically, it will ignore IconText (always IconOnly) + * and will not allow image effects to apply. + * + * @param id The button to exclude from styles + * @param no_style If true, then it is excluded (default: true). + */ + void setItemNoStyle(int id, bool no_style = true); + + void setFlat (bool flag); + + /** + * @return the number of items in the toolbar + */ + int count() const; + + /** + * Instruct the toolbar to save it's current state to either the app + * config file or to the XML-GUI resource file (whichever has + * precedence). + */ + void saveState(); + + /** + * Save the toolbar settings to group @p configGroup in @p config. + */ + void saveSettings(KConfig *config, const QString &configGroup); + + /** + * Read the toolbar settings from group @p configGroup in @p config + * and apply them. + */ + void applySettings(KConfig *config, const QString &configGroup); + + /** + * Tell the toolbar what XML-GUI resource file it should use to save + * it's state. The state of the toolbar (position, size, etc) is + * saved in KConfig files if the application does not use XML-GUI.. + * but if the app does, then it's saved the XML file. This function + * allows this to happen. + * + * @param xmlfile The XML-GUI resource file to write to + * @param xml The DOM document for the XML-GUI building + */ + // void setXML(const QString& xmlfile, const QDomDocument& xml); + /* @internal */ + void setXMLGUIClient( KXMLGUIClient *client ); + + /** + * Assign a (translated) text to this toolbar. This is used + * for the tooltip on the handle, and when listing the toolbars. + */ + void setText( const QString & txt ); + + /** + * @return the toolbar's text. + */ + QString text() const; + + void setStretchableWidget( QWidget *w ); + QSizePolicy sizePolicy() const; + bool highlight() const; + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSize minimumSize() const; + + void hide(); + void show(); + + void updateRects( bool = FALSE ) {} + +//US void loadState( const QDomElement &e ); +//US void saveState( QDomElement &e ); + + /** + * @internal + */ + void positionYourself( bool force = false); + +signals: + /** + * Emitted when button @p id is clicked. + */ + void clicked(int id); + + /** + * Emitted when button @p id is double-clicked. + * + * Note: you will always + * recive two @ref clicked() , @ref pressed() and @ref released() signals. + * There is no way to avoid it - at least no easy way. + * If you need to resolve this all you can do is set up timers + * which wait for @ref QApplication::doubleClickInterval() to expire. + * If in that time you don't get this signal, you may belive that + * button was only clicked and not double-clicked. + * And please note that butons with popup menus do not emit this signal, + * but those with delayed popup do. + */ + void doubleClicked (int id); + + /** + * Emitted when button @p id is pressed. + */ + void pressed(int); + + /** + * Emits when button @p id is released. + */ + void released(int); + + /** + * Emitted when a toggle button changes state. + * + * Emitted also if you change state + * with @ref setButton() or @ref toggleButton() + * If you make a button normal again, with + * setToggle(false), this signal won't + * be emitted. + */ + void toggled(int); + + /** + * This signal is emitted when item id gets highlighted/unhighlighted + * (i.e when mouse enters/exits). + * + * Note that this signal is emitted from + * all buttons (normal, disabled and toggle) even when there is no visible + * change in buttons (i.e., buttons do not raise when mouse enters). + * The parameter @p isHighlighted is @p true when mouse enters and @p false when + * mouse exits. + */ + void highlighted(int id, bool isHighlighted); + + /** + * This signal is emitted when item id gets highlighted/unhighlighted + * (i.e when mouse enters/exits). + * + * Note that this signal is emitted from + * all buttons (normal, disabled and toggle) even when there is no visible + * change in buttons (i.e., buttons do not raise when mouse enters). + */ + void highlighted(int id ); + + /** + * Emitted when toolbar changes position, or when + * an item is removed from toolbar. + * + * If you subclass @ref KMainWindow and reimplement + * @ref KMainWindow::resizeEvent() be sure to connect to + * this signal. Note: You can connect this signal to a slot that + * doesn't take parameter. + */ + void moved( BarPosition ); + + /** + * @internal + * This signal is emitted when toolbar detects changing of + * following parameters: + * highlighting, button-size, button-mode. This signal is + * internal, aimed to buttons. + */ + void modechange (); + + /** + * This signal is emitted when the toolbar is getting deleted, + * and before ~KToolbar finishes (so it's still time to remove + * widgets from the toolbar). + * Used by KWidgetAction. + * @since 3.2 + */ + void toolbarDestroyed(); + +public: + /** + * @return global setting for "Highlight buttons under mouse" + */ + static bool highlightSetting(); + + /** + * @return global setting for "Toolbars transparent when moving" + */ + static bool transparentSetting(); + + /** + * @return global setting for "Icon Text" + */ + static IconText iconTextSetting(); + +public slots: + virtual void setIconText( const QString &txt ) + { QToolBar::setIconText( txt ); } + +protected: + void mousePressEvent( QMouseEvent * ); + void childEvent( QChildEvent *e ); + void showEvent( QShowEvent *e ); + void resizeEvent( QResizeEvent *e ); + bool event( QEvent *e ); + void applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal = false); + QString settingsGroup(); + +private slots: + void rebuildLayout(); + void slotReadConfig (); + void slotAppearanceChanged(); + void slotIconChanged(int); + void slotRepaint(); + void toolBarPosChanged( QToolBar *tb ); + void slotContextAboutToShow(); + void widgetDestroyed(); + +private: + void init( bool readConfig = true, bool honorStyle = false ); + void doConnections( KToolBarButton *button ); + void insertWidgetInternal( QWidget *w, int &index, int id ); + void removeWidgetInternal( QWidget *w ); + void getAttributes( QString &position, QString &icontext, int &index ); +//US KPopupMenu *contextMenu(); + QPopupMenu *contextMenu(); + + QMap<QWidget*, int > widget2id; + typedef QMap<int, QWidget* > Id2WidgetMap; + Id2WidgetMap id2widget; +//US KPopupMenu *context; + QPopupMenu *context; + QPtrList<QWidget> widgets; + QTimer *layoutTimer; + QGuardedPtr<QWidget> stretchableWidget, rightAligned; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KToolBarPrivate *d; + bool inshutdownprocess; +}; + +#endif diff --git a/microkde/kdeui/ktoolbarbutton.cpp b/microkde/kdeui/ktoolbarbutton.cpp new file mode 100644 index 0000000..1d5d0e5 --- a/dev/null +++ b/microkde/kdeui/ktoolbarbutton.cpp @@ -0,0 +1,756 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 1999 Kurt Granroth (granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US #include <config.h> +#include <string.h> + +#include "ktoolbarbutton.h" +#include "ktoolbar.h" + +#include <qstyle.h> +#include <qimage.h> +#include <qtimer.h> +#include <qdrawutil.h> +#include <qtooltip.h> +#include <qbitmap.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qlayout.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> +//US #include <kiconeffect.h> +#include <kiconloader.h> + +// needed to get our instance +#include <kmainwindow.h> + +template class QIntDict<KToolBarButton>; + +class KToolBarButtonPrivate +{ +public: + KToolBarButtonPrivate() + { + m_noStyle = false; + m_isSeparator = false; + m_isRadio = false; + m_highlight = false; + m_isRaised = false; + m_isActive = false; + + m_iconName = QString::null; + m_iconText = KToolBar::IconOnly; + m_iconSize = 0; + +//US m_instance = KGlobal::instance(); + } + ~KToolBarButtonPrivate() + { + } + + int m_id; + bool m_noStyle: 1; + bool m_isSeparator: 1; + bool m_isRadio: 1; + bool m_highlight: 1; + bool m_isRaised: 1; + bool m_isActive: 1; + + QString m_iconName; + + KToolBar *m_parent; + KToolBar::IconText m_iconText; + int m_iconSize; + QSize size; + + QPoint m_mousePressPos; + +//US KInstance *m_instance; +}; + +// This will construct a separator +KToolBarButton::KToolBarButton( QWidget *_parent, const char *_name ) + : QToolButton( _parent , _name) +{ + d = new KToolBarButtonPrivate; + + resize(6,6); + hide(); + d->m_isSeparator = true; +} + +KToolBarButton::KToolBarButton( const QString& _icon, int _id, + QWidget *_parent, const char *_name, + const QString &_txt/*US, KInstance *_instance*/ ) + : QToolButton( _parent, _name ), d( 0 ) +{ + d = new KToolBarButtonPrivate; + + d->m_id = _id; + d->m_parent = (KToolBar*)_parent; + QToolButton::setTextLabel(_txt); +//US d->m_instance = _instance; + + setFocusPolicy( NoFocus ); + + // connect all of our slots and start trapping events + connect(d->m_parent, SIGNAL( modechange() ), + this, SLOT( modeChange() )); + + connect(this, SIGNAL( clicked() ), + this, SLOT( slotClicked() ) ); + connect(this, SIGNAL( pressed() ), + this, SLOT( slotPressed() ) ); + connect(this, SIGNAL( released() ), + this, SLOT( slotReleased() ) ); + installEventFilter(this); + + d->m_iconName = _icon; + + // do our initial setup + modeChange(); +} + +KToolBarButton::KToolBarButton( const QPixmap& pixmap, int _id, + QWidget *_parent, const char *name, + const QString& txt) + : QToolButton( _parent, name ), d( 0 ) +{ + d = new KToolBarButtonPrivate; + + d->m_id = _id; + d->m_parent = (KToolBar *) _parent; + QToolButton::setTextLabel(txt); + + setFocusPolicy( NoFocus ); + + // connect all of our slots and start trapping events + connect(d->m_parent, SIGNAL( modechange()), + this, SLOT(modeChange())); + + connect(this, SIGNAL( clicked() ), + this, SLOT( slotClicked() )); + connect(this, SIGNAL( pressed() ), + this, SLOT( slotPressed() )); + connect(this, SIGNAL( released() ), + this, SLOT( slotReleased() )); + installEventFilter(this); + + // set our pixmap and do our initial setup + setIconSet( QIconSet( pixmap )); + modeChange(); +} + +KToolBarButton::~KToolBarButton() +{ + delete d; d = 0; +} + +void KToolBarButton::modeChange() +{ + QSize mysize; + + // grab a few global variables for use in this function and others + d->m_highlight = d->m_parent->highlight(); + d->m_iconText = d->m_parent->iconText(); + + d->m_iconSize = d->m_parent->iconSize(); + if (!d->m_iconName.isNull()) + setIcon(d->m_iconName); + + // we'll start with the size of our pixmap + int pix_width = d->m_iconSize; + + if ( d->m_iconSize == 0 ) { + if (!strcmp(d->m_parent->name(), "mainToolBar")) +/*US + pix_width = IconSize( KIcon::MainToolbar ); + else + pix_width = IconSize( KIcon::Toolbar ); +*/ +//qDebug("KToolBarButton::modeChange make iconsize configurable"); + pix_width = 16; + } + int pix_height = pix_width; + + int text_height = 0; + int text_width = 0; + + QToolTip::remove(this); + if (d->m_iconText != KToolBar::IconOnly) + { + // okay, we have to deal with fonts. let's get our information now +/*US + QFont tmp_font = KGlobalSettings::toolBarFont(); + + // now parse out our font sizes from our chosen font + QFontMetrics fm(tmp_font); + + text_height = fm.lineSpacing(); + text_width = fm.width(textLabel()); +*/ +//qDebug("KToolBarButton::modeChange make textsize configurable"); + + // none of the other modes want tooltips + } + else + { + QToolTip::add(this, textLabel()); + } + + switch (d->m_iconText) + { + case KToolBar::IconOnly: + mysize = QSize(pix_width, pix_height); + break; + + case KToolBar::IconTextRight: + mysize = QSize(pix_width + text_width + 4, pix_height); + break; + + case KToolBar::TextOnly: + mysize = QSize(text_width + 4, text_height); + break; + + case KToolBar::IconTextBottom: + mysize = QSize((text_width + 4 > pix_width) ? text_width + 4 : pix_width, pix_height + text_height); + break; + + default: + break; + } +/*US + mysize = style().sizeFromContents(QStyle::CT_ToolButton, this, mysize). + expandedTo(QApplication::globalStrut()); +*/ + // make sure that this isn't taller then it is wide + if (mysize.height() > mysize.width()) + mysize.setWidth(mysize.height()); + + d->size = mysize; + setFixedSize(mysize); + updateGeometry(); +} + +void KToolBarButton::setTextLabel( const QString& text, bool tipToo) +{ + if (text.isNull()) + return; + + QString txt(text); + if (txt.right(3) == QString::fromLatin1("...")) + txt.truncate(txt.length() - 3); + + QToolButton::setTextLabel(txt, tipToo); + update(); +} + +void KToolBarButton::setText( const QString& text) +{ + setTextLabel(text, true); + modeChange(); +} + +void KToolBarButton::setIcon( const QString &icon ) +{ + d->m_iconName = icon; + d->m_iconSize = d->m_parent->iconSize(); + // QObject::name() return "const char *" instead of QString. + if (!strcmp(d->m_parent->name(), "mainToolBar")) +/*US QToolButton::setIconSet( d->m_instance->iconLoader()->loadIconSet( + d->m_iconName, KIcon::MainToolbar, d->m_iconSize )); +*/ + QToolButton::setIconSet( KGlobal::iconLoader()->loadIconSet(d->m_iconName )); + else +/*US QToolButton::setIconSet(d->m_instance->iconLoader()->loadIconSet( + d->m_iconName, KIcon::Toolbar, d->m_iconSize )); +*/ + QToolButton::setIconSet(KGlobal::iconLoader()->loadIconSet(d->m_iconName)); +} + +void KToolBarButton::setIconSet( const QIconSet &iconset ) +{ + QToolButton::setIconSet( iconset ); +} + +// remove? +void KToolBarButton::setPixmap( const QPixmap &pixmap ) +{ + if( pixmap.isNull()) // called by QToolButton + { + QToolButton::setPixmap( pixmap ); + return; + } + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Active ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDefaultPixmap( const QPixmap &pixmap ) +{ + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Normal ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDisabledPixmap( const QPixmap &pixmap ) +{ + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Disabled ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDefaultIcon( const QString& icon ) +{ + QIconSet set = iconSet(); + QPixmap pm; + if (!strcmp(d->m_parent->name(), "mainToolBar")) + pm = /*US d->m_instance->iconLoader()*/KGlobal::iconLoader()->loadIcon( icon, KIcon::MainToolbar, + d->m_iconSize ); + else + pm = /*US d->m_instance->iconLoader()*/KGlobal::iconLoader()->loadIcon( icon, KIcon::Toolbar, + d->m_iconSize ); + set.setPixmap( pm, QIconSet::Automatic, QIconSet::Normal ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDisabledIcon( const QString& icon ) +{ + QIconSet set = iconSet(); + QPixmap pm; + if (!strcmp(d->m_parent->name(), "mainToolBar")) + pm = /*US d->m_instance->iconLoader()*/ KGlobal::iconLoader()->loadIcon( icon, KIcon::MainToolbar, + d->m_iconSize ); + else + pm = /*US d->m_instance->iconLoader()*/ KGlobal::iconLoader()->loadIcon( icon, KIcon::Toolbar, + d->m_iconSize ); + set.setPixmap( pm, QIconSet::Automatic, QIconSet::Disabled ); + QToolButton::setIconSet( set ); +} + +QPopupMenu *KToolBarButton::popup() +{ + // obsolete + // KDE4: remove me + return QToolButton::popup(); +} + +void KToolBarButton::setPopup(QPopupMenu *p, bool) +{ + QToolButton::setPopup(p); + QToolButton::setPopupDelay(1); +} + + +void KToolBarButton::setDelayedPopup (QPopupMenu *p, bool) +{ + QToolButton::setPopup(p); +//US QToolButton::setPopupDelay(QApplication::startDragTime()); +} + +void KToolBarButton::leaveEvent(QEvent *) +{ + if( d->m_isRaised || d->m_isActive ) + { + d->m_isRaised = false; + d->m_isActive = false; + repaint(false); + } + + emit highlighted(d->m_id, false); +} + +void KToolBarButton::enterEvent(QEvent *) +{ + if (d->m_highlight) + { + if (isEnabled()) + { + d->m_isActive = true; + if (!isToggleButton()) + d->m_isRaised = true; + } + else + { + d->m_isRaised = false; + d->m_isActive = false; + } + + repaint(false); + } + emit highlighted(d->m_id, true); +} + +bool KToolBarButton::eventFilter(QObject *o, QEvent *ev) +{ + if ((KToolBarButton *)o == this) + { + + // Popup the menu when the left mousebutton is pressed and the mouse + // is moved by a small distance. + if (QToolButton::popup()) + { + if (ev->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mev = static_cast<QMouseEvent*>(ev); + d->m_mousePressPos = mev->pos(); + } + else if (ev->type() == QEvent::MouseMove) + { + QMouseEvent* mev = static_cast<QMouseEvent*>(ev); + if ((mev->pos() - d->m_mousePressPos).manhattanLength() +//US > KGlobalSettings::dndEventDelay()) + > 5 ) + { +//US openPopup(); + return true; + } + } + } + + if ((ev->type() == QEvent::MouseButtonPress || + ev->type() == QEvent::MouseButtonRelease || + ev->type() == QEvent::MouseButtonDblClick) && d->m_isRadio && isOn()) + return true; + + // From Kai-Uwe Sattler <kus@iti.CS.Uni-Magdeburg.De> + if (ev->type() == QEvent::MouseButtonDblClick) + { + emit doubleClicked(d->m_id); + return true; + } + } + + return QToolButton::eventFilter(o, ev); +} + +void KToolBarButton::drawButton( QPainter *_painter ) +{ +#ifdef DESKTOP_VERSION + QStyle::SFlags flags = QStyle::Style_Default; + QStyle::SCFlags active = QStyle::SC_None; + + if (isDown()) { + flags |= QStyle::Style_Down; + active |= QStyle::SC_ToolButton; + } + if (isEnabled()) flags |= QStyle::Style_Enabled; + if (isOn()) flags |= QStyle::Style_On; + if (isEnabled() && d->m_isRaised) flags |= QStyle::Style_Raised; + if (hasFocus()) flags |= QStyle::Style_HasFocus; + + // Draw a styled toolbutton + style().drawComplexControl(QStyle::CC_ToolButton, _painter, this, rect(), + colorGroup(), flags, QStyle::SC_ToolButton, active, QStyleOption()); + +#else + style().drawToolButton(_painter, rect().x(), rect().y(), rect().width(), rect().height(), colorGroup()); +#endif + int dx, dy; + QFont tmp_font(KGlobalSettings::toolBarFont()); + QFontMetrics fm(tmp_font); + QRect textRect; + int textFlags = 0; + + if (d->m_iconText == KToolBar::IconOnly) // icon only + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = ( width() - pixmap.width() ) / 2; + dy = ( height() - pixmap.height() ) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + } + else if (d->m_iconText == KToolBar::IconTextRight) // icon and text (if any) + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = 4; + dy = ( height() - pixmap.height() ) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + + if (!textLabel().isNull()) + { + textFlags = AlignVCenter|AlignLeft; + if (!pixmap.isNull()) + dx = 4 + pixmap.width() + 2; + else + dx = 4; + dy = 0; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect(dx, dy, width()-dx, height()); + } + } + else if (d->m_iconText == KToolBar::TextOnly) + { + if (!textLabel().isNull()) + { + textFlags = AlignVCenter|AlignLeft; + dx = (width() - fm.width(textLabel())) / 2; + dy = (height() - fm.lineSpacing()) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + else if (d->m_iconText == KToolBar::IconTextBottom) + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = (width() - pixmap.width()) / 2; + dy = (height() - fm.lineSpacing() - pixmap.height()) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + + if (!textLabel().isNull()) + { + textFlags = AlignBottom|AlignHCenter; + dx = (width() - fm.width(textLabel())) / 2; + dy = height() - fm.lineSpacing() - 4; + + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + + // Draw the text at the position given by textRect, and using textFlags + if (!textLabel().isNull() && !textRect.isNull()) + { + _painter->setFont(KGlobalSettings::toolBarFont()); + if (!isEnabled()) + _painter->setPen(palette().disabled().dark()); + else if(d->m_isRaised) + _painter->setPen(KGlobalSettings::toolBarHighlightColor()); + else + _painter->setPen( colorGroup().buttonText() ); + _painter->drawText(textRect, textFlags, textLabel()); + } + + if (QToolButton::popup()) + { +#ifdef DESKTOP_VERSION + QStyle::SFlags arrowFlags = QStyle::Style_Default; + + if (isDown()) arrowFlags |= QStyle::Style_Down; + if (isEnabled()) arrowFlags |= QStyle::Style_Enabled; + + style().drawPrimitive(QStyle::PE_ArrowDown, _painter, + QRect(width()-7, height()-7, 7, 7), colorGroup(), + arrowFlags, QStyleOption() ); +#else + style().drawArrow(_painter, Qt::DownArrow, isDown(), + width()-7, height()-7, 7, 7, colorGroup(), isEnabled() ); +#endif + + } +} + +void KToolBarButton::paletteChange(const QPalette &) +{ + if(!d->m_isSeparator) + { + modeChange(); + repaint(false); // no need to delete it first therefore only false + } +} + +void KToolBarButton::showMenu() +{ + // obsolete + // KDE4: remove me +} + +void KToolBarButton::slotDelayTimeout() +{ + // obsolete + // KDE4: remove me +} + +void KToolBarButton::slotClicked() +{ + emit clicked( d->m_id ); +} + +void KToolBarButton::slotPressed() +{ + emit pressed( d->m_id ); +} + +void KToolBarButton::slotReleased() +{ + emit released( d->m_id ); +} + +void KToolBarButton::slotToggled() +{ + emit toggled( d->m_id ); +} + +void KToolBarButton::setNoStyle(bool no_style) +{ + d->m_noStyle = no_style; + + modeChange(); + d->m_iconText = KToolBar::IconTextRight; + repaint(false); +} + +void KToolBarButton::setRadio (bool f) +{ + if ( d ) + d->m_isRadio = f; +} + +void KToolBarButton::on(bool flag) +{ + if(isToggleButton() == true) + setOn(flag); + else + { + setDown(flag); + leaveEvent((QEvent *) 0); + } + repaint(); +} + +void KToolBarButton::toggle() +{ + setOn(!isOn()); + repaint(); +} + +void KToolBarButton::setToggle(bool flag) +{ + setToggleButton(flag); + if (flag == true) + connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); + else + disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); +} + +QSize KToolBarButton::sizeHint() const +{ + return d->size; +} + +QSize KToolBarButton::minimumSizeHint() const +{ + return d->size; +} + +QSize KToolBarButton::minimumSize() const +{ + return d->size; +} + +bool KToolBarButton::isRaised() const +{ + return d->m_isRaised; +} + +bool KToolBarButton::isActive() const +{ + return d->m_isActive; +} + +int KToolBarButton::iconTextMode() const +{ + return static_cast<int>( d->m_iconText ); +} + +int KToolBarButton::id() const +{ + return d->m_id; +} + +// KToolBarButtonList +KToolBarButtonList::KToolBarButtonList() +{ + setAutoDelete(false); +} + +void KToolBarButton::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ktoolbarbutton.moc" diff --git a/microkde/kdeui/ktoolbarbutton.h b/microkde/kdeui/ktoolbarbutton.h new file mode 100644 index 0000000..9aaa13c --- a/dev/null +++ b/microkde/kdeui/ktoolbarbutton.h @@ -0,0 +1,313 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 2000 Kurt Granroth (granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ +#ifndef _KTOOLBARBUTTON_H +#define _KTOOLBARBUTTON_H + +#include <qpixmap.h> +#include <qtoolbutton.h> +#include <qintdict.h> +#include <qstring.h> +#include <kglobal.h> + +class KToolBar; +class KToolBarButtonPrivate; +//USclass KInstance; +class QEvent; +class QPopupMenu; +class QPainter; + +/** + * A toolbar button. This is used internally by @ref KToolBar, use the + * KToolBar methods instead. + * @internal + */ +class KToolBarButton : public QToolButton +{ + Q_OBJECT + +public: + /** + * Construct a button with an icon loaded by the button itself. + * This will trust the button to load the correct icon with the + * correct size. + * + * @param icon Name of icon to load (may be absolute or relative) + * @param id Id of this button + * @param parent This button's parent + * @param name This button's internal name + * @param txt This button's text (in a tooltip or otherwise) + */ + KToolBarButton(const QString& icon, int id, QWidget *parent, + const char *name=0L, const QString &txt=QString::null/*US, + KInstance *_instance = KGlobal::instance()*/); + + /** + * Construct a button with an existing pixmap. It is not + * recommended that you use this as the internal icon loading code + * will almost always get it "right". + * + * @param icon Name of icon to load (may be absolute or relative) + * @param id Id of this button + * @param parent This button's parent + * @param name This button's internal name + * @param txt This button's text (in a tooltip or otherwise) + */ + KToolBarButton(const QPixmap& pixmap, int id, QWidget *parent, + const char *name=0L, const QString &txt=QString::null); + + /** + * Construct a separator button + * + * @param parent This button's parent + * @param name This button's internal name + */ + KToolBarButton(QWidget *parent=0L, const char *name=0L); + + /** + * Standard destructor + */ + ~KToolBarButton(); + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSize minimumSize() const; + +#ifndef KDE_NO_COMPAT + /** + * @deprecated + * Set the pixmap directly for this button. This pixmap should be + * the active one... the dimmed and disabled pixmaps are constructed + * based on this one. However, don't use this function unless you + * are positive that you don't want to use @ref setIcon. + * + * @param pixmap The active pixmap + */ + // this one is from QButton, so #ifdef-ing it out doesn't break BC + virtual void setPixmap(const QPixmap &pixmap); + + /** + * @deprecated + * Force the button to use this pixmap as the default one rather + * then generating it using effects. + * + * @param pixmap The pixmap to use as the default (normal) one + */ + void setDefaultPixmap(const QPixmap& pixmap); + + /** + * @deprecated + * Force the button to use this pixmap when disabled one rather then + * generating it using effects. + * + * @param pixmap The pixmap to use when disabled + */ + void setDisabledPixmap(const QPixmap& pixmap); +#endif + + /** + * Set the text for this button. The text will be either used as a + * tooltip (IconOnly) or will be along side the icon + * + * @param text The button (or tooltip) text + */ + virtual void setText(const QString &text); + + /** + * Set the icon for this button. The icon will be loaded internally + * with the correct size. This function is preferred over @ref setIconSet + * + * @param icon The name of the icon + */ + virtual void setIcon(const QString &icon); + + /// @since 3.1 + virtual void setIcon( const QPixmap &pixmap ) + { QToolButton::setIcon( pixmap ); } + + /** + * Set the pixmaps for this toolbar button from a QIconSet. + * If you call this you don't need to call any of the other methods + * that set icons or pixmaps. + * @param iconset The iconset to use + */ + virtual void setIconSet( const QIconSet &iconset ); + +#ifndef KDE_NO_COMPAT + /** + * @deprecated + * Set the active icon for this button. The pixmap itself is loaded + * internally based on the icon size... .. the disabled and default + * pixmaps, however will only be constructed if @ref #generate is + * true. This function is preferred over @ref setPixmap + * + * @param icon The name of the active icon + * @param generate If true, then the other icons are automagically + * generated from this one + */ + void setIcon(const QString &icon, bool /*generate*/ ) { setIcon( icon ); } + + /** + * @deprecated + * Force the button to use this icon as the default one rather + * then generating it using effects. + * + * @param icon The icon to use as the default (normal) one + */ + void setDefaultIcon(const QString& icon); + + /** + * @deprecated + * Force the button to use this icon when disabled one rather then + * generating it using effects. + * + * @param icon The icon to use when disabled + */ + void setDisabledIcon(const QString& icon); +#endif + + /** + * Turn this button on or off + * + * @param flag true or false + */ + void on(bool flag = true); + + /** + * Toggle this button + */ + void toggle(); + + /** + * Turn this button into a toggle button or disable the toggle + * aspects of it. This does not toggle the button itself. + * Use @ref toggle() for that. + * + * @param toggle true or false + */ + void setToggle(bool toggle = true); + + /** + * Return a pointer to this button's popup menu (if it exists) + */ + QPopupMenu *popup(); + + /** + * Returns the button's id. + * @since 3.2 + */ + int id() const; + + /** + * Give this button a popup menu. There will not be a delay when + * you press the button. Use @ref setDelayedPopup if you want that + * behavior. + * + * @param p The new popup menu + */ + void setPopup (QPopupMenu *p, bool unused = false); + + /** + * Gives this button a delayed popup menu. + * + * This function allows you to add a delayed popup menu to the button. + * The popup menu is then only displayed when the button is pressed and + * held down for about half a second. + * + * @param p the new popup menu + */ + void setDelayedPopup(QPopupMenu *p, bool unused = false); + + /** + * Turn this button into a radio button + * + * @param f true or false + */ + void setRadio(bool f = true); + + /** + * Toolbar buttons naturally will assume the global styles + * concerning icons, icons sizes, etc. You can use this function to + * explicitely turn this off, if you like. + * + * @param no_style Will disable styles if true + */ + void setNoStyle(bool no_style = true); + +signals: + void clicked(int); + void doubleClicked(int); + void pressed(int); + void released(int); + void toggled(int); + void highlighted(int, bool); + +public slots: + /** + * This slot should be called whenever the toolbar mode has + * potentially changed. This includes such events as text changing, + * orientation changing, etc. + */ + void modeChange(); + virtual void setTextLabel(const QString&, bool tipToo); + +protected: + void paletteChange(const QPalette &); + void leaveEvent(QEvent *e); + void enterEvent(QEvent *e); + void drawButton(QPainter *p); + bool eventFilter (QObject *o, QEvent *e); + void showMenu(); + + /// @since 3.1 + bool isRaised() const; + /// @since 3.1 + bool isActive() const; + /// @since 3.1 + int iconTextMode() const; + +protected slots: + void slotClicked(); + void slotPressed(); + void slotReleased(); + void slotToggled(); + void slotDelayTimeout(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KToolBarButtonPrivate *d; +}; + +/** +* List of @ref KToolBarButton objects. +* @internal +* @version $Id$ +*/ +class KToolBarButtonList : public QIntDict<KToolBarButton> +{ +public: + KToolBarButtonList(); + ~KToolBarButtonList() {} +}; + +#endif diff --git a/microkde/kdeui/ktoolbarhandler.cpp b/microkde/kdeui/ktoolbarhandler.cpp new file mode 100644 index 0000000..7b97233 --- a/dev/null +++ b/microkde/kdeui/ktoolbarhandler.cpp @@ -0,0 +1,253 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon Hausmann <hausmann@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "ktoolbarhandler.h" + +#include <qpopupmenu.h> +#include <kapplication.h> +#include <ktoolbar.h> +#include <kmainwindow.h> +#include <klocale.h> +#include <kaction.h> +#include <assert.h> + +namespace +{ + const char *actionListName = "show_menu_and_toolbar_actionlist"; + + const char *guiDescription = "" + "<!DOCTYPE kpartgui><kpartgui name=\"StandardToolBarMenuHandler\">" + "<MenuBar>" + " <Menu name=\"settings\">" + " <ActionList name=\"%1\" />" + " </Menu>" + "</MenuBar>" + "</kpartgui>"; + + const char *resourceFileName = "barhandler.rc"; + + class BarActionBuilder + { + public: + BarActionBuilder( KActionCollection *actionCollection, KMainWindow *mainWindow, QPtrList<KToolBar> &oldToolBarList ) + : m_actionCollection( actionCollection ), m_mainWindow( mainWindow ), m_needsRebuild( false ) + { +/*US + QPtrList<QDockWindow> dockWindows = m_mainWindow->dockWindows(); + QPtrListIterator<QDockWindow> dockWindowIt( dockWindows ); + for ( ; dockWindowIt.current(); ++dockWindowIt ) { + +//US KToolBar *toolBar = dynamic_cast<KToolBar *>( dockWindowIt.current() ); + KToolBar *toolBar = (KToolBar *)( dockWindowIt.current() ); + if ( !toolBar ) + continue; + + if ( oldToolBarList.findRef( toolBar ) == -1 ) + m_needsRebuild = true; + + m_toolBars.append( toolBar ); + } +*/ + if ( !m_needsRebuild ) + m_needsRebuild = ( oldToolBarList.count() != m_toolBars.count() ); + + } + + bool needsRebuild() const { return m_needsRebuild; } + + QPtrList<KAction> create() + { + if ( !m_needsRebuild ) + return QPtrList<KAction>(); + + QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + for ( ; toolBarIt.current(); ++toolBarIt ) + handleToolBar( toolBarIt.current() ); + + QPtrList<KAction> actions; + + if ( m_toolBarActions.count() == 0 ) + return actions; + + if ( m_toolBarActions.count() == 1 ) { + m_toolBarActions.getFirst()->setText( i18n( "Show Toolbar" ) ); + return m_toolBarActions; + } + + KActionMenu *menuAction = new KActionMenu( i18n( "Toolbars" ), m_actionCollection, "toolbars_submenu_action" ); + + QPtrListIterator<KAction> actionIt( m_toolBarActions ); + for ( ; actionIt.current(); ++actionIt ) + menuAction->insert( actionIt.current() ); + + actions.append( menuAction ); + return actions; + } + + const QPtrList<KToolBar> &toolBars() const { return m_toolBars; } + + private: + void handleToolBar( KToolBar *toolBar ) + { + KAction *action = new KToggleToolBarAction( toolBar, + i18n( "Show %1" ).arg( toolBar->label() ), + m_actionCollection, + toolBar->name() ); + + m_toolBarActions.append( action ); + } + + KActionCollection *m_actionCollection; + KMainWindow *m_mainWindow; + + QPtrList<KToolBar> m_toolBars; + QPtrList<KAction> m_toolBarActions; + + bool m_needsRebuild : 1; + }; +} + +using namespace KDEPrivate; + +ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, const char *name ) + : QObject( mainWindow, name ), KXMLGUIClient( mainWindow ) +{ + init( mainWindow ); +} + +ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name ) + : QObject( parent, name ), KXMLGUIClient( mainWindow ) +{ + init( mainWindow ); +} + +ToolBarHandler::~ToolBarHandler() +{ + m_actions.setAutoDelete( true ); + m_actions.clear(); +} + +KAction *ToolBarHandler::toolBarMenuAction() +{ + assert( m_actions.count() == 1 ); + return m_actions.getFirst(); +} + +void ToolBarHandler::setupActions() +{ +//US if ( !factory() || !m_mainWindow ) + if ( !m_mainWindow ) + return; + + BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars ); + + if ( !builder.needsRebuild() ) + return; + + unplugActionList( actionListName ); + + m_actions.setAutoDelete( true ); + + m_actions.clear(); + m_actions.setAutoDelete( false ); + + m_actions = builder.create(); + + /* + for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + toolBarIt.current(); ++toolBarIt ) + toolBarIt.current()->disconnect( this ); + */ + + m_toolBars = builder.toolBars(); + + /* + for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + toolBarIt.current(); ++toolBarIt ) + connect( toolBarIt.current(), SIGNAL( destroyed() ), + this, SLOT( setupActions() ) ); + */ + +//US if (kapp && kapp->authorizeKAction("options_show_toolbar")) + plugActionList( actionListName, m_actions ); + + connectToActionContainers(); +} + +/*US +void ToolBarHandler::clientAdded( KXMLGUIClient *client ) +{ + if ( client == this ) + setupActions(); +} +*/ + +void ToolBarHandler::init( KMainWindow *mainWindow ) +{ + d = 0; + m_mainWindow = mainWindow; + +/*US + connect( m_mainWindow->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ), + this, SLOT( clientAdded( KXMLGUIClient * ) ) ); +*/ + /* re-use an existing resource file if it exists. can happen if the user launches the + * toolbar editor */ + /* + setXMLFile( resourceFileName ); + */ +/*US + if ( domDocument().documentElement().isNull() ) { + + QString completeDescription = QString::fromLatin1( guiDescription ) + .arg( actionListName ); + + setXML( completeDescription, false*/ /*merge*/ /*); + } +*/ +} + +void ToolBarHandler::connectToActionContainers() +{ + QPtrListIterator<KAction> actionIt( m_actions ); + for ( ; actionIt.current(); ++actionIt ) + connectToActionContainer( actionIt.current() ); +} + +void ToolBarHandler::connectToActionContainer( KAction *action ) +{ + uint containerCount = action->containerCount(); + for ( uint i = 0; i < containerCount; ++i ) + connectToActionContainer( action->container( i ) ); +} + +void ToolBarHandler::connectToActionContainer( QWidget *container ) +{ +//US QPopupMenu *popupMenu = dynamic_cast<QPopupMenu *>( container ); + QPopupMenu *popupMenu = (QPopupMenu *)( container ); + if ( !popupMenu ) + return; + + connect( popupMenu, SIGNAL( aboutToShow() ), + this, SLOT( setupActions() ) ); +} + +//US #include "ktoolbarhandler.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/microkde/kdeui/ktoolbarhandler.h b/microkde/kdeui/ktoolbarhandler.h new file mode 100644 index 0000000..a1340ae --- a/dev/null +++ b/microkde/kdeui/ktoolbarhandler.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon Hausmann <hausmann@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KBARHANDLER_H +#define KBARHANDLER_H + +#include <qobject.h> +#include <qguardedptr.h> +#include <qptrlist.h> +#include <kxmlguiclient.h> +#include <kaction.h> + +class KMainWindow; +class KToolBar; + +namespace KDEPrivate +{ + +/// @since 3.1 +class ToolBarHandler : public QObject, public KXMLGUIClient +{ + Q_OBJECT +public: + ToolBarHandler( KMainWindow *mainWindow, const char *name = 0 ); + ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name = 0 ); + virtual ~ToolBarHandler(); + + KAction *toolBarMenuAction(); + +public slots: + void setupActions(); + +private slots: +//US void clientAdded( KXMLGUIClient *client ); + +private: + void init( KMainWindow *mainWindow ); + void connectToActionContainers(); + void connectToActionContainer( KAction *action ); + void connectToActionContainer( QWidget *container ); + + struct Data; + Data *d; + + QGuardedPtr<KMainWindow> m_mainWindow; + QPtrList<KAction> m_actions; + QPtrList<KToolBar> m_toolBars; +}; + +} // namespace KDEPrivate + +#endif // KBARHANDLER_H + +/* vim: et sw=4 ts=4 + */ diff --git a/microkde/kdeui/kxmlguiclient.cpp b/microkde/kdeui/kxmlguiclient.cpp new file mode 100644 index 0000000..073e30b --- a/dev/null +++ b/microkde/kdeui/kxmlguiclient.cpp @@ -0,0 +1,958 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000 Kurt Granroth <granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kxmlguiclient.h" + +/*US +#include "kxmlguifactory.h" +#include "kxmlguibuilder.h" +*/ + +/*US +#include <qdir.h> +#include <qfile.h> +#include <qdom.h> +#include <qtextstream.h> +#include <qregexp.h> +*/ + +//US #include <kinstance.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <kaction.h> +#include <kapplication.h> + +#include <assert.h> + +class KXMLGUIClientPrivate +{ +public: + KXMLGUIClientPrivate() + { +//US m_instance = KGlobal::instance(); +//US m_factory = 0L; + m_parent = 0L; +//US m_builder = 0L; + m_actionCollection = 0; + } + ~KXMLGUIClientPrivate() + { + } + +//US KInstance *m_instance; + +//US QDomDocument m_doc; + KActionCollection *m_actionCollection; +//US QDomDocument m_buildDocument; +//US KXMLGUIFactory *m_factory; + KXMLGUIClient *m_parent; + //QPtrList<KXMLGUIClient> m_supers; + QPtrList<KXMLGUIClient> m_children; +//US KXMLGUIBuilder *m_builder; +//US QString m_xmlFile; +//US QString m_localXMLFile; +}; + +KXMLGUIClient::KXMLGUIClient() +{ + d = new KXMLGUIClientPrivate; +} + +KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent ) +{ + d = new KXMLGUIClientPrivate; + parent->insertChildClient( this ); +} + +KXMLGUIClient::~KXMLGUIClient() +{ + if ( d->m_parent ) + d->m_parent->removeChildClient( this ); + + QPtrListIterator<KXMLGUIClient> it( d->m_children ); + for ( ; it.current(); ++it ) { + assert( it.current()->d->m_parent == this ); + it.current()->d->m_parent = 0; + } + + delete d->m_actionCollection; + delete d; +} + +KAction *KXMLGUIClient::action( const char *name ) const +{ + KAction* act = actionCollection()->action( name ); + if ( !act ) { + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) { + act = childIt.current()->actionCollection()->action( name ); + if ( act ) + break; + } + } + return act; +} + +KActionCollection *KXMLGUIClient::actionCollection() const +{ + if ( !d->m_actionCollection ) + d->m_actionCollection = new KActionCollection( 0, 0, + "KXMLGUILClient-KActionCollection" ); + return d->m_actionCollection; +} + +/*US +KAction *KXMLGUIClient::action( const QDomElement &element ) const +{ + static const QString &attrName = KGlobal::staticQString( "name" ); + return actionCollection()->action( element.attribute( attrName ).latin1() ); +} + +KInstance *KXMLGUIClient::instance() const +{ + return d->m_instance; +} + +QDomDocument KXMLGUIClient::domDocument() const +{ + return d->m_doc; +} + +QString KXMLGUIClient::xmlFile() const +{ + return d->m_xmlFile; +} + +QString KXMLGUIClient::localXMLFile() const +{ + if ( !d->m_localXMLFile.isEmpty() ) + return d->m_localXMLFile; + + if ( d->m_xmlFile[0] == '/' ) + return QString::null; // can't save anything here + + return locateLocal( "data", QString::fromLatin1( instance()->instanceName() + '/' ) + d->m_xmlFile ); +} + + +void KXMLGUIClient::reloadXML() +{ + QString file( xmlFile() ); + if ( !file.isEmpty() ) + setXMLFile( file ); +} + +void KXMLGUIClient::setInstance( KInstance *instance ) +{ + d->m_instance = instance; + actionCollection()->setInstance( instance ); + if ( d->m_builder ) + d->m_builder->setBuilderClient( this ); +} + +void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc ) +{ + // store our xml file name + if ( !_file.isNull() ) { + d->m_xmlFile = _file; + actionCollection()->setXMLFile( _file ); + } + + if ( !setXMLDoc ) + return; + + QString file = _file; + if ( file[0] != '/' ) + { + QString doc; + + QString filter = QString::fromLatin1( instance()->instanceName() + '/' ) + _file; + + QStringList allFiles = instance()->dirs()->findAllResources( "data", filter ) + instance()->dirs()->findAllResources( "data", _file ); + + file = findMostRecentXMLFile( allFiles, doc ); + + if ( file.isEmpty() ) + { + // this might or might not be an error. for the time being, + // let's treat this as if it isn't a problem and the user just + // wants the global standards file + setXML( QString::null, true ); + return; + } + else if ( !doc.isEmpty() ) + { + setXML( doc, merge ); + return; + } + } + + QString xml = KXMLGUIFactory::readConfigFile( file ); + setXML( xml, merge ); +} + +void KXMLGUIClient::setLocalXMLFile( const QString &file ) +{ + d->m_localXMLFile = file; +} + +void KXMLGUIClient::setXML( const QString &document, bool merge ) +{ + QDomDocument doc; + doc.setContent( document ); + setDOMDocument( doc, merge ); +} + +void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge ) +{ + if ( merge ) + { + QDomElement base = d->m_doc.documentElement(); + + QDomElement e = document.documentElement(); + KXMLGUIFactory::removeDOMComments( e ); + + // merge our original (global) xml with our new one + mergeXML(base, e, actionCollection()); + + // reassign our pointer as mergeXML might have done something + // strange to it + base = d->m_doc.documentElement(); + + // we want some sort of failsafe.. just in case + if ( base.isNull() ) + d->m_doc = document; + } + else + { + d->m_doc = document; + KXMLGUIFactory::removeDOMComments( d->m_doc ); + } + + setXMLGUIBuildDocument( QDomDocument() ); +} +*/ + +/*US +bool KXMLGUIClient::mergeXML( QDomElement &base, const QDomElement &additive, KActionCollection *actionCollection ) +{ + static const QString &tagAction = KGlobal::staticQString( "Action" ); + static const QString &tagMerge = KGlobal::staticQString( "Merge" ); + static const QString &tagSeparator = KGlobal::staticQString( "Separator" ); + static const QString &attrName = KGlobal::staticQString( "name" ); + static const QString &attrAppend = KGlobal::staticQString( "append" ); + static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" ); + static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" ); + static const QString &tagText = KGlobal::staticQString( "text" ); + static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" ); + static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); + static const QString &attrOne = KGlobal::staticQString( "1" ); + + // there is a possibility that we don't want to merge in the + // additive.. rather, we might want to *replace* the base with the + // additive. this can be for any container.. either at a file wide + // level or a simple container level. we look for the 'noMerge' + // tag, in any event and just replace the old with the new + if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon) + { + base.parentNode().replaceChild(additive, base); + return true; + } + + QString tag; + + QDomElement e = base.firstChild().toElement(); + // iterate over all elements in the container (of the global DOM tree) + while ( !e.isNull() ) + { + tag = e.tagName(); + + // if there's an action tag in the global tree and the action is + // not implemented, then we remove the element + if ( tag == tagAction ) + { + QCString name = e.attribute( attrName ).utf8(); // WABA + if ( !actionCollection->action( name ) || + (kapp && !kapp->authorizeKAction(name))) + { + // remove this child as we aren't using it + QDomElement oldChild = e; + e = e.nextSibling().toElement(); + base.removeChild( oldChild ); + continue; + } + } + + // if there's a separator defined in the global tree, then add an + // attribute, specifying that this is a "weak" separator + else if ( tag == tagSeparator ) + { + e.setAttribute( attrWeakSeparator, (uint)1 ); + + // okay, hack time. if the last item was a weak separator OR + // this is the first item in a container, then we nuke the + // current one + QDomElement prev = e.previousSibling().toElement(); + if ( prev.isNull() || + ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) || + ( prev.tagName() == tagText ) ) + { + // the previous element was a weak separator or didn't exist + QDomElement oldChild = e; + e = e.nextSibling().toElement(); + base.removeChild( oldChild ); + continue; + } + } + + // the MergeLocal tag lets us specify where non-standard elements + // of the local tree shall be merged in. After inserting the + // elements we delete this element + else if ( tag == tagMergeLocal ) + { + QDomElement currElement = e; + + // switch our iterator "e" to the next sibling, so that we don't + // process the local tree's inserted items! + e = e.nextSibling().toElement(); + + QDomElement it = additive.firstChild().toElement(); + while ( !it.isNull() ) + { + QDomElement newChild = it; + + it = it.nextSibling().toElement(); + + if ( newChild.tagName() == tagText ) + continue; + + if ( newChild.attribute( attrAlreadyVisited ) == attrOne ) + continue; + + QString itAppend( newChild.attribute( attrAppend ) ); + QString elemName( currElement.attribute( attrName ) ); + + if ( ( itAppend.isNull() && elemName.isEmpty() ) || + ( itAppend == elemName ) ) + { + // first, see if this new element matches a standard one in + // the global file. if it does, then we skip it as it will + // be merged in, later + QDomElement matchingElement = findMatchingElement( newChild, base ); + if ( matchingElement.isNull() || newChild.tagName() == tagSeparator ) + base.insertBefore( newChild, currElement ); + } + } + + base.removeChild( currElement ); + continue; + } + + // in this last case we check for a separator tag and, if not, we + // can be sure that its a container --> proceed with child nodes + // recursively and delete the just proceeded container item in + // case its empty (if the recursive call returns true) + else if ( tag != tagMerge ) + { + // handle the text tag + if ( tag == tagText ) + { + e = e.nextSibling().toElement(); + continue; + } + + QDomElement matchingElement = findMatchingElement( e, additive ); + + QDomElement currElement = e; + e = e.nextSibling().toElement(); + + if ( !matchingElement.isNull() ) + { + matchingElement.setAttribute( attrAlreadyVisited, (uint)1 ); + + if ( mergeXML( currElement, matchingElement, actionCollection ) ) + { + base.removeChild( currElement ); + continue; + } + + // Merge attributes + QDomNamedNodeMap attribs = matchingElement.attributes(); + for(uint i = 0; i < attribs.count(); i++) + { + QDomNode node = attribs.item(i); + currElement.setAttribute(node.nodeName(), node.nodeValue()); + } + + continue; + } + else + { + // this is an important case here! We reach this point if the + // "local" tree does not contain a container definition for + // this container. However we have to call mergeXML recursively + // and make it check if there are actions implemented for this + // container. *If* none, then we can remove this container now + if ( mergeXML( currElement, QDomElement(), actionCollection ) ) + base.removeChild( currElement ); + continue; + } + } + + //I think this can be removed ;-) + e = e.nextSibling().toElement(); + } + + //here we append all child elements which were not inserted + //previously via the LocalMerge tag + e = additive.firstChild().toElement(); + while ( !e.isNull() ) + { + QDomElement matchingElement = findMatchingElement( e, base ); + + if ( matchingElement.isNull() ) + { + QDomElement newChild = e; + e = e.nextSibling().toElement(); + base.appendChild( newChild ); + } + else + e = e.nextSibling().toElement(); + } + + // do one quick check to make sure that the last element was not + // a weak separator + QDomElement last = base.lastChild().toElement(); + if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) ) + { + base.removeChild( base.lastChild() ); + } + + // now we check if we are empty (in which case we return "true", to + // indicate the caller that it can delete "us" (the base element + // argument of "this" call) + bool deleteMe = true; + e = base.firstChild().toElement(); + for ( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + tag = e.tagName(); + + if ( tag == tagAction ) + { + // if base contains an implemented action, then we must not get + // deleted (note that the actionCollection contains both, + // "global" and "local" actions + if ( actionCollection->action( e.attribute( attrName ).utf8() ) ) + { + deleteMe = false; + break; + } + } + else if ( tag == tagSeparator ) + { + // if we have a separator which has *not* the weak attribute + // set, then it must be owned by the "local" tree in which case + // we must not get deleted either + QString weakAttr = e.attribute( attrWeakSeparator ); + if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 ) + { + deleteMe = false; + break; + } + } + + // in case of a merge tag we have unlimited lives, too ;-) + else if ( tag == tagMerge ) + { +// deleteMe = false; +// break; + continue; + } + + // a text tag is NOT enough to spare this container + else if ( tag == tagText ) + { + continue; + } + + // what's left are non-empty containers! *don't* delete us in this + // case (at this position we can be *sure* that the container is + // *not* empty, as the recursive call for it was in the first loop + // which deleted the element in case the call returned "true" + else + { + deleteMe = false; + break; + } + } + + return deleteMe; +} + +QDomElement KXMLGUIClient::findMatchingElement( const QDomElement &base, const QDomElement &additive ) +{ + static const QString &tagAction = KGlobal::staticQString( "Action" ); + static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" ); + static const QString &attrName = KGlobal::staticQString( "name" ); + + QDomElement e = additive.firstChild().toElement(); + for ( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + // skip all action and merge tags as we will never use them + if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) ) + { + continue; + } + + // now see if our tags are equivalent + if ( ( e.tagName() == base.tagName() ) && + ( e.attribute( attrName ) == base.attribute( attrName ) ) ) + { + return e; + } + } + + // nope, return a (now) null element + return e; +} + +void KXMLGUIClient::conserveMemory() +{ + d->m_doc = QDomDocument(); + d->m_buildDocument = QDomDocument(); +} + +void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc ) +{ + d->m_buildDocument = doc; +} + +QDomDocument KXMLGUIClient::xmlguiBuildDocument() const +{ + return d->m_buildDocument; +} +*/ + +/*US +void KXMLGUIClient::setFactory( KXMLGUIFactory *factory ) +{ + d->m_factory = factory; +} + +KXMLGUIFactory *KXMLGUIClient::factory() const +{ + return d->m_factory; +} +*/ +KXMLGUIClient *KXMLGUIClient::parentClient() const +{ + return d->m_parent; +} + +void KXMLGUIClient::insertChildClient( KXMLGUIClient *child ) +{ + if ( child->d->m_parent ) + child->d->m_parent->removeChildClient( child ); + d->m_children.append( child ); + child->d->m_parent = this; +} + +void KXMLGUIClient::removeChildClient( KXMLGUIClient *child ) +{ + assert( d->m_children.containsRef( child ) ); + d->m_children.removeRef( child ); + child->d->m_parent = 0; +} + +/*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super ) +{ + if ( d->m_supers.contains( super ) ) + return false; + d->m_supers.append( super ); + return true; +}*/ + +const QPtrList<KXMLGUIClient> *KXMLGUIClient::childClients() +{ + return &d->m_children; +} +/*US +void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder ) +{ + d->m_builder = builder; + if ( builder ) + builder->setBuilderInstance( instance() ); +} + +KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const +{ + return d->m_builder; +} +*/ + +void KXMLGUIClient::plugActionList( const QString &name, const QPtrList<KAction> &actionList ) +{ +/*US + if ( !d->m_factory ) + return; + + d->m_factory->plugActionList( this, name, actionList ); +*/ +} + +void KXMLGUIClient::unplugActionList( const QString &name ) +{ +/*US + if ( !d->m_factory ) + return; + + d->m_factory->unplugActionList( this, name ); +*/ +} + +/*US +QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc ) +{ + + QValueList<DocStruct> allDocuments; + + QStringList::ConstIterator it = files.begin(); + QStringList::ConstIterator end = files.end(); + for (; it != end; ++it ) + { + //kdDebug() << "KXMLGUIClient::findMostRecentXMLFile " << *it << endl; + QString data = KXMLGUIFactory::readConfigFile( *it ); + DocStruct d; + d.file = *it; + d.data = data; + allDocuments.append( d ); + } + + QValueList<DocStruct>::Iterator best = allDocuments.end(); + uint bestVersion = 0; + + QValueList<DocStruct>::Iterator docIt = allDocuments.begin(); + QValueList<DocStruct>::Iterator docEnd = allDocuments.end(); + for (; docIt != docEnd; ++docIt ) + { + QString versionStr = findVersionNumber( (*docIt).data ); + if ( versionStr.isEmpty() ) + continue; + + bool ok = false; + uint version = versionStr.toUInt( &ok ); + if ( !ok ) + continue; + //kdDebug() << "FOUND VERSION " << version << endl; + + if ( version > bestVersion ) + { + best = docIt; + //kdDebug() << "best version is now " << version << endl; + bestVersion = version; + } + } + + if ( best != docEnd ) + { + if ( best != allDocuments.begin() ) + { + QValueList<DocStruct>::Iterator local = allDocuments.begin(); + + // load the local document and extract the action properties + QDomDocument document; + document.setContent( (*local).data ); + + ActionPropertiesMap properties = extractActionProperties( document ); + + // in case the document has a ActionProperties section + // we must not delete it but copy over the global doc + // to the local and insert the ActionProperties section + if ( !properties.isEmpty() ) + { + // now load the global one with the higher version number + // into memory + document.setContent( (*best).data ); + // and store the properties in there + storeActionProperties( document, properties ); + + (*local).data = document.toString(); + // make sure we pick up the new local doc, when we return later + best = local; + + // write out the new version of the local document + QFile f( (*local).file ); + if ( f.open( IO_WriteOnly ) ) + { + QCString utf8data = (*local).data.utf8(); + f.writeBlock( utf8data.data(), utf8data.length() ); + f.close(); + } + } + else + { + QString f = (*local).file; + QString backup = f + QString::fromLatin1( ".backup" ); + QDir dir; + dir.rename( f, backup ); + } + } + doc = (*best).data; + return (*best).file; + } + else if ( files.count() > 0 ) + { + //kdDebug() << "returning first one..." << endl; + doc = (*allDocuments.begin()).data; + return (*allDocuments.begin()).file; + } + + return QString::null; +} + + + +QString KXMLGUIClient::findVersionNumber( const QString &xml ) +{ + enum { ST_START, ST_AFTER_OPEN, ST_AFTER_GUI, + ST_EXPECT_VERSION, ST_VERSION_NUM} state = ST_START; + for (unsigned int pos = 0; pos < xml.length(); pos++) + { + switch (state) + { + case ST_START: + if (xml[pos] == '<') + state = ST_AFTER_OPEN; + break; + case ST_AFTER_OPEN: + { + //Jump to gui.. + int guipos = xml.find("gui", pos, false); + if (guipos == -1) + return QString::null; //Reject + + pos = guipos + 2; //Position at i, so we're moved ahead to the next character by the ++; + state = ST_AFTER_GUI; + break; + } + case ST_AFTER_GUI: + state = ST_EXPECT_VERSION; + break; + case ST_EXPECT_VERSION: + { + int verpos = xml.find("version=\"", pos, false ); + if (verpos == -1) + return QString::null; //Reject + + pos = verpos + 8; //v = 0, e = +1, r = +2, s = +3 , i = +4, o = +5, n = +6, = = +7, " = + 8 + state = ST_VERSION_NUM; + break; + } + case ST_VERSION_NUM: + { + unsigned int endpos; + for (endpos = pos; endpos < xml.length(); endpos++) + { + if (xml[endpos].unicode() >= '0' && xml[endpos].unicode() <= '9') + continue; //Number.. + if (xml[endpos].unicode() == '"') //End of parameter + break; + else //This shouldn't be here.. + { + endpos = xml.length(); + } + } + + if (endpos != pos && endpos < xml.length() ) + { + QString matchCandidate = xml.mid(pos, endpos - pos); //Don't include " ". + return matchCandidate; + } + + state = ST_EXPECT_VERSION; //Try to match a well-formed version.. + break; + } //case.. + } //switch + } //for + + return QString::null; +} + +KXMLGUIClient::ActionPropertiesMap KXMLGUIClient::extractActionProperties( const QDomDocument &doc ) +{ + ActionPropertiesMap properties; + + QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement(); + + if ( actionPropElement.isNull() ) + return properties; + + QDomNode n = actionPropElement.firstChild(); + for (; !n.isNull(); n = n.nextSibling() ) + { + QDomElement e = n.toElement(); + if ( e.isNull() ) + continue; + + if ( e.tagName().lower() != "action" ) + continue; + + QString actionName = e.attribute( "name" ); + + if ( actionName.isEmpty() ) + continue; + + QMap<QString, QMap<QString, QString> >::Iterator propIt = properties.find( actionName ); + if ( propIt == properties.end() ) + propIt = properties.insert( actionName, QMap<QString, QString>() ); + + QDomNamedNodeMap attributes = e.attributes(); + for ( uint i = 0; i < attributes.length(); ++i ) + { + QDomAttr attr = attributes.item( i ).toAttr(); + + if ( attr.isNull() ) + continue; + + QString name = attr.name(); + + if ( name == "name" || name.isEmpty() ) + continue; + + (*propIt)[ name ] = attr.value(); + } + + } + + return properties; +} + +void KXMLGUIClient::storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties ) +{ + QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement(); + + if ( actionPropElement.isNull() ) + { + actionPropElement = doc.createElement( "ActionProperties" ); + doc.documentElement().appendChild( actionPropElement ); + } + + while ( !actionPropElement.firstChild().isNull() ) + actionPropElement.removeChild( actionPropElement.firstChild() ); + + ActionPropertiesMap::ConstIterator it = properties.begin(); + ActionPropertiesMap::ConstIterator end = properties.end(); + for (; it != end; ++it ) + { + QDomElement action = doc.createElement( "Action" ); + action.setAttribute( "name", it.key() ); + actionPropElement.appendChild( action ); + + QMap<QString, QString> attributes = (*it); + QMap<QString, QString>::ConstIterator attrIt = attributes.begin(); + QMap<QString, QString>::ConstIterator attrEnd = attributes.end(); + for (; attrIt != attrEnd; ++attrIt ) + action.setAttribute( attrIt.key(), attrIt.data() ); + } +} +*/ + +void KXMLGUIClient::addStateActionEnabled(const QString& state, + const QString& action) +{ + StateChange stateChange = getActionsToChangeForState(state); + + stateChange.actionsToEnable.append( action ); + //kdDebug() << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")" << endl; + + m_actionsStateMap.replace( state, stateChange ); +} + + +void KXMLGUIClient::addStateActionDisabled(const QString& state, + const QString& action) +{ + StateChange stateChange = getActionsToChangeForState(state); + + stateChange.actionsToDisable.append( action ); + //kdDebug() << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")" << endl; + + m_actionsStateMap.replace( state, stateChange ); +} + + +KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state) +{ + return m_actionsStateMap[state]; +} + + +void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse) +{ + StateChange stateChange = getActionsToChangeForState(newstate); + + bool setTrue = (reverse == StateNoReverse); + bool setFalse = !setTrue; + + // Enable actions which need to be enabled... + // + for ( QStringList::Iterator it = stateChange.actionsToEnable.begin(); + it != stateChange.actionsToEnable.end(); ++it ) { + + KAction *action = actionCollection()->action((*it).latin1()); + if (action) action->setEnabled(setTrue); + } + + // and disable actions which need to be disabled... + // + for ( QStringList::Iterator it = stateChange.actionsToDisable.begin(); + it != stateChange.actionsToDisable.end(); ++it ) { + + KAction *action = actionCollection()->action((*it).latin1()); + if (action) action->setEnabled(setFalse); + } + +} +/*US +void KXMLGUIClient::beginXMLPlug( QWidget *w ) +{ + actionCollection()->beginXMLPlug( w ); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->beginXMLPlug( w ); +} + +void KXMLGUIClient::endXMLPlug() +{ + actionCollection()->endXMLPlug(); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->endXMLPlug(); +} + +void KXMLGUIClient::prepareXMLUnplug( QWidget * ) +{ + actionCollection()->prepareXMLUnplug(); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->prepareXMLUnplug(); +} +*/ +void KXMLGUIClient::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } diff --git a/microkde/kdeui/kxmlguiclient.h b/microkde/kdeui/kxmlguiclient.h new file mode 100644 index 0000000..cd74c8e --- a/dev/null +++ b/microkde/kdeui/kxmlguiclient.h @@ -0,0 +1,361 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000 Kurt Granroth <granroth@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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KXMLGUICLIENT_H +#define _KXMLGUICLIENT_H + + +//US #include <qdom.h> +#include <qptrlist.h> +#include <qmap.h> +#include <qstringlist.h> + +class QWidget; +class KAction; +class KActionCollection; +class KInstance; + +class KXMLGUIClientPrivate; +class KXMLGUIFactory; +class KXMLGUIBuilder; + +/** + * + * A KXMLGUIClient can be used with @ref KXMLGUIFactory to create a + * GUI from actions and an XML document, and can be dynamically merged + * with other KXMLGUIClients. + */ +class KXMLGUIClient +{ + friend class KEditToolbarWidget; // for setXMLFile(3 args) +public: + /** + * Constructs a KXMLGUIClient which can be used with a + * @ref KXMLGUIFactory to create a GUI from actions and an XML document, and + * which can be dynamically merged with other KXMLGUIClients. + */ + KXMLGUIClient(); + + /** + * Constructs a KXMLGUIClient which can be used with a @ref KXMLGUIFactory + * to create a GUI from actions and an XML document, + * and which can be dynamically merged with other KXMLGUIClients. + * + * This constructor takes an additional @p parent argument, which makes + * the client a child client of the parent. + * + * Child clients are automatically added to the GUI if the parent is added. + * + */ + KXMLGUIClient( KXMLGUIClient *parent ); + + /** + * Destructs the KXMLGUIClient. + */ + virtual ~KXMLGUIClient(); + + /** + * Retrieves an action of the client by name. If not found, it looks in its child clients. + * This method is provided for convenience, as it uses @ref #actionCollection() + * to get the action object. + */ + KAction* action( const char* name ) const; + + /** + * Retrieves an action for a given @ref QDomElement. The default + * implementation uses the "name" attribute to query the action + * object via the other action() method. + */ +//US virtual KAction *action( const QDomElement &element ) const; + + /** + * Retrieves the entire action collection for the GUI client + */ + virtual KActionCollection* actionCollection() const; + + /** + * @return The instance (@ref KInstance) for this part. + */ +//US virtual KInstance *instance() const; + + /** + * @return The parsed XML in a @ref QDomDocument, set by @ref + * setXMLFile() or @ref setXML(). + * This document describes the layout of the GUI. + */ +//US virtual QDomDocument domDocument() const; + + /** + * This will return the name of the XML file as set by @ref #setXMLFile(). + * If @ref #setXML() is used directly, then this will return NULL. + * + * The filename that this returns is obvious for components as each + * component has exactly one XML file. In non-components, however, + * there are usually two: the global file and the local file. This + * function doesn't really care about that, though. It will always + * return the last XML file set. This, in almost all cases, will + * be the local XML file. + * + * @return The name of the XML file or QString::null + */ +//US virtual QString xmlFile() const; + +//US virtual QString localXMLFile() const; + + /** + * @internal + */ +//US void setXMLGUIBuildDocument( const QDomDocument &doc ); + /** + * @internal + */ +//US QDomDocument xmlguiBuildDocument() const; + + /** + * This method is called by the @ref KXMLGUIFactory as soon as the client + * is added to the KXMLGUIFactory's GUI. + */ +//US void setFactory( KXMLGUIFactory *factory ); + /** + * Retrieves a pointer to the @ref KXMLGUIFactory this client is + * associated with (will return 0L if the client's GUI has not been built + * by a KXMLGUIFactory. + */ +//US KXMLGUIFactory *factory() const; + + /** + * KXMLGUIClients can form a simple child/parent object tree. This + * method returns a pointer to the parent client or 0L if it has no + * parent client assigned. + */ + KXMLGUIClient *parentClient() const; + + /** + * Use this method to make a client a child client of another client. + * Usually you don't need to call this method, as it is called + * automatically when using the second constructor, which takes a + * arent argument. + */ + void insertChildClient( KXMLGUIClient *child ); + + /** + * Removes the given @p child from the client's children list. + */ + void removeChildClient( KXMLGUIClient *child ); + + /** + * Retrieves a list of all child clients. + */ + const QPtrList<KXMLGUIClient> *childClients(); + + /** + * A client can have an own @ref KXMLGUIBuilder. + * Use this method to assign your builder instance to the client (so that the + * @ref KXMLGUIFactory can use it when building the client's GUI) + * + * Client specific guibuilders are useful if you want to create + * custom container widgets for your GUI. + */ +//US void setClientBuilder( KXMLGUIBuilder *builder ); + + /** + * Retrieves the client's GUI builder or 0L if no client specific + * builder has been assigned via @ref #setClientBuilder() + */ +//US KXMLGUIBuilder *clientBuilder() const; + + /** + * Forces this client to re-read its XML resource file. This is + * intended to be used when you know that the resource file has + * changed and you will soon be rebuilding the GUI. It has no + * useful effect with non-KParts GUIs, so don't bother using it + * unless your app is component based. + */ +//US void reloadXML(); + + /** + * ActionLists are a way for XMLGUI to support dynamic lists of + * actions. E.g. if you are writing a file manager, and there is a + * menu file whose contents depend on the mimetype of the file that + * is selected, then you can achieve this using ActionLists. It + * works as follows: + * In your xxxui.rc file ( the one that you set in @ref setXMLFile() + * ), you put an <ActionList name="xxx"> tag. E.g. + * \verbatim + * <kpartgui name="xxx_part" version="1"> + * <MenuBar> + * <Menu name="file"> + * ... <!-- some useful actions--> + * <ActionList name="xxx_file_actionlist" /> + * ... <!-- even more useful actions--> + * </Menu> + * ... + * </MenuBar> + * </kpartgui> + * \endverbatim + * + * This tag will get expanded to a list of actions. In the example + * above ( a file manager with a dynamic file menu ), you would call + * \code + * QPtrList<KAction> file_actions; + * for( ... ) + * if( ... ) + * file_actions.append( cool_action ); + * unplugActionList( "xxx_file_actionlist" ); + * plugActionList( "xxx_file_actionlist", file_actions ); + * \endcode + * every time a file is selected, unselected or ... + * + * \note You should not call createGUI() after calling this + * function. In fact, that would remove the newly added + * actionlists again... + * \note Forgetting to call unplugActionList() before + * plugActionList() would leave the previous actions in the + * menu too.. + */ + void plugActionList( const QString &name, const QPtrList<KAction> &actionList ); + + /** + * The complement of \ref plugActionList() ... + */ + void unplugActionList( const QString &name ); + +//US static QString findMostRecentXMLFile( const QStringList &files, QString &doc ); + + void addStateActionEnabled(const QString& state, const QString& action); + + void addStateActionDisabled(const QString& state, const QString& action); + + enum ReverseStateChange { StateNoReverse, StateReverse }; + struct StateChange + { + QStringList actionsToEnable; + QStringList actionsToDisable; + }; + + StateChange getActionsToChangeForState(const QString& state); + + /// @since 3.1 +//US void beginXMLPlug( QWidget * ); + /// @since 3.1 +//US void endXMLPlug(); + /// @since 3.1 +//US void prepareXMLUnplug( QWidget * ); + +protected: + /** + * Returns true if client was added to super client list. + * Returns false if client was already in list. + */ + //bool addSuperClient( KXMLGUIClient * ); + + /** + * Sets the instance (@ref KInstance) for this part. + * + * Call this first in the inherited class constructor. + * (At least before @ref setXMLFile().) + */ +//US virtual void setInstance( KInstance *instance ); + + /** + * Sets the name of the rc file containing the XML for the part. + * + * Call this in the Part-inherited class constructor. + * + * @param file Either an absolute path for the file, or simply the + * filename, which will then be assumed to be installed + * in the "data" resource, under a directory named like + * the instance. + * @param setXML Specify whether to call setXML. Default is true. + * and the DOM document at once. + **/ +//US virtual void setXMLFile( const QString& file, bool merge = false, bool setXMLDoc = true ); + +//US virtual void setLocalXMLFile( const QString &file ); + + /** + * Sets the XML for the part. + * + * Call this in the Part-inherited class constructor if you + * don't call @ref setXMLFile(). + **/ +//US virtual void setXML( const QString &document, bool merge = false ); + + /** + * Sets the Document for the part, describing the layout of the GUI. + * + * Call this in the Part-inherited class constructor if you don't call + * @ref setXMLFile or @ref setXML . + */ +//US virtual void setDOMDocument( const QDomDocument &document, bool merge = false ); + + /** + * This function will attempt to give up some memory after the GUI + * is built. It should never be used in apps where the GUI may be + * rebuilt at some later time (components, for instance). + */ +//US virtual void conserveMemory(); + + /** + * Actions can collectively be assigned a "State". To accomplish this + * the respective actions are tagged as <enable> or <disable> in + * a <State> </State> group of the XMLfile. During program execution the + * programmer can call stateChanged() to set actions to a defined state. + * + * @param newstate Name of a State in the XMLfile. + * @param reverse If the flag reverse is set to StateReverse, the State is reversed. + * (actions to be enabled will be disabled and action to be disabled will be enabled) + * Default is reverse=false. + */ + virtual void stateChanged(const QString &newstate, ReverseStateChange reverse = StateNoReverse); + + // Use this one for KDE 4.0 + //virtual void stateChanged(const QString &newstate, bool reverse = false); + +private: +/*US + struct DocStruct + { + QString file; + QString data; + }; + + bool mergeXML( QDomElement &base, const QDomElement &additive, + KActionCollection *actionCollection ); + + QDomElement findMatchingElement( const QDomElement &base, + const QDomElement &additive ); +*/ + typedef QMap<QString, QMap<QString, QString> > ActionPropertiesMap; + +//US static ActionPropertiesMap extractActionProperties( const QDomDocument &doc ); + +//US static void storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties ); + +//US static QString findVersionNumber( const QString &_xml ); + + // Actions to enable/disable on a state change + QMap<QString,StateChange> m_actionsStateMap; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KXMLGUIClientPrivate *d; +}; + +#endif |