diff options
Diffstat (limited to 'koshell/iconsidepane.cpp')
-rw-r--r-- | koshell/iconsidepane.cpp | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/koshell/iconsidepane.cpp b/koshell/iconsidepane.cpp new file mode 100644 index 00000000..8698f9a0 --- /dev/null +++ b/koshell/iconsidepane.cpp @@ -0,0 +1,595 @@ +/* + This file is part of KDE KOffice project. + + Copyright (C) 2003 Cornelius Schumacher <[email protected]> + Copyright (C) 2005 Fredrik Edemar <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <qbitmap.h> +#include <qcursor.h> +#include <qdrawutil.h> +#include <qfontmetrics.h> +#include <qframe.h> +#include <qlabel.h> +#include <qobjectlist.h> +#include <qpainter.h> +#include <qptrlist.h> +#include <qstyle.h> +#include <qtooltip.h> +#include <qwidgetstack.h> + + +#include <kapplication.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kpushbutton.h> + +#include "iconsidepane.h" + +EntryItem::EntryItem( Navigator *parent, int _id, const QString &_text, const QString & _pix ) + : QListBoxItem( parent ), + mPixmapName(_pix), + mId(_id), + mHasHover( false ), + mPaintActive( false ) +{ + reloadPixmap(); + setCustomHighlighting( true ); + setText( _text ); +} + +EntryItem::~EntryItem() +{ +} + +void EntryItem::setNewText(const QString &_text) +{ + setText( _text ); +} + +void EntryItem::reloadPixmap() +{ + int size = (int)navigator()->viewMode(); + if ( size != 0 ) + mPixmap = KGlobal::iconLoader()->loadIcon( mPixmapName, KIcon::Desktop, size ); + else + mPixmap = QPixmap(); +} + +Navigator* EntryItem::navigator() const +{ + return static_cast<Navigator*>( listBox() ); +} + +int EntryItem::width( const QListBox *listbox ) const +{ + int w = 0; + if( navigator()->showIcons() ) { + w = navigator()->viewMode(); + if ( navigator()->viewMode() == SmallIcons ) + w += 4; + } + if( navigator()->showText() ) { + if ( navigator()->viewMode() == SmallIcons ) + w += listbox->fontMetrics().width( text() ); + else + w = QMAX( w, listbox->fontMetrics().width( text() ) ); + } + return w + ( KDialog::marginHint() * 2 ); +} + +int EntryItem::height( const QListBox *listbox ) const +{ + int h = 0; + if ( navigator()->showIcons() ) + h = (int)navigator()->viewMode() + 4; + if ( navigator()->showText() ) { + if ( navigator()->viewMode() == SmallIcons || !navigator()->showIcons() ) + h = QMAX( h, listbox->fontMetrics().lineSpacing() ) + KDialog::spacingHint() * 2; + else + h = (int)navigator()->viewMode() + listbox->fontMetrics().lineSpacing() + 4; + } + return h; +} + +void EntryItem::paint( QPainter *p ) +{ + reloadPixmap(); + + QListBox *box = listBox(); + bool iconAboveText = ( navigator()->viewMode() > SmallIcons ) + && navigator()->showIcons(); + int w = box->viewport()->width(); + int y = 2; + + // draw selected + if ( isCurrent() || isSelected() || mHasHover || mPaintActive ) { + int h = height( box ); + + QBrush brush; + if ( isCurrent() || isSelected() || mPaintActive ) + brush = box->colorGroup().brush( QColorGroup::Highlight ); + else + brush = box->colorGroup().highlight().light( 115 ); + p->fillRect( 1, 0, w - 2, h - 1, brush ); + QPen pen = p->pen(); + QPen oldPen = pen; + pen.setColor( box->colorGroup().mid() ); + p->setPen( pen ); + + p->drawPoint( 1, 0 ); + p->drawPoint( 1, h - 2 ); + p->drawPoint( w - 2, 0 ); + p->drawPoint( w - 2, h - 2 ); + + p->setPen( oldPen ); + } + + if ( !mPixmap.isNull() && navigator()->showIcons() ) { + int x = iconAboveText ? ( ( w - mPixmap.width() ) / 2 ) : + KDialog::marginHint(); + p->drawPixmap( x, y, mPixmap ); + } + + QColor shadowColor = listBox()->colorGroup().background().dark(115); + if ( isCurrent() || isSelected() ) { + p->setPen( box->colorGroup().highlightedText() ); + } + + if ( !text().isEmpty() && navigator()->showText() ) { + QFontMetrics fm = p->fontMetrics(); + + int x = 0; + if ( iconAboveText ) { + x = ( w - fm.width( text() ) ) / 2; + y += fm.height() - fm.descent(); + if ( navigator()->showIcons() ) + y += mPixmap.height(); + } else { + x = KDialog::marginHint() + 4; + if( navigator()->showIcons() ) { + x += mPixmap.width(); + } + + if ( !navigator()->showIcons() || mPixmap.height() < fm.height() ) + y += fm.ascent() + fm.leading()/2; + else + y += mPixmap.height()/2 - fm.height()/2 + fm.ascent(); + } + + if ( isCurrent() || isSelected() || mHasHover ) { + p->setPen( box->colorGroup().highlight().dark(115) ); + p->drawText( x + ( QApplication::reverseLayout() ? -1 : 1), + y + 1, text() ); + p->setPen( box->colorGroup().highlightedText() ); + } + else + p->setPen( box->colorGroup().text() ); + + p->drawText( x, y, text() ); + } + + // ensure that we don't have a stale flag around + if ( isCurrent() || isSelected() ) mHasHover = false; +} + +void EntryItem::setHover( bool hasHover ) +{ + mHasHover = hasHover; +} + +void EntryItem::setPaintActive( bool paintActive ) +{ + mPaintActive = paintActive; +} + +// ************************************************ + +Navigator::Navigator(bool _selectable, KPopupMenu * menu, IconSidePane *_iconsidepane, QWidget *parent, const char *name ) + : KListBox( parent, name ), mSidePane( _iconsidepane ), mPopupMenu( menu ) +{ + setSelectionMode( KListBox::Single ); + viewport()->setBackgroundMode( PaletteBackground ); + setFrameStyle( QFrame::NoFrame ); + setHScrollBarMode( QScrollView::AlwaysOff ); + //setAcceptDrops( true ); + mMinWidth = 0; + mSelectable = _selectable; + executedItem = 0; + mMouseOn = 0; + + setFocusPolicy( NoFocus ); + + connect( this, SIGNAL( clicked( QListBoxItem* ) ), + SLOT( slotExecuted( QListBoxItem* ) ) ); + connect( this, SIGNAL( onItem( QListBoxItem * ) ), + SLOT( slotMouseOn( QListBoxItem * ) ) ); + connect( this, SIGNAL( onViewport() ), SLOT( slotMouseOff() ) ); + + QToolTip::remove( this ); + if ( !mSidePane->showText() ) + new EntryItemToolTip( this ); +} + +IconViewMode Navigator::viewMode() +{ + return mSidePane->viewMode(); +} + +bool Navigator::showText() +{ + return mSidePane->showText(); +} + +bool Navigator::showIcons() +{ + return mSidePane->showIcons(); +} + +void Navigator::mouseReleaseEvent(QMouseEvent *e) +{ + KListBox::mouseReleaseEvent(e); + if ( e->button() != LeftButton || !mLeftMouseButtonPressed ) + return; + if ( itemAt( e->pos() ) && executedItem == selectedItem() ) + emit itemSelected( currentItem() ); + if ( !mSelectable ) + clearSelection(); +} + +void Navigator::mousePressEvent(QMouseEvent *e) +{ + if ( e->button() != LeftButton || itemAt( e->pos() ) == 0 ) + { + mLeftMouseButtonPressed = false; + if (e->button() == RightButton) + slotShowRMBMenu( 0,mapToGlobal( e->pos() ) ); + return; + } + else + mLeftMouseButtonPressed = true; + KListBox::mousePressEvent(e); +} + +void Navigator::enterEvent( QEvent *event ) +{ + // work around Qt behaviour: onItem is not emmitted in enterEvent() + KListBox::enterEvent( event ); + emit onItem( itemAt( mapFromGlobal( QCursor::pos() ) ) ); +} + +void Navigator::slotExecuted( QListBoxItem *item ) +{ + if ( !item ) + return; + executedItem = item; +} + +QSize Navigator::sizeHint() const +{ + return QSize( mMinWidth, 100 ); +} + +void Navigator::calculateMinWidth() +{ + mMinWidth = mSidePane->minWidth(); + + for (EntryItem *item = static_cast<EntryItem *>(firstItem()) ; item; item = static_cast<EntryItem *>(item->next())) + { + if (item->width( this ) > mMinWidth) + mMinWidth = item->width( this ); + } + //kdDebug() << "minWidth:" << mMinWidth << endl; + parentWidget()->setFixedWidth( mMinWidth ); + triggerUpdate(true); +} + +int Navigator::insertItem(const QString &_text, const QString & _pix) +{ + EntryItem *item = new EntryItem( this, count(), _text, _pix ); + if (item->width( this ) > mSidePane->minWidth() ) + { + mMinWidth = item->width( this ); + parentWidget()->setMinimumWidth( mMinWidth ); + //kdDebug() << "minWidth:" << mMinWidth << endl; + } + return item->id(); +} + +void Navigator::setHoverItem( QListBoxItem* item, bool hover ) +{ + static_cast<EntryItem*>( item )->setHover( hover ); + updateItem( item ); +} + +void Navigator::setPaintActiveItem( QListBoxItem* item, bool paintActive ) +{ + static_cast<EntryItem*>( item )->setPaintActive( paintActive ); + updateItem( item ); +} + +void Navigator::slotMouseOn( QListBoxItem* newItem ) +{ + QListBoxItem* oldItem = mMouseOn; + if ( oldItem == newItem ) + return; + + if ( oldItem && !oldItem->isCurrent() && !oldItem->isSelected() ) + setHoverItem( oldItem, false ); + + if ( newItem && !newItem->isCurrent() && !newItem->isSelected() ) + setHoverItem( newItem, true ); + mMouseOn = newItem; +} + +void Navigator::slotMouseOff() +{ + slotMouseOn( 0 ); +} + +void Navigator::resizeEvent( QResizeEvent *event ) +{ + QListBox::resizeEvent( event ); + triggerUpdate( true ); +} + +void Navigator::slotShowRMBMenu( QListBoxItem *, const QPoint &pos ) +{ + int choice = mPopupMenu->exec( pos ); + + if ( choice == -1 ) + return; + + mSidePane->resetWidth(); + if ( choice >= SmallIcons ) { + mSidePane->setViewMode( mSidePane->sizeIntToEnum( choice ) ); + mPopupMenu->setItemChecked( (int)SmallIcons, false); + mPopupMenu->setItemChecked( (int)NormalIcons, false); + mPopupMenu->setItemChecked( (int)LargeIcons, false); + mPopupMenu->setItemChecked( mSidePane->viewMode(), true); + KoShellSettings::setSidePaneIconSize( choice ); + } + else + { + // either icons or text were toggled + if ( choice == ShowIcons ) { + mSidePane->toogleIcons(); + mPopupMenu->setItemChecked( (int)ShowIcons, mSidePane->showIcons() ); + mPopupMenu->setItemEnabled( (int)ShowText, mSidePane->showIcons() ); + mPopupMenu->setItemEnabled( (int)SmallIcons, mSidePane->showIcons()); + mPopupMenu->setItemEnabled( (int)NormalIcons, mSidePane->showIcons()); + mPopupMenu->setItemEnabled( (int)LargeIcons, mSidePane->showIcons()); + KoShellSettings::setSidePaneShowIcons( mSidePane->showIcons() ); + + QToolTip::remove( this ); + } else { + mSidePane->toogleText(); + mSidePane->resetWidth(); + mPopupMenu->setItemChecked( (int)ShowText, mSidePane->showText() ); + mPopupMenu->setItemEnabled( (int)ShowIcons, mSidePane->showText() ); + mPopupMenu->setItemEnabled( (int)SmallIcons, true); + mPopupMenu->setItemEnabled( (int)NormalIcons, true); + mPopupMenu->setItemEnabled( (int)LargeIcons, true); + KoShellSettings::setSidePaneShowText( mSidePane->showText() ); + new EntryItemToolTip( this ); +// if ( !mSidePane->showText() ) +// mSidePane->buttonGroup()->hide(); +// else +// mSidePane->buttonGroup()->show(); + } + } + calculateMinWidth(); + emit updateAllWidgets(); +} + +// ************************************************ + +IconSidePane::IconSidePane(QWidget *parent, const char *name ) + : QVBox( parent, name ) +{ + m_buttongroup = new QButtonGroup(1, QGroupBox::Horizontal, this); + m_buttongroup->setExclusive(true); + m_buttongroup->hide(); + mWidgetstack = new QWidgetStack(this); + mWidgetstack->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + + // setup the popup menu + mShowIcons = KoShellSettings::sidePaneShowIcons(); + mShowText = KoShellSettings::sidePaneShowText(); + mViewMode = sizeIntToEnum( KoShellSettings::sidePaneIconSize() ); + mPopupMenu = new KPopupMenu(0); + mPopupMenu->insertTitle( i18n( "Icon Size" ) ); + mPopupMenu->insertItem( i18n( "Large" ), (int)LargeIcons ); + mPopupMenu->setItemEnabled( (int)LargeIcons, mShowIcons ); + mPopupMenu->insertItem( i18n( "Normal" ), (int)NormalIcons ); + mPopupMenu->setItemEnabled( (int)NormalIcons, mShowIcons ); + mPopupMenu->insertItem( i18n( "Small" ), (int)SmallIcons ); + mPopupMenu->setItemEnabled( (int)SmallIcons, mShowIcons ); + mPopupMenu->setItemChecked( (int)mViewMode, true ); + mPopupMenu->insertSeparator(); + mPopupMenu->insertItem( i18n( "Show Icons" ), (int)ShowIcons ); + mPopupMenu->setItemChecked( (int)ShowIcons, mShowIcons ); + mPopupMenu->setItemEnabled( (int)ShowIcons, mShowText ); + mPopupMenu->insertItem( i18n( "Show Text" ), (int)ShowText ); + mPopupMenu->setItemChecked( (int)ShowText, mShowText ); + mPopupMenu->setItemEnabled( (int)ShowText, mShowIcons ); + if ( !mShowText ) + m_buttongroup->hide(); +} + +IconSidePane::~IconSidePane() +{ +} + +int IconSidePane::insertItem(int _grp, const QString & _pix, const QString &_text) +{ + return static_cast<Navigator*>( mWidgetstack->widget(_grp))->insertItem( _text, _pix ); +} + +int IconSidePane::insertItem(const QString & _pix, const QString &_text) +{ + return mCurrentNavigator->insertItem(_text, _pix); +} + +void IconSidePane::renameItem( int _grp, int _id, const QString & _text ) +{ + Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp)); + if (!navigator) + return; + EntryItem *item = 0; + for (uint i=0; i< navigator->count(); i++) + { + item = static_cast<EntryItem *>(navigator->item(i)); + if (_id == item->id()) + { + item->setNewText(_text); + navigator->triggerUpdate(false); + break; + } + } +} + +void IconSidePane::removeItem( int _grp, int _id ) +{ + Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp)); + if (!navigator) + return; + for (uint i=0; i< navigator->count(); i++) + { + if (_id == static_cast<EntryItem *>(navigator->item(i))->id()) + { + navigator->removeItem(i); + break; + } + } +} + +int IconSidePane::insertGroup(const QString &_text, bool _selectable, QObject *_obj, const char *_slot) +{ + mCurrentNavigator = new Navigator(_selectable, mPopupMenu, this, mWidgetstack ); + //connect( mCurrentNavigator, SIGNAL( itemSelected( int ) ), this, SLOT( itemSelected( int ) ) ); + if ( _obj != 0L && _slot != 0L ) + connect( mCurrentNavigator, SIGNAL( itemSelected(int ) ), _obj, _slot ); + connect( mCurrentNavigator, SIGNAL( updateAllWidgets() ), this, SLOT(updateAllWidgets()) ); + int const id = mWidgetstack->addWidget(mCurrentNavigator); + mWidgetStackIds.append( id ); + KPushButton *b = new KPushButton( _text, m_buttongroup ); + m_buttongroup->insert( b, id ); + connect( b, SIGNAL( clicked() ), this, SLOT( buttonClicked() ) ); + b->setToggleButton( true ); + b->setFocusPolicy( NoFocus ); + if (m_buttongroup->count()==1) + { + mCurrentNavigator->calculateMinWidth(); + m_buttongroup->setButton(m_buttongroup->id(b)); + mWidgetstack->raiseWidget(id); + } + if ( b->width() > minimumWidth() ) + setMinimumWidth( b->width() ); + return id; +} + +void IconSidePane::buttonClicked() +{ + mWidgetstack->raiseWidget( m_buttongroup->selectedId() ); +} + +void IconSidePane::selectGroup(int group_id) +{ + mWidgetstack->raiseWidget(group_id); +} + +void IconSidePane::itemSelected(int item) +{ + kdDebug() << "Item selected:" << item << endl; +} + +Navigator * IconSidePane::group(int _grp) +{ + return static_cast<Navigator*>(mWidgetstack->widget(_grp)); +} + +void IconSidePane::updateAllWidgets() +{ + QValueList<int>::iterator it; + for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it ) + static_cast<Navigator*>(mWidgetstack->widget(*it))->triggerUpdate( true ); +} + +int IconSidePane::minWidth() +{ + int width = 0; + QValueList<int>::iterator it; + Navigator *n; + for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it ) + { + n = static_cast<Navigator*>(mWidgetstack->widget(*it)); + if ( n->minWidth() > width ) + width = n->minWidth(); + } + return width; +} + +void IconSidePane::resetWidth() +{ + QValueList<int>::iterator it; + Navigator *n; + for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it ) + { + n = static_cast<Navigator*>(mWidgetstack->widget(*it)); + n->resetWidth(); + n->triggerUpdate(true); + } +} + +IconViewMode IconSidePane::sizeIntToEnum(int size) const +{ + switch ( size ) { + case int(LargeIcons): + return LargeIcons; + break; + case int(NormalIcons): + return NormalIcons; + break; + case int(SmallIcons): + return SmallIcons; + break; + default: + // Stick with sane values + return NormalIcons; + kdDebug() << "View mode not implemented!" << endl; + break; + } +} + +void IconSidePane::setActionCollection( KActionCollection *actionCollection ) +{ + mActionCollection = actionCollection; +} + +KActionCollection *IconSidePane::actionCollection() const +{ + return mActionCollection; +} + +#include "iconsidepane.moc" + +// vim: sw=2 sts=2 et tw=80 |