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 mHoverCloseButton->deleteLater();
00190 mHoverCloseButton = 0;
00191 }
00192
00193 mHoverCloseButton = new QPushButton( this );
00194 mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIconSet("fileclose", KIcon::Toolbar, KIcon::SizeSmall) );
00195 mHoverCloseButton->setGeometry( rect );
00196 QToolTip::add(mHoverCloseButton,i18n("Close this tab"));
00197 mHoverCloseButton->setFlat(true);
00198 mHoverCloseButton->show();
00199 if ( mHoverCloseButtonDelayed ) {
00200 mHoverCloseButton->setEnabled(false);
00201 mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
00202 }
00203 mHoverCloseButtonTab = t;
00204 connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
00205 return;
00206 }
00207 }
00208 if ( mHoverCloseButton ) {
00209 mEnableCloseButtonTimer->stop();
00210 mHoverCloseButton->deleteLater();
00211 mHoverCloseButton = 0;
00212 }
00213 }
00214
00215 QTabBar::mouseMoveEvent( e );
00216 }
00217
00218 void KTabBar::enableCloseButton()
00219 {
00220 mHoverCloseButton->setEnabled(true);
00221 }
00222
00223 void KTabBar::activateDragSwitchTab()
00224 {
00225 QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) );
00226 if ( tab && mDragSwitchTab == tab )
00227 setCurrentTab( mDragSwitchTab );
00228 mDragSwitchTab = 0;
00229 }
00230
00231 void KTabBar::mouseReleaseEvent( QMouseEvent *e )
00232 {
00233 if( e->button() == MidButton ) {
00234 if ( mReorderStartTab==-1 ) {
00235 QTab *tab = selectTab( e->pos() );
00236 if( tab ) {
00237 emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
00238 return;
00239 }
00240 }
00241 else {
00242 releaseMouse();
00243 setCursor( arrowCursor );
00244 mReorderStartTab=-1;
00245 mReorderPreviousTab=-1;
00246 }
00247 }
00248 QTabBar::mouseReleaseEvent( e );
00249 }
00250
00251 void KTabBar::dragMoveEvent( QDragMoveEvent *e )
00252 {
00253 QTab *tab = selectTab( e->pos() );
00254 if( tab ) {
00255 bool accept = false;
00256
00257
00258 emit testCanDecode( e, accept);
00259 if ( accept && tab != QTabBar::tab( currentTab() ) ) {
00260 mDragSwitchTab = tab;
00261 mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
00262 }
00263 e->accept( accept );
00264 return;
00265 }
00266 e->accept( false );
00267 QTabBar::dragMoveEvent( e );
00268 }
00269
00270 void KTabBar::dropEvent( QDropEvent *e )
00271 {
00272 QTab *tab = selectTab( e->pos() );
00273 if( tab ) {
00274 mActivateDragSwitchTabTimer->stop();
00275 mDragSwitchTab = 0;
00276 emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
00277 return;
00278 }
00279 QTabBar::dropEvent( e );
00280 }
00281
00282 #ifndef QT_NO_WHEELEVENT
00283 void KTabBar::wheelEvent( QWheelEvent *e )
00284 {
00285 if ( e->orientation() == Horizontal )
00286 return;
00287
00288 emit( wheelDelta( e->delta() ) );
00289 }
00290 #endif
00291
00292 void KTabBar::setTabColor( int id, const QColor& color )
00293 {
00294 QTab *t = tab( id );
00295 if ( t ) {
00296 mTabColors.insert( id, color );
00297 repaint( t->rect(), false );
00298 }
00299 }
00300
00301 const QColor &KTabBar::tabColor( int id ) const
00302 {
00303 if ( mTabColors.contains( id ) )
00304 return mTabColors[id];
00305
00306 return colorGroup().foreground();
00307 }
00308
00309 int KTabBar::insertTab( QTab *t, int index )
00310 {
00311 int res = QTabBar::insertTab( t, index );
00312
00313 if ( mTabCloseActivatePrevious && count() > 2 ) {
00314 QPtrList<QTab> *tablist = tabList();
00315 tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
00316 }
00317
00318 return res;
00319 }
00320
00321 void KTabBar::removeTab( QTab *t )
00322 {
00323 mTabColors.remove( t->identifier() );
00324 QTabBar::removeTab( t );
00325 }
00326
00327 void KTabBar::paintLabel( QPainter *p, const QRect& br,
00328 QTab *t, bool has_focus ) const
00329 {
00330 QRect r = br;
00331 bool selected = currentTab() == t->identifier();
00332 if ( t->iconSet() ) {
00333
00334 QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
00335 ? QIconSet::Normal : QIconSet::Disabled;
00336 if ( mode == QIconSet::Normal && has_focus )
00337 mode = QIconSet::Active;
00338 QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
00339 int pixw = pixmap.width();
00340 int pixh = pixmap.height();
00341 r.setLeft( r.left() + pixw + 4 );
00342 r.setRight( r.right() + 2 );
00343
00344 int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
00345 int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
00346
00347 int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
00348
00349 p->drawPixmap( right + (selected ? 0 : inactiveXShift),
00350 br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
00351 pixmap );
00352 }
00353
00354 QStyle::SFlags flags = QStyle::Style_Default;
00355
00356 if ( isEnabled() && t->isEnabled() )
00357 flags |= QStyle::Style_Enabled;
00358 if ( has_focus )
00359 flags |= QStyle::Style_HasFocus;
00360
00361 QColorGroup cg( colorGroup() );
00362 if ( mTabColors.contains( t->identifier() ) )
00363 cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
00364
00365 style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
00366 t->isEnabled() ? cg : palette().disabled(),
00367 flags, QStyleOption(t) );
00368 }
00369
00370 bool KTabBar::isTabReorderingEnabled() const
00371 {
00372 return mTabReorderingEnabled;
00373 }
00374
00375 void KTabBar::setTabReorderingEnabled( bool on )
00376 {
00377 mTabReorderingEnabled = on;
00378 }
00379
00380 bool KTabBar::tabCloseActivatePrevious() const
00381 {
00382 return mTabCloseActivatePrevious;
00383 }
00384
00385 void KTabBar::setTabCloseActivatePrevious( bool on )
00386 {
00387 mTabCloseActivatePrevious = on;
00388 }
00389
00390 void KTabBar::closeButtonClicked()
00391 {
00392 emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
00393 }
00394
00395 void KTabBar::setHoverCloseButton( bool button )
00396 {
00397 mHoverCloseButtonEnabled = button;
00398 if ( !button )
00399 onLayoutChange();
00400 }
00401
00402 bool KTabBar::hoverCloseButton() const
00403 {
00404 return mHoverCloseButtonEnabled;
00405 }
00406
00407 void KTabBar::setHoverCloseButtonDelayed( bool delayed )
00408 {
00409 mHoverCloseButtonDelayed = delayed;
00410 }
00411
00412 bool KTabBar::hoverCloseButtonDelayed() const
00413 {
00414 return mHoverCloseButtonDelayed;
00415 }
00416
00417 void KTabBar::onLayoutChange()
00418 {
00419 mEnableCloseButtonTimer->stop();
00420 delete mHoverCloseButton;
00421 mHoverCloseButton = 0;
00422 mHoverCloseButtonTab = 0;
00423 mActivateDragSwitchTabTimer->stop();
00424 mDragSwitchTab = 0;
00425 }
00426
00427 #include "ktabbar.moc"