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 )
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 #if QT_VERSION >= 0x030200
00051     connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
00052 #endif
00053 }
00054 
00055 KTabBar::~KTabBar()
00056 {
00057     //For the future
00058     //delete d;
00059 }
00060 
00061 void KTabBar::setTabEnabled( int id, bool enabled )
00062 {
00063     QTab * t = tab( id );
00064     if ( t ) {
00065         if ( t->isEnabled() != enabled ) {
00066             t->setEnabled( enabled );
00067             QRect r( t->rect() );
00068             if ( !enabled && id == currentTab() && count()>1 ) {
00069                 int index = indexOf( id );
00070                 index += ( index+1 == count() ) ? -1 : 1;
00071                 t = tabAt( index );
00072 
00073                 if ( t->isEnabled() ) {
00074                     r = r.unite( t->rect() );
00075                     QPtrList<QTab> *tablist = tabList();
00076                     tablist->append( tablist->take( tablist->findRef( t ) ) );
00077                     emit selected( t->identifier() );
00078                 }
00079             }
00080             repaint( r );
00081         }
00082     }
00083 }
00084 
00085 void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
00086 {
00087     QTab *tab = selectTab( e->pos() );
00088     if( tab!= 0L ) {
00089         emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
00090         return;
00091     }
00092     QTabBar::mouseDoubleClickEvent( e );
00093 }
00094 
00095 void KTabBar::mousePressEvent( QMouseEvent *e )
00096 {
00097     if( e->button() == LeftButton ) {
00098         mEnableCloseButtonTimer->stop();
00099         mDragStart = e->pos();
00100     }
00101     else if( e->button() == RightButton ) {
00102         QTab *tab = selectTab( e->pos() );
00103         if( tab!= 0L ) {
00104             emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
00105             return;
00106         }
00107     }
00108     QTabBar::mousePressEvent( e );
00109 }
00110 
00111 void KTabBar::mouseMoveEvent( QMouseEvent *e )
00112 {
00113     if ( e->state() == LeftButton ) {
00114         QTab *tab = selectTab( e->pos() );
00115         if ( mDragSwitchTab && tab != mDragSwitchTab ) {
00116           mActivateDragSwitchTabTimer->stop();
00117           mDragSwitchTab = 0;
00118         }
00119 
00120         int delay = KGlobalSettings::dndEventDelay();
00121         QPoint newPos = e->pos();
00122         if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
00123             newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
00124          {
00125             if( tab!= 0L ) {
00126                 emit( initiateDrag( indexOf( tab->identifier() ) ) );
00127                 return;
00128            }
00129        }
00130     }
00131     else if ( e->state() == MidButton ) {
00132         if (mReorderStartTab==-1) {
00133             int delay = KGlobalSettings::dndEventDelay();
00134             QPoint newPos = e->pos();
00135             if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
00136                 newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
00137             {
00138                 QTab *tab = selectTab( e->pos() );
00139                 if( tab!= 0L && mTabReorderingEnabled ) {
00140                     mReorderStartTab = indexOf( tab->identifier() );
00141                     grabMouse( sizeAllCursor );
00142                     return;
00143                 }
00144             }
00145         }
00146         else {
00147             QTab *tab = selectTab( e->pos() );
00148             if( tab!= 0L ) {
00149                 int reorderStopTab = indexOf( tab->identifier() );
00150                 if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
00151                     emit( moveTab( mReorderStartTab, reorderStopTab ) );
00152                     mReorderPreviousTab=mReorderStartTab;
00153                     mReorderStartTab=reorderStopTab;
00154                     return;
00155                 }
00156             }
00157         }
00158     }
00159 
00160     if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
00161         QTab *t = selectTab( e->pos() );
00162 
00163         //BEGIN Workaround
00164         //Qt3.2.0 (and 3.2.1) emit wrong local coordinates
00165         //for MouseMove events when the pointer leaves a widget. Discard those
00166         //to avoid enabling the wrong hover button
00167 #ifdef __GNUC__
00168 #warning "Workaround for Qt 3.2.0, 3.2.1 bug"
00169 #endif
00170         if ( e->globalPos() != mapToGlobal( e->pos() ) )
00171             return;
00172         //END Workaround
00173 
00174         if( t && t->iconSet() && t->isEnabled() ) {
00175             QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
00176             QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
00177 
00178             int xoff = 0, yoff = 0;
00179             // The additional offsets were found by try and error, TODO: find the rational behind them
00180             if ( t == tab( currentTab() ) ) {
00181 #if QT_VERSION >= 0x030200
00182                 xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
00183                 yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
00184 #else
00185                 xoff = 3;
00186                 yoff = -4;
00187 #endif
00188             }
00189             else {
00190                 xoff = 7;
00191                 yoff = 0;
00192             }
00193             rect.moveLeft( t->rect().left() + 2 + xoff );
00194             rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
00195             if ( rect.contains( e->pos() ) ) {
00196                 if ( mHoverCloseButton ) {
00197                     if ( mHoverCloseButtonTab == t )
00198                         return;
00199                     mEnableCloseButtonTimer->stop();
00200                     delete mHoverCloseButton;
00201                 }
00202 
00203                 mHoverCloseButton = new QPushButton( this );
00204                 mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIcon("fileclose", KIcon::Toolbar, KIcon::SizeSmall, KIcon::ActiveState) );
00205                 mHoverCloseButton->setGeometry( rect );
00206                 QToolTip::add(mHoverCloseButton,i18n("Close this tab"));
00207                 mHoverCloseButton->setFlat(true);
00208                 mHoverCloseButton->show();
00209                 if ( mHoverCloseButtonDelayed ) {
00210                   mHoverCloseButton->setEnabled(false);
00211                   mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
00212                 }
00213                 mHoverCloseButtonTab = t;
00214                 connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
00215                 return;
00216             }
00217         }
00218         if ( mHoverCloseButton ) {
00219             mEnableCloseButtonTimer->stop();
00220             delete mHoverCloseButton;
00221             mHoverCloseButton = 0;
00222         }
00223     }
00224 
00225     QTabBar::mouseMoveEvent( e );
00226 }
00227 
00228 void KTabBar::enableCloseButton()
00229 {
00230     mHoverCloseButton->setEnabled(true);
00231 }
00232 
00233 void KTabBar::activateDragSwitchTab()
00234 {
00235     setCurrentTab( mDragSwitchTab );
00236     mDragSwitchTab = 0;
00237 }
00238 
00239 void KTabBar::mouseReleaseEvent( QMouseEvent *e )
00240 {
00241     if( e->button() == MidButton ) {
00242         QTab *tab = selectTab( e->pos() );
00243         if ( mReorderStartTab==-1 ) {
00244             if( tab!= 0L ) {
00245                 emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
00246                 return;
00247             }
00248         }
00249         else {
00250             releaseMouse();
00251             setCursor( arrowCursor );
00252             mReorderStartTab=-1;
00253             mReorderPreviousTab=-1;
00254         }
00255     }
00256     QTabBar::mouseReleaseEvent( e );
00257 }
00258 
00259 void KTabBar::dragMoveEvent( QDragMoveEvent *e )
00260 {
00261     QTab *tab = selectTab( e->pos() );
00262     if( tab!= 0L ) {
00263         bool accept = false;
00264         // The receivers of the testCanDecode() signal has to adjust
00265         // 'accept' accordingly.
00266         emit testCanDecode( e, accept);
00267         if ( accept && tab != QTabBar::tab( currentTab() ) ) {
00268           mDragSwitchTab = tab;
00269           mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
00270         }
00271         e->accept( accept );
00272         return;
00273     }
00274     e->accept( false );
00275     QTabBar::dragMoveEvent( e );
00276 }
00277 
00278 void KTabBar::dropEvent( QDropEvent *e )
00279 {
00280     QTab *tab = selectTab( e->pos() );
00281     if( tab!= 0L ) {
00282         mActivateDragSwitchTabTimer->stop();
00283         mDragSwitchTab = 0;
00284         emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
00285         return;
00286     }
00287     QTabBar::dropEvent( e );
00288 }
00289 
00290 void KTabBar::setTabColor( int id, const QColor& color )
00291 {
00292     QTab *t = tab( id );
00293     if ( t ) {
00294         mTabColors.insert( id, color );
00295         repaint( t->rect(), false );
00296     }
00297 }
00298 
00299 const QColor &KTabBar::tabColor( int id  ) const
00300 {
00301     if ( mTabColors.contains( id ) )
00302         return mTabColors[id];
00303 
00304     return colorGroup().foreground();
00305 }
00306 
00307 void KTabBar::removeTab( QTab *t )
00308 {
00309     mTabColors.remove( t->identifier() );
00310     QTabBar::removeTab( t );
00311 }
00312 
00313 void KTabBar::paintLabel( QPainter *p, const QRect& br,
00314                           QTab *t, bool has_focus ) const
00315 {
00316     QRect r = br;
00317     bool selected = currentTab() == t->identifier();
00318     if ( t->iconSet() ) {
00319         // the tab has an iconset, draw it in the right mode
00320         QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
00321                                  ? QIconSet::Normal : QIconSet::Disabled;
00322         if ( mode == QIconSet::Normal && has_focus )
00323             mode = QIconSet::Active;
00324         QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
00325         int pixw = pixmap.width();
00326         int pixh = pixmap.height();
00327         r.setLeft( r.left() + pixw + 4 );
00328         r.setRight( r.right() + 2 );
00329 
00330         int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
00331         int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
00332 
00333         int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
00334 
00335         p->drawPixmap( right + ((selected == true) ? 0 : inactiveXShift),
00336                        br.center().y() - pixh / 2 + ((selected == true) ? 0 : inactiveYShift),
00337                        pixmap );
00338     }
00339 
00340     QStyle::SFlags flags = QStyle::Style_Default;
00341 
00342     if ( isEnabled() && t->isEnabled() )
00343         flags |= QStyle::Style_Enabled;
00344     if ( has_focus )
00345         flags |= QStyle::Style_HasFocus;
00346 
00347     QColorGroup cg( colorGroup() );
00348     if ( mTabColors.contains( t->identifier() ) )
00349         cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
00350 
00351     style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
00352                              t->isEnabled() ? cg : palette().disabled(),
00353                              flags, QStyleOption(t) );
00354 }
00355 
00356 bool KTabBar::isTabReorderingEnabled() const
00357 {
00358     return mTabReorderingEnabled;
00359 }
00360 
00361 void KTabBar::setTabReorderingEnabled( bool on )
00362 {
00363     mTabReorderingEnabled = on;
00364 }
00365 
00366 void KTabBar::closeButtonClicked()
00367 {
00368     emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
00369 #if QT_VERSION < 0x030200
00370     onLayoutChange();
00371 #endif
00372 }
00373 
00374 void KTabBar::setHoverCloseButton( bool button )
00375 {
00376     mHoverCloseButtonEnabled = button;
00377     if ( !button )
00378         onLayoutChange();
00379 }
00380 
00381 bool KTabBar::hoverCloseButton() const
00382 {
00383     return mHoverCloseButtonEnabled;
00384 }
00385 
00386 void KTabBar::setHoverCloseButtonDelayed( bool delayed )
00387 {
00388     mHoverCloseButtonDelayed = delayed;
00389 }
00390 
00391 bool KTabBar::hoverCloseButtonDelayed() const
00392 {
00393     return mHoverCloseButtonDelayed;
00394 }
00395 
00396 void KTabBar::onLayoutChange()
00397 {
00398     mEnableCloseButtonTimer->stop();
00399     delete mHoverCloseButton;
00400     mHoverCloseButton = 0;
00401     mHoverCloseButtonTab = 0;
00402     mActivateDragSwitchTabTimer->stop();
00403     mDragSwitchTab = 0;
00404 }
00405 
00406 #include "ktabbar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Mar 3 19:23:12 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003