kdeui Library API Documentation

ktabbar.cpp

00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2003 Stephan Binner <binner@kde.org>
00003     Copyright (C) 2003 Zack Rusin <zack@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018     Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <qapplication.h>
00022 #include <qpainter.h>
00023 #include <qstyle.h>
00024 #include <qtimer.h>
00025 #include <qpushbutton.h>
00026 #include <qtooltip.h>
00027 
00028 #include <kglobalsettings.h>
00029 #include <kiconloader.h>
00030 #include <klocale.h>
00031 
00032 #include "ktabbar.h"
00033 #include "ktabwidget.h"
00034 
00035 KTabBar::KTabBar( QWidget *parent, const char *name )
00036     : QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ),
00037       mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ),
00038       mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ),
00039       mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false )
00040 {
00041     setAcceptDrops( true );
00042     setMouseTracking( true );
00043 
00044     mEnableCloseButtonTimer = new QTimer( this );
00045     connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) );
00046 
00047     mActivateDragSwitchTabTimer = new QTimer( this );
00048     connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
00049 
00050     connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
00051 }
00052 
00053 KTabBar::~KTabBar()
00054 {
00055     //For the future
00056     //delete d;
00057 }
00058 
00059 void KTabBar::setTabEnabled( int id, bool enabled )
00060 {
00061     QTab * t = tab( id );
00062     if ( t ) {
00063         if ( t->isEnabled() != enabled ) {
00064             t->setEnabled( enabled );
00065             QRect r( t->rect() );
00066             if ( !enabled && id == currentTab() && count()>1 ) {
00067                 QPtrList<QTab> *tablist = tabList();
00068                 if ( mTabCloseActivatePrevious )
00069                     t = tablist->at( count()-2 );
00070                 else {
00071                 int index = indexOf( id );
00072                 index += ( index+1 == count() ) ? -1 : 1;
00073                 t = tabAt( index );
00074                 }
00075 
00076                 if ( t->isEnabled() ) {
00077                     r = r.unite( t->rect() );
00078                     tablist->append( tablist->take( tablist->findRef( t ) ) );
00079                     emit selected( t->identifier() );
00080                 }
00081             }
00082             repaint( r );
00083         }
00084     }
00085 }
00086 
00087 void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
00088 {
00089     if( e->button() != LeftButton )
00090         return;
00091 
00092     QTab *tab = selectTab( e->pos() );
00093     if( tab!= 0L ) {
00094         emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
00095         return;
00096     }
00097     QTabBar::mouseDoubleClickEvent( e );
00098 }
00099 
00100 void KTabBar::mousePressEvent( QMouseEvent *e )
00101 {
00102     if( e->button() == LeftButton ) {
00103         mEnableCloseButtonTimer->stop();
00104         mDragStart = e->pos();
00105     }
00106     else if( e->button() == RightButton ) {
00107         QTab *tab = selectTab( e->pos() );
00108         if( tab!= 0L ) {
00109             emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
00110             return;
00111         }
00112     }
00113     QTabBar::mousePressEvent( e );
00114 }
00115 
00116 void KTabBar::mouseMoveEvent( QMouseEvent *e )
00117 {
00118     if ( e->state() == LeftButton ) {
00119         QTab *tab = selectTab( e->pos() );
00120         if ( mDragSwitchTab && tab != mDragSwitchTab ) {
00121           mActivateDragSwitchTabTimer->stop();
00122           mDragSwitchTab = 0;
00123         }
00124 
00125         int delay = KGlobalSettings::dndEventDelay();
00126         QPoint newPos = e->pos();
00127         if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
00128             newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
00129          {
00130             if( tab!= 0L ) {
00131                 emit( initiateDrag( indexOf( tab->identifier() ) ) );
00132                 return;
00133            }
00134        }
00135     }
00136     else if ( e->state() == MidButton ) {
00137         if (mReorderStartTab==-1) {
00138             int delay = KGlobalSettings::dndEventDelay();
00139             QPoint newPos = e->pos();
00140             if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
00141                 newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
00142             {
00143                 QTab *tab = selectTab( e->pos() );
00144                 if( tab!= 0L && mTabReorderingEnabled ) {
00145                     mReorderStartTab = indexOf( tab->identifier() );
00146                     grabMouse( sizeAllCursor );
00147                     return;
00148                 }
00149             }
00150         }
00151         else {
00152             QTab *tab = selectTab( e->pos() );
00153             if( tab!= 0L ) {
00154                 int reorderStopTab = indexOf( tab->identifier() );
00155                 if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
00156                     emit( moveTab( mReorderStartTab, reorderStopTab ) );
00157                     mReorderPreviousTab=mReorderStartTab;
00158                     mReorderStartTab=reorderStopTab;
00159                     return;
00160                 }
00161             }
00162         }
00163     }
00164 
00165     if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
00166         QTab *t = selectTab( e->pos() );
00167         if( t && t->iconSet() && t->isEnabled() ) {
00168             QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
00169             QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
00170 
00171             int xoff = 0, yoff = 0;
00172             // The additional offsets were found by try and error, TODO: find the rational behind them
00173             if ( t == tab( currentTab() ) ) {
00174                 xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
00175                 yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
00176             }
00177             else {
00178                 xoff = 7;
00179                 yoff = 0;
00180             }
00181             rect.moveLeft( t->rect().left() + 2 + xoff );
00182             rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
00183             if ( rect.contains( e->pos() ) ) {
00184                 if ( mHoverCloseButton ) {
00185                     if ( mHoverCloseButtonTab == t )
00186                         return;
00187                     mEnableCloseButtonTimer->stop();
00188                     delete mHoverCloseButton;
00189                 }
00190 
00191                 mHoverCloseButton = new QPushButton( this );
00192                 mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIcon("fileclose", KIcon::Toolbar, KIcon::SizeSmall, KIcon::ActiveState) );
00193                 mHoverCloseButton->setGeometry( rect );
00194                 QToolTip::add(mHoverCloseButton,i18n("Close this tab"));
00195                 mHoverCloseButton->setFlat(true);
00196                 mHoverCloseButton->show();
00197                 if ( mHoverCloseButtonDelayed ) {
00198                   mHoverCloseButton->setEnabled(false);
00199                   mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
00200                 }
00201                 mHoverCloseButtonTab = t;
00202                 connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
00203                 return;
00204             }
00205         }
00206         if ( mHoverCloseButton ) {
00207             mEnableCloseButtonTimer->stop();
00208             delete mHoverCloseButton;
00209             mHoverCloseButton = 0;
00210         }
00211     }
00212 
00213     QTabBar::mouseMoveEvent( e );
00214 }
00215 
00216 void KTabBar::enableCloseButton()
00217 {
00218     mHoverCloseButton->setEnabled(true);
00219 }
00220 
00221 void KTabBar::activateDragSwitchTab()
00222 {
00223     setCurrentTab( mDragSwitchTab );
00224     mDragSwitchTab = 0;
00225 }
00226 
00227 void KTabBar::mouseReleaseEvent( QMouseEvent *e )
00228 {
00229     if( e->button() == MidButton ) {
00230         if ( mReorderStartTab==-1 ) {
00231             QTab *tab = selectTab( e->pos() );
00232             if( tab!= 0L ) {
00233                 emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
00234                 return;
00235             }
00236         }
00237         else {
00238             releaseMouse();
00239             setCursor( arrowCursor );
00240             mReorderStartTab=-1;
00241             mReorderPreviousTab=-1;
00242         }
00243     }
00244     QTabBar::mouseReleaseEvent( e );
00245 }
00246 
00247 void KTabBar::dragMoveEvent( QDragMoveEvent *e )
00248 {
00249     QTab *tab = selectTab( e->pos() );
00250     if( tab!= 0L ) {
00251         bool accept = false;
00252         // The receivers of the testCanDecode() signal has to adjust
00253         // 'accept' accordingly.
00254         emit testCanDecode( e, accept);
00255         if ( accept && tab != QTabBar::tab( currentTab() ) ) {
00256           mDragSwitchTab = tab;
00257           mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
00258         }
00259         e->accept( accept );
00260         return;
00261     }
00262     e->accept( false );
00263     QTabBar::dragMoveEvent( e );
00264 }
00265 
00266 void KTabBar::dropEvent( QDropEvent *e )
00267 {
00268     QTab *tab = selectTab( e->pos() );
00269     if( tab!= 0L ) {
00270         mActivateDragSwitchTabTimer->stop();
00271         mDragSwitchTab = 0;
00272         emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
00273         return;
00274     }
00275     QTabBar::dropEvent( e );
00276 }
00277 
00278 #ifndef QT_NO_WHEELEVENT
00279 void KTabBar::wheelEvent( QWheelEvent *e )
00280 {
00281     if ( e->orientation() == Horizontal )
00282         return;
00283 
00284     emit( wheelDelta( e->delta() ) );
00285 }
00286 #endif
00287 
00288 void KTabBar::setTabColor( int id, const QColor& color )
00289 {
00290     QTab *t = tab( id );
00291     if ( t ) {
00292         mTabColors.insert( id, color );
00293         repaint( t->rect(), false );
00294     }
00295 }
00296 
00297 const QColor &KTabBar::tabColor( int id  ) const
00298 {
00299     if ( mTabColors.contains( id ) )
00300         return mTabColors[id];
00301 
00302     return colorGroup().foreground();
00303 }
00304 
00305 int KTabBar::insertTab( QTab *t, int index )
00306 {
00307     int res = QTabBar::insertTab( t, index );
00308 
00309     if ( mTabCloseActivatePrevious && count() > 2 ) {
00310         QPtrList<QTab> *tablist = tabList();
00311         tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
00312     }
00313 
00314     return res;
00315 }
00316 
00317 void KTabBar::removeTab( QTab *t )
00318 {
00319     mTabColors.remove( t->identifier() );
00320     QTabBar::removeTab( t );
00321 }
00322 
00323 void KTabBar::paintLabel( QPainter *p, const QRect& br,
00324                           QTab *t, bool has_focus ) const
00325 {
00326     QRect r = br;
00327     bool selected = currentTab() == t->identifier();
00328     if ( t->iconSet() ) {
00329         // the tab has an iconset, draw it in the right mode
00330         QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
00331                                  ? QIconSet::Normal : QIconSet::Disabled;
00332         if ( mode == QIconSet::Normal && has_focus )
00333             mode = QIconSet::Active;
00334         QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
00335         int pixw = pixmap.width();
00336         int pixh = pixmap.height();
00337         r.setLeft( r.left() + pixw + 4 );
00338         r.setRight( r.right() + 2 );
00339 
00340         int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
00341         int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
00342 
00343         int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
00344 
00345         p->drawPixmap( right + ((selected == true) ? 0 : inactiveXShift),
00346                        br.center().y() - pixh / 2 + ((selected == true) ? 0 : inactiveYShift),
00347                        pixmap );
00348     }
00349 
00350     QStyle::SFlags flags = QStyle::Style_Default;
00351 
00352     if ( isEnabled() && t->isEnabled() )
00353         flags |= QStyle::Style_Enabled;
00354     if ( has_focus )
00355         flags |= QStyle::Style_HasFocus;
00356 
00357     QColorGroup cg( colorGroup() );
00358     if ( mTabColors.contains( t->identifier() ) )
00359         cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
00360 
00361     style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
00362                              t->isEnabled() ? cg : palette().disabled(),
00363                              flags, QStyleOption(t) );
00364 }
00365 
00366 bool KTabBar::isTabReorderingEnabled() const
00367 {
00368     return mTabReorderingEnabled;
00369 }
00370 
00371 void KTabBar::setTabReorderingEnabled( bool on )
00372 {
00373     mTabReorderingEnabled = on;
00374 }
00375 
00376 bool KTabBar::tabCloseActivatePrevious() const
00377 {
00378     return mTabCloseActivatePrevious;
00379 }
00380 
00381 void KTabBar::setTabCloseActivatePrevious( bool on )
00382 {
00383     mTabCloseActivatePrevious = on;
00384 }
00385 
00386 void KTabBar::closeButtonClicked()
00387 {
00388     emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
00389 }
00390 
00391 void KTabBar::setHoverCloseButton( bool button )
00392 {
00393     mHoverCloseButtonEnabled = button;
00394     if ( !button )
00395         onLayoutChange();
00396 }
00397 
00398 bool KTabBar::hoverCloseButton() const
00399 {
00400     return mHoverCloseButtonEnabled;
00401 }
00402 
00403 void KTabBar::setHoverCloseButtonDelayed( bool delayed )
00404 {
00405     mHoverCloseButtonDelayed = delayed;
00406 }
00407 
00408 bool KTabBar::hoverCloseButtonDelayed() const
00409 {
00410     return mHoverCloseButtonDelayed;
00411 }
00412 
00413 void KTabBar::onLayoutChange()
00414 {
00415     mEnableCloseButtonTimer->stop();
00416     delete mHoverCloseButton;
00417     mHoverCloseButton = 0;
00418     mHoverCloseButtonTab = 0;
00419     mActivateDragSwitchTabTimer->stop();
00420     mDragSwitchTab = 0;
00421 }
00422 
00423 #include "ktabbar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 23 17:11:55 2004 by doxygen 1.3.8-20040913 written by Dimitri van Heesch, © 1997-2003