KDEUI
ktabbar.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2003 Stephan Binner <binner@kde.org> 00003 Copyright (C) 2003 Zack Rusin <zack@kde.org> 00004 Copyright (C) 2009 Urs Wolfer <uwolfer @ kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "ktabbar.h" 00023 #include "ktabwidget.h" 00024 00025 #include <QtCore/QTimer> 00026 #include <QtGui/QApplication> 00027 #include <QtGui/QCursor> 00028 #include <QtGui/QMouseEvent> 00029 #include <QtGui/QPainter> 00030 #include <QtGui/QPushButton> 00031 #include <QtGui/QStyle> 00032 #include <QtGui/QStyleOption> 00033 00034 #include <kglobalsettings.h> 00035 #include <kicon.h> 00036 #include <kiconeffect.h> 00037 #include <kiconloader.h> 00038 #include <klocale.h> 00039 #include <kstyle.h> 00040 00041 class KTabBar::Private 00042 { 00043 public: 00044 Private() 00045 : mReorderStartTab( -1 ), 00046 mReorderPreviousTab( -1 ), 00047 mDragSwitchTab( -1 ), 00048 mActivateDragSwitchTabTimer( 0 ), 00049 mTabReorderingEnabled( false ), 00050 mMiddleMouseTabMoveInProgress( false) 00051 { 00052 } 00053 00054 QPoint mDragStart; 00055 int mReorderStartTab; 00056 int mReorderPreviousTab; 00057 int mDragSwitchTab; 00058 QTimer *mActivateDragSwitchTabTimer; 00059 00060 bool mTabReorderingEnabled : 1; 00061 bool mMiddleMouseTabMoveInProgress : 1; 00062 00063 }; 00064 00065 KTabBar::KTabBar( QWidget *parent ) 00066 : QTabBar( parent ), 00067 d( new Private ) 00068 { 00069 setAcceptDrops( true ); 00070 setMouseTracking( true ); 00071 00072 d->mActivateDragSwitchTabTimer = new QTimer( this ); 00073 d->mActivateDragSwitchTabTimer->setSingleShot( true ); 00074 connect( d->mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) ); 00075 connect( this, SIGNAL(tabCloseRequested(int)), this, SIGNAL(closeRequest(int))); // just for backward compatibility, KDE5 remove 00076 00077 //connect( this, SIGNAL( layoutChanged() ), SLOT( onLayoutChange() ) ); 00078 } 00079 00080 KTabBar::~KTabBar() 00081 { 00082 delete d; 00083 } 00084 00085 void KTabBar::mouseDoubleClickEvent( QMouseEvent *event ) 00086 { 00087 if ( event->button() != Qt::LeftButton ) 00088 return; 00089 00090 int tab = selectTab( event->pos() ); 00091 00092 if(tab == -1) { 00093 emit newTabRequest(); 00094 } else { 00095 #ifndef KDE_NO_DEPRECATED 00096 emit mouseDoubleClick( tab ); //deprecated 00097 #endif 00098 emit tabDoubleClicked( tab ); 00099 } 00100 00101 QTabBar::mouseDoubleClickEvent( event ); 00102 } 00103 00104 void KTabBar::mousePressEvent( QMouseEvent *event ) 00105 { 00106 if ( event->button() == Qt::LeftButton ) { 00107 d->mDragStart = event->pos(); 00108 } else if( event->button() == Qt::RightButton ) { 00109 int tab = selectTab( event->pos() ); 00110 if ( tab != -1 ) { 00111 emit contextMenu( tab, mapToGlobal( event->pos() ) ); 00112 } else { 00113 emit emptyAreaContextMenu( mapToGlobal( event->pos() ) ); 00114 } 00115 return; 00116 } else if (QTabBar::isMovable() && event->button() == Qt::MidButton) { 00117 // compatibility feature for old middle mouse tab moving 00118 event->accept(); 00119 QMouseEvent fakedMouseEvent(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); 00120 QCoreApplication::sendEvent(this, &fakedMouseEvent); 00121 } 00122 00123 QTabBar::mousePressEvent( event ); 00124 } 00125 00126 void KTabBar::mouseMoveEvent( QMouseEvent *event ) 00127 { 00128 if ( event->buttons() == Qt::LeftButton && !isMovable() ) { 00129 int tab = selectTab( event->pos() ); 00130 if ( d->mDragSwitchTab && tab != d->mDragSwitchTab ) { 00131 d->mActivateDragSwitchTabTimer->stop(); 00132 d->mDragSwitchTab = 0; 00133 } 00134 00135 int delay = KGlobalSettings::dndEventDelay(); 00136 QPoint newPos = event->pos(); 00137 if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay || 00138 newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) { 00139 if ( tab != -1 ) { 00140 emit initiateDrag( tab ); 00141 return; 00142 } 00143 } 00144 } else if ( event->buttons() == Qt::MidButton && !isMovable() ) { 00145 if ( d->mReorderStartTab == -1 ) { 00146 int delay = KGlobalSettings::dndEventDelay(); 00147 QPoint newPos = event->pos(); 00148 00149 if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay || 00150 newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) { 00151 int tab = selectTab( event->pos() ); 00152 if ( tab != -1 && d->mTabReorderingEnabled ) { 00153 d->mReorderStartTab = tab; 00154 grabMouse( Qt::SizeAllCursor ); 00155 return; 00156 } 00157 } 00158 } else { 00159 int tab = selectTab( event->pos() ); 00160 if ( tab != -1 ) { 00161 int reorderStopTab = tab; 00162 if ( d->mReorderStartTab != reorderStopTab && d->mReorderPreviousTab != reorderStopTab ) { 00163 emit moveTab( d->mReorderStartTab, reorderStopTab ); 00164 00165 d->mReorderPreviousTab = d->mReorderStartTab; 00166 d->mReorderStartTab = reorderStopTab; 00167 00168 return; 00169 } 00170 } 00171 } 00172 } else if ( event->button() == Qt::NoButton && event->buttons() == Qt::MidButton && isMovable() ) { 00173 // compatibility feature for old middle mouse tab moving 00174 d->mMiddleMouseTabMoveInProgress = true; 00175 event->accept(); 00176 QMouseEvent fakedMouseEvent(event->type(), event->pos(), event->button(), Qt::LeftButton, event->modifiers()); 00177 QCoreApplication::sendEvent(this, &fakedMouseEvent); 00178 return; 00179 } 00180 00181 QTabBar::mouseMoveEvent( event ); 00182 } 00183 00184 00185 #ifndef KDE_NO_DEPRECATED 00186 void KTabBar::closeButtonClicked() 00187 { 00188 // deprecated 00189 } 00190 #endif 00191 00192 00193 #ifndef KDE_NO_DEPRECATED 00194 void KTabBar::enableCloseButton() 00195 { 00196 // deprecated 00197 } 00198 #endif 00199 00200 00201 void KTabBar::activateDragSwitchTab() 00202 { 00203 int tab = selectTab( mapFromGlobal( QCursor::pos() ) ); 00204 if ( tab != -1 && d->mDragSwitchTab == tab ) 00205 setCurrentIndex( d->mDragSwitchTab ); 00206 00207 d->mDragSwitchTab = 0; 00208 } 00209 00210 void KTabBar::mouseReleaseEvent( QMouseEvent *event ) 00211 { 00212 switch ( event->button() ) { 00213 case Qt::LeftButton: 00214 break; 00215 00216 case Qt::MidButton: 00217 if (d->mMiddleMouseTabMoveInProgress && QTabBar::isMovable()) { 00218 // compatibility feature for old middle mouse tab moving 00219 d->mMiddleMouseTabMoveInProgress = false; 00220 event->accept(); 00221 QMouseEvent fakedMouseEvent(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); 00222 QCoreApplication::sendEvent(this, &fakedMouseEvent); 00223 return; 00224 } 00225 if ( d->mReorderStartTab == -1 ) { 00226 int tab = selectTab( event->pos() ); 00227 if ( tab != -1 ) { 00228 event->accept(); 00229 if (QTabBar::isMovable()) { 00230 QMouseEvent fakedMouseEvent(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); 00231 QCoreApplication::sendEvent(this, &fakedMouseEvent); 00232 } 00233 emit mouseMiddleClick( tab ); 00234 return; 00235 } 00236 } else { 00237 releaseMouse(); 00238 setCursor( Qt::ArrowCursor ); 00239 d->mReorderStartTab = -1; 00240 d->mReorderPreviousTab = -1; 00241 } 00242 break; 00243 00244 default: 00245 break; 00246 } 00247 00248 QTabBar::mouseReleaseEvent( event ); 00249 } 00250 00251 void KTabBar::dragEnterEvent( QDragEnterEvent *event ) 00252 { 00253 int tab = selectTab( event->pos() ); 00254 if ( tab != -1 ) { 00255 bool accept = false; 00256 // The receivers of the testCanDecode() signal has to adjust 00257 // 'accept' accordingly. 00258 emit testCanDecode( event, accept ); 00259 if ( accept && tab != currentIndex() ) { 00260 d->mDragSwitchTab = tab; 00261 d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 ); 00262 } 00263 00264 event->setAccepted( accept ); 00265 return; 00266 } 00267 00268 QTabBar::dragEnterEvent( event ); 00269 } 00270 00271 void KTabBar::dragMoveEvent( QDragMoveEvent *event ) 00272 { 00273 int tab = selectTab( event->pos() ); 00274 if ( tab != -1 ) { 00275 bool accept = false; 00276 // The receivers of the testCanDecode() signal has to adjust 00277 // 'accept' accordingly. 00278 emit testCanDecode( event, accept ); 00279 if ( accept && tab != currentIndex() ) { 00280 d->mDragSwitchTab = tab; 00281 d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 ); 00282 } 00283 00284 event->setAccepted( accept ); 00285 return; 00286 } 00287 00288 QTabBar::dragMoveEvent( event ); 00289 } 00290 00291 void KTabBar::dropEvent( QDropEvent *event ) 00292 { 00293 int tab = selectTab( event->pos() ); 00294 if ( tab != -1 ) { 00295 d->mActivateDragSwitchTabTimer->stop(); 00296 d->mDragSwitchTab = 0; 00297 emit receivedDropEvent( tab , event ); 00298 return; 00299 } 00300 00301 QTabBar::dropEvent( event ); 00302 } 00303 00304 void KTabBar::paintEvent( QPaintEvent *event ) 00305 { 00306 QTabBar::paintEvent( event ); 00307 } 00308 00309 void KTabBar::leaveEvent( QEvent *event ) 00310 { 00311 QTabBar::leaveEvent( event ); 00312 } 00313 00314 QSize KTabBar::tabSizeHint( int index ) const 00315 { 00316 QSize size = QTabBar::tabSizeHint( index ); 00317 00318 return size; 00319 } 00320 00321 #ifndef QT_NO_WHEELEVENT 00322 void KTabBar::wheelEvent( QWheelEvent *event ) 00323 { 00324 if ( !( event->orientation() == Qt::Horizontal ) ) { 00325 if ( receivers( SIGNAL(wheelDelta(int)) ) ) { 00326 emit( wheelDelta( event->delta() ) ); 00327 return; 00328 } 00329 int lastIndex = count() - 1; 00330 //Set an invalid index as base case 00331 int targetIndex = -1; 00332 bool forward = event->delta() < 0; 00333 if ( forward && lastIndex == currentIndex() ) { 00334 targetIndex = 0; 00335 } 00336 else if ( !forward && 0 == currentIndex() ) { 00337 targetIndex = lastIndex; 00338 } 00339 //Will not move when targetIndex is invalid 00340 setCurrentIndex( targetIndex ); 00341 //If it has not moved yet (targetIndex == -1), or if it moved but current tab is disabled 00342 if ( targetIndex != currentIndex() || !isTabEnabled( targetIndex ) ) { 00343 QTabBar::wheelEvent( event ); 00344 } 00345 event->accept(); 00346 } else { 00347 event->ignore(); 00348 } 00349 } 00350 #endif 00351 00352 #ifndef KDE_NO_DEPRECATED 00353 bool KTabBar::isTabReorderingEnabled() const 00354 { 00355 return d->mTabReorderingEnabled; 00356 } 00357 #endif 00358 00359 #ifndef KDE_NO_DEPRECATED 00360 void KTabBar::setTabReorderingEnabled( bool on ) 00361 { 00362 d->mTabReorderingEnabled = on; 00363 } 00364 #endif 00365 00366 #ifndef KDE_NO_DEPRECATED 00367 bool KTabBar::tabCloseActivatePrevious() const 00368 { 00369 return selectionBehaviorOnRemove() == QTabBar::SelectPreviousTab; 00370 } 00371 #endif 00372 00373 #ifndef KDE_NO_DEPRECATED 00374 void KTabBar::setTabCloseActivatePrevious( bool on ) 00375 { 00376 setSelectionBehaviorOnRemove(on ? QTabBar::SelectPreviousTab : QTabBar::SelectRightTab); 00377 } 00378 #endif 00379 00380 00381 #ifndef KDE_NO_DEPRECATED 00382 void KTabBar::setHoverCloseButton( bool button ) 00383 { 00384 // deprecated 00385 setTabsClosable(button); 00386 } 00387 #endif 00388 00389 #ifndef KDE_NO_DEPRECATED 00390 bool KTabBar::hoverCloseButton() const 00391 { 00392 // deprecated 00393 return tabsClosable(); 00394 } 00395 #endif 00396 00397 #ifndef KDE_NO_DEPRECATED 00398 void KTabBar::setHoverCloseButtonDelayed( bool delayed ) 00399 { 00400 // deprecated 00401 Q_UNUSED( delayed ); 00402 } 00403 #endif 00404 00405 #ifndef KDE_NO_DEPRECATED 00406 bool KTabBar::hoverCloseButtonDelayed() const 00407 { 00408 // deprecated 00409 return false; 00410 } 00411 #endif 00412 00413 #ifndef KDE_NO_DEPRECATED 00414 void KTabBar::setCloseButtonEnabled( bool enable ) 00415 { 00416 QTabBar::setTabsClosable(enable); 00417 } 00418 #endif 00419 00420 #ifndef KDE_NO_DEPRECATED 00421 bool KTabBar::isCloseButtonEnabled() const 00422 { 00423 return QTabBar::tabsClosable(); 00424 } 00425 #endif 00426 00427 void KTabBar::tabLayoutChange() 00428 { 00429 d->mActivateDragSwitchTabTimer->stop(); 00430 d->mDragSwitchTab = 0; 00431 } 00432 00433 int KTabBar::selectTab( const QPoint &pos ) const 00434 { 00435 const int tabCount = count(); 00436 for ( int i = 0; i < tabCount; ++i ) 00437 if ( tabRect( i ).contains( pos ) ) 00438 return i; 00439 00440 return -1; 00441 } 00442 00443 QPoint KTabBar::closeButtonPos( int tabIndex ) const 00444 { 00445 Q_UNUSED(tabIndex); 00446 return QPoint(); 00447 } 00448 00449 QRect KTabBar::closeButtonRect( int tabIndex ) const 00450 { 00451 Q_UNUSED(tabIndex); 00452 return QRect(); 00453 } 00454 00455 #include "ktabbar.moc"
KDE 4.6 API Reference