00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00056
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
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
00253
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
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"