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 QTab *tab = selectTab( e->pos() );
00090 if( tab!= 0L ) {
00091 emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
00092 return;
00093 }
00094 QTabBar::mouseDoubleClickEvent( e );
00095 }
00096
00097 void KTabBar::mousePressEvent( QMouseEvent *e )
00098 {
00099 if( e->button() == LeftButton ) {
00100 mEnableCloseButtonTimer->stop();
00101 mDragStart = e->pos();
00102 }
00103 else if( e->button() == RightButton ) {
00104 QTab *tab = selectTab( e->pos() );
00105 if( tab!= 0L ) {
00106 emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
00107 return;
00108 }
00109 }
00110 QTabBar::mousePressEvent( e );
00111 }
00112
00113 void KTabBar::mouseMoveEvent( QMouseEvent *e )
00114 {
00115 if ( e->state() == LeftButton ) {
00116 QTab *tab = selectTab( e->pos() );
00117 if ( mDragSwitchTab && tab != mDragSwitchTab ) {
00118 mActivateDragSwitchTabTimer->stop();
00119 mDragSwitchTab = 0;
00120 }
00121
00122 int delay = KGlobalSettings::dndEventDelay();
00123 QPoint newPos = e->pos();
00124 if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
00125 newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
00126 {
00127 if( tab!= 0L ) {
00128 emit( initiateDrag( indexOf( tab->identifier() ) ) );
00129 return;
00130 }
00131 }
00132 }
00133 else if ( e->state() == MidButton ) {
00134 if (mReorderStartTab==-1) {
00135 int delay = KGlobalSettings::dndEventDelay();
00136 QPoint newPos = e->pos();
00137 if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
00138 newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
00139 {
00140 QTab *tab = selectTab( e->pos() );
00141 if( tab!= 0L && mTabReorderingEnabled ) {
00142 mReorderStartTab = indexOf( tab->identifier() );
00143 grabMouse( sizeAllCursor );
00144 return;
00145 }
00146 }
00147 }
00148 else {
00149 QTab *tab = selectTab( e->pos() );
00150 if( tab!= 0L ) {
00151 int reorderStopTab = indexOf( tab->identifier() );
00152 if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
00153 emit( moveTab( mReorderStartTab, reorderStopTab ) );
00154 mReorderPreviousTab=mReorderStartTab;
00155 mReorderStartTab=reorderStopTab;
00156 return;
00157 }
00158 }
00159 }
00160 }
00161
00162 if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
00163 QTab *t = selectTab( e->pos() );
00164 if( t && t->iconSet() && t->isEnabled() ) {
00165 QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
00166 QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
00167
00168 int xoff = 0, yoff = 0;
00169
00170 if ( t == tab( currentTab() ) ) {
00171 xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
00172 yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
00173 }
00174 else {
00175 xoff = 7;
00176 yoff = 0;
00177 }
00178 rect.moveLeft( t->rect().left() + 2 + xoff );
00179 rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
00180 if ( rect.contains( e->pos() ) ) {
00181 if ( mHoverCloseButton ) {
00182 if ( mHoverCloseButtonTab == t )
00183 return;
00184 mEnableCloseButtonTimer->stop();
00185 delete mHoverCloseButton;
00186 }
00187
00188 mHoverCloseButton = new QPushButton( this );
00189 mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIcon("fileclose", KIcon::Toolbar, KIcon::SizeSmall, KIcon::ActiveState) );
00190 mHoverCloseButton->setGeometry( rect );
00191 QToolTip::add(mHoverCloseButton,i18n("Close this tab"));
00192 mHoverCloseButton->setFlat(true);
00193 mHoverCloseButton->show();
00194 if ( mHoverCloseButtonDelayed ) {
00195 mHoverCloseButton->setEnabled(false);
00196 mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
00197 }
00198 mHoverCloseButtonTab = t;
00199 connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
00200 return;
00201 }
00202 }
00203 if ( mHoverCloseButton ) {
00204 mEnableCloseButtonTimer->stop();
00205 delete mHoverCloseButton;
00206 mHoverCloseButton = 0;
00207 }
00208 }
00209
00210 QTabBar::mouseMoveEvent( e );
00211 }
00212
00213 void KTabBar::enableCloseButton()
00214 {
00215 mHoverCloseButton->setEnabled(true);
00216 }
00217
00218 void KTabBar::activateDragSwitchTab()
00219 {
00220 setCurrentTab( mDragSwitchTab );
00221 mDragSwitchTab = 0;
00222 }
00223
00224 void KTabBar::mouseReleaseEvent( QMouseEvent *e )
00225 {
00226 if( e->button() == MidButton ) {
00227 if ( mReorderStartTab==-1 ) {
00228 QTab *tab = selectTab( e->pos() );
00229 if( tab!= 0L ) {
00230 emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
00231 return;
00232 }
00233 }
00234 else {
00235 releaseMouse();
00236 setCursor( arrowCursor );
00237 mReorderStartTab=-1;
00238 mReorderPreviousTab=-1;
00239 }
00240 }
00241 QTabBar::mouseReleaseEvent( e );
00242 }
00243
00244 void KTabBar::dragMoveEvent( QDragMoveEvent *e )
00245 {
00246 QTab *tab = selectTab( e->pos() );
00247 if( tab!= 0L ) {
00248 bool accept = false;
00249
00250
00251 emit testCanDecode( e, accept);
00252 if ( accept && tab != QTabBar::tab( currentTab() ) ) {
00253 mDragSwitchTab = tab;
00254 mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
00255 }
00256 e->accept( accept );
00257 return;
00258 }
00259 e->accept( false );
00260 QTabBar::dragMoveEvent( e );
00261 }
00262
00263 void KTabBar::dropEvent( QDropEvent *e )
00264 {
00265 QTab *tab = selectTab( e->pos() );
00266 if( tab!= 0L ) {
00267 mActivateDragSwitchTabTimer->stop();
00268 mDragSwitchTab = 0;
00269 emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
00270 return;
00271 }
00272 QTabBar::dropEvent( e );
00273 }
00274
00275 #ifndef QT_NO_WHEELEVENT
00276 void KTabBar::wheelEvent( QWheelEvent *e )
00277 {
00278 if ( e->orientation() == Horizontal )
00279 return;
00280
00281 emit( wheelDelta( e->delta() ) );
00282 }
00283 #endif
00284
00285 void KTabBar::setTabColor( int id, const QColor& color )
00286 {
00287 QTab *t = tab( id );
00288 if ( t ) {
00289 mTabColors.insert( id, color );
00290 repaint( t->rect(), false );
00291 }
00292 }
00293
00294 const QColor &KTabBar::tabColor( int id ) const
00295 {
00296 if ( mTabColors.contains( id ) )
00297 return mTabColors[id];
00298
00299 return colorGroup().foreground();
00300 }
00301
00302 int KTabBar::insertTab( QTab *t, int index )
00303 {
00304 int res = QTabBar::insertTab( t, index );
00305
00306 if ( mTabCloseActivatePrevious && count() > 2 ) {
00307 QPtrList<QTab> *tablist = tabList();
00308 tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
00309 }
00310
00311 return res;
00312 }
00313
00314 void KTabBar::removeTab( QTab *t )
00315 {
00316 mTabColors.remove( t->identifier() );
00317 QTabBar::removeTab( t );
00318 }
00319
00320 void KTabBar::paintLabel( QPainter *p, const QRect& br,
00321 QTab *t, bool has_focus ) const
00322 {
00323 QRect r = br;
00324 bool selected = currentTab() == t->identifier();
00325 if ( t->iconSet() ) {
00326
00327 QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
00328 ? QIconSet::Normal : QIconSet::Disabled;
00329 if ( mode == QIconSet::Normal && has_focus )
00330 mode = QIconSet::Active;
00331 QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
00332 int pixw = pixmap.width();
00333 int pixh = pixmap.height();
00334 r.setLeft( r.left() + pixw + 4 );
00335 r.setRight( r.right() + 2 );
00336
00337 int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
00338 int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
00339
00340 int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
00341
00342 p->drawPixmap( right + ((selected == true) ? 0 : inactiveXShift),
00343 br.center().y() - pixh / 2 + ((selected == true) ? 0 : inactiveYShift),
00344 pixmap );
00345 }
00346
00347 QStyle::SFlags flags = QStyle::Style_Default;
00348
00349 if ( isEnabled() && t->isEnabled() )
00350 flags |= QStyle::Style_Enabled;
00351 if ( has_focus )
00352 flags |= QStyle::Style_HasFocus;
00353
00354 QColorGroup cg( colorGroup() );
00355 if ( mTabColors.contains( t->identifier() ) )
00356 cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
00357
00358 style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
00359 t->isEnabled() ? cg : palette().disabled(),
00360 flags, QStyleOption(t) );
00361 }
00362
00363 bool KTabBar::isTabReorderingEnabled() const
00364 {
00365 return mTabReorderingEnabled;
00366 }
00367
00368 void KTabBar::setTabReorderingEnabled( bool on )
00369 {
00370 mTabReorderingEnabled = on;
00371 }
00372
00373 bool KTabBar::tabCloseActivatePrevious() const
00374 {
00375 return mTabCloseActivatePrevious;
00376 }
00377
00378 void KTabBar::setTabCloseActivatePrevious( bool on )
00379 {
00380 mTabCloseActivatePrevious = on;
00381 }
00382
00383 void KTabBar::closeButtonClicked()
00384 {
00385 emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
00386 }
00387
00388 void KTabBar::setHoverCloseButton( bool button )
00389 {
00390 mHoverCloseButtonEnabled = button;
00391 if ( !button )
00392 onLayoutChange();
00393 }
00394
00395 bool KTabBar::hoverCloseButton() const
00396 {
00397 return mHoverCloseButtonEnabled;
00398 }
00399
00400 void KTabBar::setHoverCloseButtonDelayed( bool delayed )
00401 {
00402 mHoverCloseButtonDelayed = delayed;
00403 }
00404
00405 bool KTabBar::hoverCloseButtonDelayed() const
00406 {
00407 return mHoverCloseButtonDelayed;
00408 }
00409
00410 void KTabBar::onLayoutChange()
00411 {
00412 mEnableCloseButtonTimer->stop();
00413 delete mHoverCloseButton;
00414 mHoverCloseButton = 0;
00415 mHoverCloseButtonTab = 0;
00416 mActivateDragSwitchTabTimer->stop();
00417 mDragSwitchTab = 0;
00418 }
00419
00420 #include "ktabbar.moc"