KDEUI
ktabbar.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ktabbar.h"
00022 #include "ktabwidget.h"
00023
00024 #include <QtCore/QTimer>
00025 #include <QtGui/QApplication>
00026 #include <QtGui/QCursor>
00027 #include <QtGui/QMouseEvent>
00028 #include <QtGui/QPainter>
00029 #include <QtGui/QPushButton>
00030 #include <QtGui/QStyle>
00031 #include <QtGui/QStyleOption>
00032
00033 #include <kglobalsettings.h>
00034 #include <kicon.h>
00035 #include <kiconeffect.h>
00036 #include <kiconloader.h>
00037 #include <klocale.h>
00038 #include <kstyle.h>
00039
00040 class KTabBar::Private
00041 {
00042 public:
00043 Private()
00044 : mReorderStartTab( -1 ),
00045 mReorderPreviousTab( -1 ),
00046 mDragSwitchTab( -1 ),
00047 mHoveredCloseIconIndex( -1 ),
00048 mActivateDragSwitchTabTimer( 0 ),
00049 mHoveredCloseIcon( 0 ),
00050 mInactiveCloseIcon( 0 ),
00051 mActiveCloseIcon( 0 ),
00052 mTabReorderingEnabled( false ),
00053 mTabCloseActivatePrevious( false ),
00054 mTabCloseButtonClicked( false )
00055 {
00056 }
00057
00058 QPoint mDragStart;
00059 int mReorderStartTab;
00060 int mReorderPreviousTab;
00061 int mDragSwitchTab;
00062 int mHoveredCloseIconIndex;
00063
00064 QTimer *mActivateDragSwitchTabTimer;
00065 QPixmap *mHoveredCloseIcon;
00066 QPixmap *mInactiveCloseIcon;
00067 QPixmap *mActiveCloseIcon;
00068
00069 bool mTabReorderingEnabled : 1;
00070 bool mTabCloseActivatePrevious : 1;
00071 bool mTabCloseButtonClicked : 1;
00072
00073 };
00074
00075 KTabBar::KTabBar( QWidget *parent )
00076 : QTabBar( parent ),
00077 d( new Private )
00078 {
00079 setAcceptDrops( true );
00080 setMouseTracking( true );
00081
00082 d->mActivateDragSwitchTabTimer = new QTimer( this );
00083 d->mActivateDragSwitchTabTimer->setSingleShot( true );
00084 connect( d->mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
00085
00086
00087 }
00088
00089 KTabBar::~KTabBar()
00090 {
00091 delete d->mHoveredCloseIcon;
00092 d->mHoveredCloseIcon = 0;
00093
00094 delete d->mInactiveCloseIcon;
00095 d->mInactiveCloseIcon = 0;
00096
00097 delete d->mActiveCloseIcon;
00098 d->mActiveCloseIcon = 0;
00099
00100 delete d;
00101 }
00102
00103 void KTabBar::mouseDoubleClickEvent( QMouseEvent *event )
00104 {
00105 if ( event->button() != Qt::LeftButton )
00106 return;
00107
00108 int tab = selectTab( event->pos() );
00109
00110 if(tab == -1) {
00111 emit newTabRequest();
00112 } else {
00113 emit mouseDoubleClick( tab );
00114 emit tabDoubleClicked( tab );
00115 }
00116 }
00117
00118 void KTabBar::mousePressEvent( QMouseEvent *event )
00119 {
00120 if ( event->button() == Qt::LeftButton ) {
00121 d->mDragStart = event->pos();
00122 if ( isCloseButtonEnabled() ) {
00123 const QPoint pos = event->pos();
00124 const int tabIndex = tabAt( pos );
00125 if (closeButtonRect( tabIndex ).contains( pos )) {
00126
00127 d->mTabCloseButtonClicked = true;
00128 return;
00129 }
00130 }
00131 } else if( event->button() == Qt::RightButton ) {
00132 int tab = selectTab( event->pos() );
00133 if ( tab != -1 ) {
00134 emit contextMenu( tab, mapToGlobal( event->pos() ) );
00135 } else {
00136 emit emptyAreaContextMenu( mapToGlobal( event->pos() ) );
00137 }
00138 return;
00139 }
00140
00141 QTabBar::mousePressEvent( event );
00142 }
00143
00144 void KTabBar::mouseMoveEvent( QMouseEvent *event )
00145 {
00146 if ( isCloseButtonEnabled() ) {
00147 if ( d->mHoveredCloseIconIndex >= 0) {
00148
00149 update( closeButtonRect( d->mHoveredCloseIconIndex ));
00150 d->mHoveredCloseIconIndex = -1;
00151 }
00152
00153 const QPoint pos = event->pos();
00154 const int tabCount = count();
00155 for ( int i = 0; i < tabCount; ++i ) {
00156 const QRect rect = closeButtonRect( i );
00157 if (rect.contains( pos )) {
00158
00159 d->mHoveredCloseIconIndex = i;
00160 update( rect );
00161 break;
00162 }
00163 }
00164 }
00165
00166 if ( event->buttons() == Qt::LeftButton ) {
00167 int tab = selectTab( event->pos() );
00168 if ( d->mDragSwitchTab && tab != d->mDragSwitchTab ) {
00169 d->mActivateDragSwitchTabTimer->stop();
00170 d->mDragSwitchTab = 0;
00171 }
00172
00173 int delay = KGlobalSettings::dndEventDelay();
00174 QPoint newPos = event->pos();
00175 if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay ||
00176 newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) {
00177 if ( tab != -1 ) {
00178 emit initiateDrag( tab );
00179 return;
00180 }
00181 }
00182 } else if ( event->buttons() == Qt::MidButton ) {
00183 if ( d->mReorderStartTab == -1 ) {
00184 int delay = KGlobalSettings::dndEventDelay();
00185 QPoint newPos = event->pos();
00186
00187 if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay ||
00188 newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) {
00189 int tab = selectTab( event->pos() );
00190 if ( tab != -1 && d->mTabReorderingEnabled ) {
00191 d->mReorderStartTab = tab;
00192 grabMouse( Qt::SizeAllCursor );
00193 return;
00194 }
00195 }
00196 } else {
00197 int tab = selectTab( event->pos() );
00198 if ( tab != -1 ) {
00199 int reorderStopTab = tab;
00200 if ( d->mReorderStartTab != reorderStopTab && d->mReorderPreviousTab != reorderStopTab ) {
00201 emit moveTab( d->mReorderStartTab, reorderStopTab );
00202
00203 d->mReorderPreviousTab = d->mReorderStartTab;
00204 d->mReorderStartTab = reorderStopTab;
00205
00206 return;
00207 }
00208 }
00209 }
00210 }
00211
00212 QTabBar::mouseMoveEvent( event );
00213 }
00214
00215
00216 void KTabBar::closeButtonClicked()
00217 {
00218
00219 }
00220
00221
00222 void KTabBar::enableCloseButton()
00223 {
00224
00225 }
00226
00227
00228 void KTabBar::activateDragSwitchTab()
00229 {
00230 int tab = selectTab( mapFromGlobal( QCursor::pos() ) );
00231 if ( tab != -1 && d->mDragSwitchTab == tab )
00232 setCurrentIndex( d->mDragSwitchTab );
00233
00234 d->mDragSwitchTab = 0;
00235 }
00236
00237 void KTabBar::mouseReleaseEvent( QMouseEvent *event )
00238 {
00239 switch ( event->button() ) {
00240 case Qt::LeftButton:
00241 if ( isCloseButtonEnabled() ) {
00242 update(closeButtonRect( d->mHoveredCloseIconIndex ));
00243
00244 const QPoint pos = event->pos();
00245 const int tabIndex = tabAt( pos );
00246 if (d->mTabCloseButtonClicked && closeButtonRect( tabIndex ).contains( pos )) {
00247 d->mHoveredCloseIconIndex = -1;
00248 emit closeRequest( tabIndex );
00249 }
00250 }
00251 break;
00252
00253 case Qt::MidButton:
00254 if ( d->mReorderStartTab == -1 ) {
00255 int tab = selectTab( event->pos() );
00256 if ( tab != -1 ) {
00257 emit mouseMiddleClick( tab );
00258 return;
00259 }
00260 } else {
00261 releaseMouse();
00262 setCursor( Qt::ArrowCursor );
00263 d->mReorderStartTab = -1;
00264 d->mReorderPreviousTab = -1;
00265 }
00266 break;
00267
00268 default:
00269 break;
00270 }
00271
00272 d->mTabCloseButtonClicked = false;
00273 QTabBar::mouseReleaseEvent( event );
00274 }
00275
00276 void KTabBar::dragEnterEvent( QDragEnterEvent *event )
00277 {
00278 int tab = selectTab( event->pos() );
00279 if ( tab != -1 ) {
00280 bool accept = false;
00281
00282
00283 emit testCanDecode( event, accept );
00284 if ( accept && tab != currentIndex() ) {
00285 d->mDragSwitchTab = tab;
00286 d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 );
00287 }
00288
00289 event->setAccepted( accept );
00290 return;
00291 }
00292
00293 QTabBar::dragEnterEvent( event );
00294 }
00295
00296 void KTabBar::dragMoveEvent( QDragMoveEvent *event )
00297 {
00298 int tab = selectTab( event->pos() );
00299 if ( tab != -1 ) {
00300 bool accept = false;
00301
00302
00303 emit testCanDecode( event, accept );
00304 if ( accept && tab != currentIndex() ) {
00305 d->mDragSwitchTab = tab;
00306 d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 );
00307 }
00308
00309 event->setAccepted( accept );
00310 return;
00311 }
00312
00313 QTabBar::dragMoveEvent( event );
00314 }
00315
00316 void KTabBar::dropEvent( QDropEvent *event )
00317 {
00318 int tab = selectTab( event->pos() );
00319 if ( tab != -1 ) {
00320 d->mActivateDragSwitchTabTimer->stop();
00321 d->mDragSwitchTab = 0;
00322 emit receivedDropEvent( tab , event );
00323 return;
00324 }
00325
00326 QTabBar::dropEvent( event );
00327 }
00328
00329 void KTabBar::paintEvent( QPaintEvent *event )
00330 {
00331 QTabBar::paintEvent( event );
00332
00333 if ( isCloseButtonEnabled() ) {
00334 QPainter painter( this );
00335 const int tabCount = count();
00336 for ( int i = 0; i < tabCount; ++i ) {
00337 QPixmap icon;
00338 if ( i == d->mHoveredCloseIconIndex)
00339 icon = *d->mActiveCloseIcon;
00340 else if ( i == currentIndex() )
00341 icon = *d->mHoveredCloseIcon;
00342 else
00343 icon = *d->mInactiveCloseIcon;
00344
00345 painter.drawPixmap( closeButtonPos( i ), icon );
00346 }
00347 }
00348 }
00349
00350 void KTabBar::leaveEvent( QEvent *event )
00351 {
00352 QTabBar::leaveEvent( event );
00353 if ( d->mHoveredCloseIconIndex >= 0 ) {
00354 update( closeButtonRect( d->mHoveredCloseIconIndex ));
00355 d->mHoveredCloseIconIndex = -1;
00356 }
00357 }
00358
00359 QSize KTabBar::tabSizeHint( int index ) const
00360 {
00361 QSize size = QTabBar::tabSizeHint( index );
00362 if ( isCloseButtonEnabled() )
00363 size.rwidth() += KIconLoader::SizeSmall * 3 / 2;
00364
00365 return size;
00366 }
00367
00368 #ifndef QT_NO_WHEELEVENT
00369 void KTabBar::wheelEvent( QWheelEvent *event )
00370 {
00371 if ( event->orientation() == Qt::Horizontal )
00372 return;
00373
00374 emit( wheelDelta( event->delta() ) );
00375 }
00376 #endif
00377
00378 bool KTabBar::isTabReorderingEnabled() const
00379 {
00380 return d->mTabReorderingEnabled;
00381 }
00382
00383 void KTabBar::setTabReorderingEnabled( bool on )
00384 {
00385 d->mTabReorderingEnabled = on;
00386 }
00387
00388 bool KTabBar::tabCloseActivatePrevious() const
00389 {
00390 return d->mTabCloseActivatePrevious;
00391 }
00392
00393 void KTabBar::setTabCloseActivatePrevious( bool on )
00394 {
00395 d->mTabCloseActivatePrevious = on;
00396 }
00397
00398
00399 void KTabBar::setHoverCloseButton( bool button )
00400 {
00401
00402 setCloseButtonEnabled( button );
00403 }
00404
00405 bool KTabBar::hoverCloseButton() const
00406 {
00407
00408 return isCloseButtonEnabled();
00409 }
00410
00411 void KTabBar::setHoverCloseButtonDelayed( bool delayed )
00412 {
00413
00414 Q_UNUSED( delayed );
00415 }
00416
00417 bool KTabBar::hoverCloseButtonDelayed() const
00418 {
00419
00420 return false;
00421 }
00422
00423 void KTabBar::setCloseButtonEnabled( bool enable )
00424 {
00425 if ( enable == isCloseButtonEnabled() )
00426 return;
00427
00428 d->mHoveredCloseIconIndex = -1;
00429 if ( enable ) {
00430 Q_ASSERT( d->mHoveredCloseIcon == 0 );
00431 Q_ASSERT( d->mInactiveCloseIcon == 0 );
00432 Q_ASSERT( d->mActiveCloseIcon == 0 );
00433
00434 const QPixmap icon = KIconLoader::global()->loadIcon( "dialog-close", KIconLoader::Small );
00435
00436 d->mHoveredCloseIcon = new QPixmap( icon );
00437 KIconEffect::semiTransparent( *d->mHoveredCloseIcon );
00438
00439 KIconEffect iconEffect;
00440 d->mInactiveCloseIcon = new QPixmap( iconEffect.apply( icon, KIconLoader::Small, KIconLoader::DisabledState ));
00441
00442 KIconEffect::semiTransparent( *d->mInactiveCloseIcon );
00443 d->mActiveCloseIcon = new QPixmap( icon );
00444 } else {
00445 delete d->mHoveredCloseIcon;
00446 d->mHoveredCloseIcon = 0;
00447
00448 delete d->mInactiveCloseIcon;
00449 d->mInactiveCloseIcon = 0;
00450
00451 delete d->mActiveCloseIcon;
00452 d->mActiveCloseIcon = 0;
00453 }
00454 }
00455
00456 bool KTabBar::isCloseButtonEnabled() const
00457 {
00458 return d->mHoveredCloseIcon != 0;
00459 }
00460
00461 void KTabBar::tabLayoutChange()
00462 {
00463 d->mActivateDragSwitchTabTimer->stop();
00464 d->mDragSwitchTab = 0;
00465 }
00466
00467 int KTabBar::selectTab( const QPoint &pos ) const
00468 {
00469 const int tabCount = count();
00470 for ( int i = 0; i < tabCount; ++i )
00471 if ( tabRect( i ).contains( pos ) )
00472 return i;
00473
00474 return -1;
00475 }
00476
00477 QPoint KTabBar::closeButtonPos( int tabIndex ) const
00478 {
00479 QPoint buttonPos;
00480 if ( tabIndex < 0 ) {
00481 return buttonPos;
00482 }
00483
00484 int availableHeight = height();
00485 if ( tabIndex == currentIndex() ) {
00486 QStyleOption option;
00487 option.initFrom(this);
00488 availableHeight -= style()->pixelMetric( QStyle::PM_TabBarTabShiftVertical, &option, this );
00489 }
00490
00491 const QRect tabBounds = tabRect( tabIndex );
00492 const int xInc = (height() - KIconLoader::SizeSmall) / 2;
00493
00494 if ( layoutDirection() == Qt::RightToLeft ) {
00495 buttonPos = tabBounds.topLeft();
00496 buttonPos.rx() += xInc;
00497 } else {
00498 buttonPos = tabBounds.topRight();
00499 buttonPos.rx() -= KIconLoader::SizeSmall + xInc;
00500 }
00501 buttonPos.ry() += (availableHeight - KIconLoader::SizeSmall) / 2;
00502
00503 return buttonPos;
00504 }
00505
00506 QRect KTabBar::closeButtonRect( int tabIndex ) const
00507 {
00508 QRect rect;
00509 if ( tabIndex >= 0 ) {
00510 rect.setTopLeft(closeButtonPos( tabIndex ));
00511 rect.setSize(QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall));
00512 }
00513 return rect;
00514 }
00515
00516 #include "ktabbar.moc"