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 )
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
00058
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
00164
00165
00166
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
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
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
00265
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
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"