koshell

iconsidepane.cpp

00001 /*
00002   This file is part of KDE KOffice project.
00003 
00004   Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
00005   Copyright (C) 2005 Fredrik Edemar <f_edemar@linux.se>
00006 
00007   This program is free software; you can redistribute it and/or
00008   modify it under the terms of the GNU General Public
00009   License as published by the Free Software Foundation; either
00010   version 2 of the License, or (at your option) any later version.
00011 
00012   This program is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with this program; see the file COPYING.  If not, write to
00019   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #include <qbitmap.h>
00024 #include <qcursor.h>
00025 #include <qdrawutil.h>
00026 #include <qfontmetrics.h>
00027 #include <qframe.h>
00028 #include <qlabel.h>
00029 #include <qobjectlist.h>
00030 #include <qpainter.h>
00031 #include <qptrlist.h>
00032 #include <qstyle.h>
00033 #include <qtooltip.h>
00034 #include <qwidgetstack.h>
00035 
00036 
00037 #include <kapplication.h>
00038 #include <kdebug.h>
00039 #include <kdialog.h>
00040 #include <kiconloader.h>
00041 #include <klocale.h>
00042 #include <kpopupmenu.h>
00043 #include <kpushbutton.h>
00044 
00045 #include "iconsidepane.h"
00046 
00047 EntryItem::EntryItem( Navigator *parent, int _id, const QString &_text, const QString & _pix )
00048   : QListBoxItem( parent ),
00049     mPixmapName(_pix),
00050     mId(_id),
00051     mHasHover( false ),
00052     mPaintActive( false )
00053 {
00054   reloadPixmap();
00055   setCustomHighlighting( true );
00056   setText( _text  );
00057 }
00058 
00059 EntryItem::~EntryItem()
00060 {
00061 }
00062 
00063 void EntryItem::setNewText(const QString &_text)
00064 {
00065     setText( _text );
00066 }
00067 
00068 void EntryItem::reloadPixmap()
00069 {
00070   int size = (int)navigator()->viewMode();
00071   if ( size != 0 )
00072     mPixmap = KGlobal::iconLoader()->loadIcon( mPixmapName, KIcon::Desktop, size );
00073   else
00074     mPixmap = QPixmap();
00075 }
00076 
00077 Navigator* EntryItem::navigator() const
00078 {
00079   return static_cast<Navigator*>( listBox() );
00080 }
00081 
00082 int EntryItem::width( const QListBox *listbox ) const
00083 {
00084   int w = 0;
00085   if( navigator()->showIcons() ) {
00086     w = navigator()->viewMode();
00087     if ( navigator()->viewMode() == SmallIcons )
00088       w += 4;
00089   }
00090   if( navigator()->showText() ) {
00091     if ( navigator()->viewMode() == SmallIcons )
00092       w += listbox->fontMetrics().width( text() );
00093     else
00094       w = QMAX( w, listbox->fontMetrics().width( text() ) );
00095   }
00096   return w + ( KDialog::marginHint() * 2 );
00097 }
00098 
00099 int EntryItem::height( const QListBox *listbox ) const
00100 {
00101   int h = 0;
00102   if ( navigator()->showIcons() )
00103     h = (int)navigator()->viewMode() + 4;
00104   if ( navigator()->showText() ) {
00105     if ( navigator()->viewMode() == SmallIcons || !navigator()->showIcons() )
00106       h = QMAX( h, listbox->fontMetrics().lineSpacing() ) + KDialog::spacingHint() * 2;
00107     else
00108       h = (int)navigator()->viewMode() + listbox->fontMetrics().lineSpacing() + 4;
00109   }
00110   return h;
00111 }
00112 
00113 void EntryItem::paint( QPainter *p )
00114 {
00115   reloadPixmap();
00116 
00117   QListBox *box = listBox();
00118   bool iconAboveText = ( navigator()->viewMode() > SmallIcons ) 
00119                      && navigator()->showIcons();
00120   int w = box->viewport()->width();
00121   int y = 2;
00122 
00123   // draw selected
00124    if ( isCurrent() || isSelected() || mHasHover || mPaintActive ) {
00125     int h = height( box );
00126 
00127     QBrush brush;
00128     if ( isCurrent() || isSelected() || mPaintActive )
00129       brush = box->colorGroup().brush( QColorGroup::Highlight );
00130     else
00131       brush = box->colorGroup().highlight().light( 115 );
00132     p->fillRect( 1, 0, w - 2, h - 1, brush );
00133     QPen pen = p->pen();
00134     QPen oldPen = pen;
00135     pen.setColor( box->colorGroup().mid() );
00136     p->setPen( pen );
00137 
00138     p->drawPoint( 1, 0 );
00139     p->drawPoint( 1, h - 2 );
00140     p->drawPoint( w - 2, 0 );
00141     p->drawPoint( w - 2, h - 2 );
00142 
00143     p->setPen( oldPen );
00144   }
00145 
00146   if ( !mPixmap.isNull() && navigator()->showIcons() ) {
00147       int x = iconAboveText ? ( ( w - mPixmap.width() ) / 2 ) :
00148                               KDialog::marginHint();
00149     p->drawPixmap( x, y, mPixmap );
00150   }
00151 
00152   QColor shadowColor = listBox()->colorGroup().background().dark(115);
00153   if ( isCurrent() || isSelected() ) {
00154     p->setPen( box->colorGroup().highlightedText() );
00155   }
00156 
00157   if ( !text().isEmpty() && navigator()->showText() ) {
00158     QFontMetrics fm = p->fontMetrics();
00159 
00160     int x = 0;
00161     if ( iconAboveText ) {
00162       x = ( w - fm.width( text() ) ) / 2;
00163       y += fm.height() - fm.descent();
00164       if ( navigator()->showIcons() )
00165         y += mPixmap.height();
00166     } else {
00167       x = KDialog::marginHint() + 4;
00168       if( navigator()->showIcons() ) {
00169         x += mPixmap.width();
00170       }
00171 
00172       if ( !navigator()->showIcons() || mPixmap.height() < fm.height() )
00173         y += fm.ascent() + fm.leading()/2;
00174       else
00175         y += mPixmap.height()/2 - fm.height()/2 + fm.ascent();
00176     }
00177 
00178     if ( isCurrent() || isSelected() || mHasHover ) {
00179       p->setPen( box->colorGroup().highlight().dark(115) );
00180       p->drawText( x + ( QApplication::reverseLayout() ? -1 : 1),
00181                    y + 1, text() );
00182       p->setPen( box->colorGroup().highlightedText() );
00183     }
00184     else
00185       p->setPen( box->colorGroup().text() );
00186 
00187     p->drawText( x, y, text() );
00188   }
00189 
00190   // ensure that we don't have a stale flag around
00191   if (  isCurrent() || isSelected() ) mHasHover = false;
00192 }
00193 
00194 void EntryItem::setHover( bool hasHover )
00195 {
00196   mHasHover = hasHover;
00197 }
00198 
00199 void EntryItem::setPaintActive( bool paintActive )
00200 {
00201   mPaintActive = paintActive;
00202 }
00203 
00204 // ************************************************
00205 
00206 Navigator::Navigator(bool _selectable, KPopupMenu * menu, IconSidePane *_iconsidepane, QWidget *parent, const char *name )
00207   : KListBox( parent, name ), mSidePane( _iconsidepane ), mPopupMenu( menu )
00208 {
00209   setSelectionMode( KListBox::Single );
00210   viewport()->setBackgroundMode( PaletteBackground );
00211   setFrameStyle( QFrame::NoFrame );
00212   setHScrollBarMode( QScrollView::AlwaysOff );
00213   //setAcceptDrops( true );
00214   mMinWidth = 0;
00215   mSelectable = _selectable;
00216   executedItem = 0;
00217   mMouseOn = 0;
00218 
00219   setFocusPolicy( NoFocus );
00220 
00221   connect( this, SIGNAL( clicked( QListBoxItem* ) ),
00222            SLOT( slotExecuted( QListBoxItem* ) ) );
00223   connect( this, SIGNAL( onItem( QListBoxItem * ) ),
00224             SLOT(  slotMouseOn( QListBoxItem * ) ) );
00225   connect( this, SIGNAL( onViewport() ), SLOT(  slotMouseOff() ) );
00226 
00227   QToolTip::remove( this );
00228   if ( !mSidePane->showText() )
00229     new EntryItemToolTip( this );
00230 }
00231 
00232 IconViewMode Navigator::viewMode()
00233 {
00234   return mSidePane->viewMode();
00235 }
00236 
00237 bool Navigator::showText()
00238 {
00239   return mSidePane->showText();
00240 }
00241 
00242 bool Navigator::showIcons()
00243 {
00244   return mSidePane->showIcons();
00245 }
00246 
00247 void Navigator::mouseReleaseEvent(QMouseEvent *e)
00248 {
00249   KListBox::mouseReleaseEvent(e);
00250   if ( e->button() != LeftButton || !mLeftMouseButtonPressed )
00251     return;
00252   if ( itemAt( e->pos() ) && executedItem == selectedItem() )
00253     emit itemSelected( currentItem() );
00254    if ( !mSelectable )
00255      clearSelection();
00256 }
00257 
00258 void Navigator::mousePressEvent(QMouseEvent *e)
00259 {
00260   if ( e->button() != LeftButton || itemAt( e->pos() ) == 0 )
00261   {
00262     mLeftMouseButtonPressed = false;
00263     if (e->button() == RightButton)
00264       slotShowRMBMenu( 0,mapToGlobal( e->pos() ) );
00265     return;
00266   }
00267   else
00268     mLeftMouseButtonPressed = true;
00269   KListBox::mousePressEvent(e);
00270 }
00271 
00272 void Navigator::enterEvent( QEvent *event )
00273 {
00274   // work around Qt behaviour: onItem is not emmitted in enterEvent()
00275   KListBox::enterEvent( event );
00276   emit onItem( itemAt( mapFromGlobal( QCursor::pos() ) ) );
00277 }
00278 
00279 void Navigator::slotExecuted( QListBoxItem *item )
00280 {
00281    if ( !item )
00282      return;
00283    executedItem = item;
00284 }
00285 
00286 QSize Navigator::sizeHint() const
00287 {
00288   return QSize( mMinWidth, 100 );
00289 }
00290 
00291 void Navigator::calculateMinWidth()
00292 {
00293   mMinWidth = mSidePane->minWidth();
00294 
00295   for (EntryItem *item = static_cast<EntryItem *>(firstItem()) ; item; item = static_cast<EntryItem *>(item->next()))
00296   {
00297     if (item->width( this ) > mMinWidth)
00298       mMinWidth = item->width( this );
00299   }
00300   //kdDebug() << "minWidth:" << mMinWidth << endl;
00301   parentWidget()->setFixedWidth( mMinWidth );
00302   triggerUpdate(true);
00303 }
00304 
00305 int Navigator::insertItem(const QString &_text, const QString & _pix)
00306 {
00307   EntryItem *item = new EntryItem( this, count(), _text, _pix );
00308   if (item->width( this ) > mSidePane->minWidth() )
00309   {
00310     mMinWidth = item->width( this );
00311     parentWidget()->setMinimumWidth( mMinWidth );
00312     //kdDebug() << "minWidth:" << mMinWidth << endl;
00313   }
00314   return item->id();
00315 }
00316 
00317 void Navigator::setHoverItem( QListBoxItem* item, bool hover )
00318 {
00319     static_cast<EntryItem*>( item )->setHover( hover );
00320     updateItem( item );
00321 }
00322 
00323 void Navigator::setPaintActiveItem( QListBoxItem* item, bool paintActive )
00324 {
00325     static_cast<EntryItem*>( item )->setPaintActive( paintActive );
00326     updateItem( item );
00327 }
00328 
00329 void Navigator::slotMouseOn( QListBoxItem* newItem )
00330 {
00331     QListBoxItem* oldItem = mMouseOn;
00332     if ( oldItem == newItem )
00333       return;
00334 
00335     if ( oldItem && !oldItem->isCurrent() && !oldItem->isSelected() )
00336         setHoverItem( oldItem, false );
00337 
00338     if ( newItem && !newItem->isCurrent() && !newItem->isSelected() )
00339         setHoverItem( newItem, true );
00340     mMouseOn = newItem;
00341 }
00342 
00343 void Navigator::slotMouseOff()
00344 {
00345     slotMouseOn( 0 );
00346 }
00347 
00348 void Navigator::resizeEvent( QResizeEvent *event )
00349 {
00350   QListBox::resizeEvent( event );
00351   triggerUpdate( true );
00352 }
00353 
00354 void Navigator::slotShowRMBMenu( QListBoxItem *, const QPoint &pos )
00355 {
00356   int choice = mPopupMenu->exec( pos );
00357 
00358   if ( choice == -1 )
00359     return;
00360 
00361   mSidePane->resetWidth();
00362   if ( choice >= SmallIcons ) {
00363     mSidePane->setViewMode( mSidePane->sizeIntToEnum( choice ) );
00364     mPopupMenu->setItemChecked( (int)SmallIcons, false);
00365     mPopupMenu->setItemChecked( (int)NormalIcons, false);
00366     mPopupMenu->setItemChecked( (int)LargeIcons, false);
00367     mPopupMenu->setItemChecked( mSidePane->viewMode(), true);
00368     KoShellSettings::setSidePaneIconSize( choice );
00369   }
00370   else
00371   {
00372     // either icons or text were toggled
00373     if ( choice == ShowIcons ) {
00374         mSidePane->toogleIcons();
00375         mPopupMenu->setItemChecked( (int)ShowIcons,  mSidePane->showIcons() );
00376         mPopupMenu->setItemEnabled( (int)ShowText,  mSidePane->showIcons() );
00377         mPopupMenu->setItemEnabled( (int)SmallIcons, mSidePane->showIcons());
00378         mPopupMenu->setItemEnabled( (int)NormalIcons, mSidePane->showIcons());
00379         mPopupMenu->setItemEnabled( (int)LargeIcons, mSidePane->showIcons());
00380         KoShellSettings::setSidePaneShowIcons( mSidePane->showIcons() );
00381 
00382         QToolTip::remove( this );
00383     } else {
00384         mSidePane->toogleText();
00385         mSidePane->resetWidth();
00386         mPopupMenu->setItemChecked( (int)ShowText,  mSidePane->showText() );
00387         mPopupMenu->setItemEnabled( (int)ShowIcons,  mSidePane->showText() );
00388         mPopupMenu->setItemEnabled( (int)SmallIcons, true);
00389         mPopupMenu->setItemEnabled( (int)NormalIcons, true);
00390         mPopupMenu->setItemEnabled( (int)LargeIcons, true);
00391         KoShellSettings::setSidePaneShowText( mSidePane->showText() );
00392         new EntryItemToolTip( this );
00393 //         if ( !mSidePane->showText() )
00394 //           mSidePane->buttonGroup()->hide();
00395 //         else
00396 //           mSidePane->buttonGroup()->show();
00397     }
00398   }
00399   calculateMinWidth();
00400   emit updateAllWidgets();
00401 }
00402 
00403 // ************************************************
00404 
00405 IconSidePane::IconSidePane(QWidget *parent, const char *name )
00406   : QVBox( parent, name )
00407 {
00408   m_buttongroup = new QButtonGroup(1, QGroupBox::Horizontal, this);
00409   m_buttongroup->setExclusive(true);
00410   m_buttongroup->hide();
00411   mWidgetstack = new QWidgetStack(this);
00412   mWidgetstack->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
00413   
00414   // setup the popup menu
00415   mShowIcons = KoShellSettings::sidePaneShowIcons();
00416   mShowText = KoShellSettings::sidePaneShowText();
00417   mViewMode = sizeIntToEnum( KoShellSettings::sidePaneIconSize() );
00418   mPopupMenu = new KPopupMenu(0);
00419   mPopupMenu->insertTitle( i18n( "Icon Size" ) );
00420   mPopupMenu->insertItem( i18n( "Large" ), (int)LargeIcons );
00421   mPopupMenu->setItemEnabled( (int)LargeIcons, mShowIcons );
00422   mPopupMenu->insertItem( i18n( "Normal" ), (int)NormalIcons );
00423   mPopupMenu->setItemEnabled( (int)NormalIcons, mShowIcons );
00424   mPopupMenu->insertItem( i18n( "Small" ), (int)SmallIcons );
00425   mPopupMenu->setItemEnabled( (int)SmallIcons, mShowIcons );
00426   mPopupMenu->setItemChecked( (int)mViewMode, true );
00427   mPopupMenu->insertSeparator();
00428   mPopupMenu->insertItem( i18n( "Show Icons" ), (int)ShowIcons );
00429   mPopupMenu->setItemChecked( (int)ShowIcons, mShowIcons );
00430   mPopupMenu->setItemEnabled( (int)ShowIcons, mShowText );
00431   mPopupMenu->insertItem( i18n( "Show Text" ), (int)ShowText );
00432   mPopupMenu->setItemChecked( (int)ShowText, mShowText );
00433   mPopupMenu->setItemEnabled( (int)ShowText, mShowIcons );
00434   if ( !mShowText )
00435     m_buttongroup->hide();
00436 }
00437 
00438 IconSidePane::~IconSidePane()
00439 {
00440 }
00441 
00442 int IconSidePane::insertItem(int _grp, const QString & _pix, const QString &_text)
00443 {
00444   return static_cast<Navigator*>( mWidgetstack->widget(_grp))->insertItem( _text, _pix );
00445 }
00446 
00447 int IconSidePane::insertItem(const QString & _pix, const QString &_text)
00448 {
00449   return mCurrentNavigator->insertItem(_text, _pix);
00450 }
00451 
00452 void IconSidePane::renameItem( int _grp, int _id, const QString & _text )
00453 {
00454   Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp));
00455   if (!navigator)
00456     return;
00457   EntryItem *item = 0;
00458   for (uint i=0; i< navigator->count(); i++)
00459   {
00460     item = static_cast<EntryItem *>(navigator->item(i));
00461     if (_id == item->id())
00462     {
00463       item->setNewText(_text);
00464       navigator->triggerUpdate(false);
00465       break;
00466     }
00467   }
00468 }
00469 
00470 void IconSidePane::removeItem( int _grp, int _id )
00471 {
00472   Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp));
00473   if (!navigator)
00474     return;
00475   for (uint i=0; i< navigator->count(); i++)
00476   {
00477     if (_id == static_cast<EntryItem *>(navigator->item(i))->id())
00478     {
00479       navigator->removeItem(i);
00480       break;
00481     }
00482   }
00483 }
00484 
00485 int IconSidePane::insertGroup(const QString &_text, bool _selectable, QObject *_obj, const char *_slot)
00486 {
00487   mCurrentNavigator = new Navigator(_selectable, mPopupMenu, this, mWidgetstack );
00488   //connect( mCurrentNavigator, SIGNAL( itemSelected( int ) ), this, SLOT( itemSelected( int ) ) );
00489   if ( _obj != 0L && _slot != 0L )
00490     connect( mCurrentNavigator, SIGNAL( itemSelected(int ) ), _obj, _slot );
00491   connect( mCurrentNavigator, SIGNAL( updateAllWidgets() ), this, SLOT(updateAllWidgets()) );
00492   int const id = mWidgetstack->addWidget(mCurrentNavigator);
00493   mWidgetStackIds.append( id );
00494   KPushButton *b = new KPushButton( _text, m_buttongroup );
00495   m_buttongroup->insert( b, id );
00496   connect( b, SIGNAL( clicked() ), this, SLOT( buttonClicked() ) );
00497   b->setToggleButton( true );
00498   b->setFocusPolicy( NoFocus );
00499   if (m_buttongroup->count()==1)
00500   {
00501     mCurrentNavigator->calculateMinWidth();
00502     m_buttongroup->setButton(m_buttongroup->id(b));
00503     mWidgetstack->raiseWidget(id);
00504   }
00505   if ( b->width() > minimumWidth() )
00506     setMinimumWidth( b->width() );
00507   return id;
00508 }
00509 
00510 void IconSidePane::buttonClicked()
00511 {
00512     mWidgetstack->raiseWidget( m_buttongroup->selectedId() );
00513 }
00514 
00515 void IconSidePane::selectGroup(int group_id)
00516 {
00517     mWidgetstack->raiseWidget(group_id);
00518 }
00519 
00520 void IconSidePane::itemSelected(int item)
00521 {
00522   kdDebug() << "Item selected:" << item << endl;
00523 }
00524 
00525 Navigator * IconSidePane::group(int _grp)
00526 {
00527   return static_cast<Navigator*>(mWidgetstack->widget(_grp));
00528 }
00529 
00530 void IconSidePane::updateAllWidgets()
00531 {
00532   QValueList<int>::iterator it;
00533   for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
00534     static_cast<Navigator*>(mWidgetstack->widget(*it))->triggerUpdate( true );
00535 }
00536 
00537 int IconSidePane::minWidth()
00538 {
00539   int width = 0;
00540   QValueList<int>::iterator it;
00541   Navigator *n;
00542   for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
00543   {
00544     n = static_cast<Navigator*>(mWidgetstack->widget(*it));
00545     if ( n->minWidth() > width )
00546         width = n->minWidth();
00547   }
00548   return width;
00549 }
00550 
00551 void IconSidePane::resetWidth()
00552 {
00553   QValueList<int>::iterator it;
00554   Navigator *n;
00555   for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
00556   {
00557     n = static_cast<Navigator*>(mWidgetstack->widget(*it));
00558     n->resetWidth();
00559     n->triggerUpdate(true);
00560   }
00561 }
00562 
00563 IconViewMode IconSidePane::sizeIntToEnum(int size) const
00564 {
00565   switch ( size ) {
00566     case int(LargeIcons):
00567       return LargeIcons;
00568       break;
00569     case int(NormalIcons):
00570       return NormalIcons;
00571       break;
00572     case int(SmallIcons):
00573       return SmallIcons;
00574       break;
00575     default:
00576       // Stick with sane values
00577       return NormalIcons;
00578       kdDebug() << "View mode not implemented!" << endl;
00579       break;
00580   }
00581 }
00582 
00583 void IconSidePane::setActionCollection( KActionCollection *actionCollection )
00584 {
00585   mActionCollection = actionCollection;
00586 }
00587 
00588 KActionCollection *IconSidePane::actionCollection() const
00589 {
00590   return mActionCollection;
00591 }
00592 
00593 #include "iconsidepane.moc"
00594 
00595 // vim: sw=2 sts=2 et tw=80
KDE Home | KDE Accessibility Home | Description of Access Keys