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