/* This file is part of the KDE libraries Copyright (C) 2003 Stephan Binner Copyright (C) 2003 Zack Rusin Copyright (C) 2009 Urs Wolfer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ktabbar.h" #include #include #include #include #include class KTabBar::Private { public: Private() : mReorderStartTab( -1 ), mReorderPreviousTab( -1 ), mDragSwitchTab( -1 ), mActivateDragSwitchTabTimer( 0 ), mTabReorderingEnabled( false ), mMiddleMouseTabMoveInProgress( false) { } QPoint mDragStart; int mReorderStartTab; int mReorderPreviousTab; int mDragSwitchTab; QTimer *mActivateDragSwitchTabTimer; bool mTabReorderingEnabled : 1; bool mMiddleMouseTabMoveInProgress : 1; }; KTabBar::KTabBar( QWidget *parent ) : QTabBar( parent ), d( new Private ) { setAcceptDrops( true ); setMouseTracking( true ); d->mActivateDragSwitchTabTimer = new QTimer( this ); d->mActivateDragSwitchTabTimer->setSingleShot( true ); connect( d->mActivateDragSwitchTabTimer, SIGNAL(timeout()), SLOT(activateDragSwitchTab()) ); //connect( this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()) ); } KTabBar::~KTabBar() { delete d; } void KTabBar::mouseDoubleClickEvent( QMouseEvent *event ) { if ( event->button() != Qt::LeftButton ) return; int tab = selectTab( event->pos() ); if(tab == -1) { emit newTabRequest(); } else { emit tabDoubleClicked( tab ); } QTabBar::mouseDoubleClickEvent( event ); } void KTabBar::mousePressEvent( QMouseEvent *event ) { if ( event->button() == Qt::LeftButton ) { d->mDragStart = event->pos(); } else if( event->button() == Qt::RightButton ) { int tab = selectTab( event->pos() ); if ( tab != -1 ) { emit contextMenu( tab, mapToGlobal( event->pos() ) ); } else { emit emptyAreaContextMenu( mapToGlobal( event->pos() ) ); } return; } else if (QTabBar::isMovable() && event->button() == Qt::MiddleButton) { // compatibility feature for old middle mouse tab moving event->accept(); QMouseEvent fakedMouseEvent(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); QCoreApplication::sendEvent(this, &fakedMouseEvent); } QTabBar::mousePressEvent( event ); } void KTabBar::mouseMoveEvent( QMouseEvent *event ) { if ( event->buttons() == Qt::LeftButton && !isMovable() ) { int tab = selectTab( event->pos() ); if ( d->mDragSwitchTab && tab != d->mDragSwitchTab ) { d->mActivateDragSwitchTabTimer->stop(); d->mDragSwitchTab = 0; } int delay = KGlobalSettings::dndEventDelay(); QPoint newPos = event->pos(); if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay || newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) { if ( tab != -1 ) { emit initiateDrag( tab ); return; } } } else if ( event->buttons() == Qt::MiddleButton && !isMovable() ) { if ( d->mReorderStartTab == -1 ) { int delay = KGlobalSettings::dndEventDelay(); QPoint newPos = event->pos(); if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay || newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) { int tab = selectTab( event->pos() ); if ( tab != -1 && d->mTabReorderingEnabled ) { d->mReorderStartTab = tab; grabMouse( Qt::SizeAllCursor ); return; } } } else { int tab = selectTab( event->pos() ); if ( tab != -1 ) { int reorderStopTab = tab; if ( d->mReorderStartTab != reorderStopTab && d->mReorderPreviousTab != reorderStopTab ) { emit moveTab( d->mReorderStartTab, reorderStopTab ); d->mReorderPreviousTab = d->mReorderStartTab; d->mReorderStartTab = reorderStopTab; return; } } } } else if ( event->button() == Qt::NoButton && event->buttons() == Qt::MiddleButton && isMovable() ) { // compatibility feature for old middle mouse tab moving d->mMiddleMouseTabMoveInProgress = true; event->accept(); QMouseEvent fakedMouseEvent(event->type(), event->pos(), event->button(), Qt::LeftButton, event->modifiers()); QCoreApplication::sendEvent(this, &fakedMouseEvent); return; } QTabBar::mouseMoveEvent( event ); } void KTabBar::activateDragSwitchTab() { int tab = selectTab( mapFromGlobal( QCursor::pos() ) ); if ( tab != -1 && d->mDragSwitchTab == tab ) setCurrentIndex( d->mDragSwitchTab ); d->mDragSwitchTab = 0; } void KTabBar::mouseReleaseEvent( QMouseEvent *event ) { switch ( event->button() ) { case Qt::LeftButton: break; case Qt::MiddleButton: if (d->mMiddleMouseTabMoveInProgress && QTabBar::isMovable()) { // compatibility feature for old middle mouse tab moving d->mMiddleMouseTabMoveInProgress = false; event->accept(); QMouseEvent fakedMouseEvent(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); QCoreApplication::sendEvent(this, &fakedMouseEvent); return; } if ( d->mReorderStartTab == -1 ) { int tab = selectTab( event->pos() ); if ( tab != -1 ) { event->accept(); if (QTabBar::isMovable()) { QMouseEvent fakedMouseEvent(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); QCoreApplication::sendEvent(this, &fakedMouseEvent); } emit mouseMiddleClick( tab ); return; } } else { releaseMouse(); setCursor( Qt::ArrowCursor ); d->mReorderStartTab = -1; d->mReorderPreviousTab = -1; } break; default: break; } QTabBar::mouseReleaseEvent( event ); } void KTabBar::dragEnterEvent( QDragEnterEvent *event ) { int tab = selectTab( event->pos() ); if ( tab != -1 ) { bool accept = false; // The receivers of the testCanDecode() signal has to adjust // 'accept' accordingly. emit testCanDecode( event, accept ); if ( accept && tab != currentIndex() ) { d->mDragSwitchTab = tab; d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 ); } event->setAccepted( accept ); return; } QTabBar::dragEnterEvent( event ); } void KTabBar::dragMoveEvent( QDragMoveEvent *event ) { int tab = selectTab( event->pos() ); if ( tab != -1 ) { bool accept = false; // The receivers of the testCanDecode() signal has to adjust // 'accept' accordingly. emit testCanDecode( event, accept ); if ( accept && tab != currentIndex() ) { d->mDragSwitchTab = tab; d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 ); } event->setAccepted( accept ); return; } QTabBar::dragMoveEvent( event ); } void KTabBar::dropEvent( QDropEvent *event ) { int tab = selectTab( event->pos() ); if ( tab != -1 ) { d->mActivateDragSwitchTabTimer->stop(); d->mDragSwitchTab = 0; emit receivedDropEvent( tab , event ); return; } QTabBar::dropEvent( event ); } void KTabBar::paintEvent( QPaintEvent *event ) { QTabBar::paintEvent( event ); } void KTabBar::leaveEvent( QEvent *event ) { QTabBar::leaveEvent( event ); } QSize KTabBar::tabSizeHint( int index ) const { QSize size = QTabBar::tabSizeHint( index ); return size; } #ifndef QT_NO_WHEELEVENT void KTabBar::wheelEvent( QWheelEvent *event ) { if ( !( event->orientation() == Qt::Horizontal ) ) { if ( receivers( SIGNAL(wheelDelta(int)) ) ) { emit( wheelDelta( event->delta() ) ); return; } int lastIndex = count() - 1; //Set an invalid index as base case int targetIndex = -1; bool forward = event->delta() < 0; if ( forward && lastIndex == currentIndex() ) { targetIndex = 0; } else if ( !forward && 0 == currentIndex() ) { targetIndex = lastIndex; } //Will not move when targetIndex is invalid setCurrentIndex( targetIndex ); //If it has not moved yet (targetIndex == -1), or if it moved but current tab is disabled if ( targetIndex != currentIndex() || !isTabEnabled( targetIndex ) ) { QTabBar::wheelEvent( event ); } event->accept(); } else { event->ignore(); } } #endif void KTabBar::tabLayoutChange() { d->mActivateDragSwitchTabTimer->stop(); d->mDragSwitchTab = 0; } int KTabBar::selectTab( const QPoint &pos ) const { const int tabCount = count(); for ( int i = 0; i < tabCount; ++i ) if ( tabRect( i ).contains( pos ) ) return i; return -1; } QPoint KTabBar::closeButtonPos( int tabIndex ) const { Q_UNUSED(tabIndex); return QPoint(); } QRect KTabBar::closeButtonRect( int tabIndex ) const { Q_UNUSED(tabIndex); return QRect(); } #include "moc_ktabbar.cpp"