/* 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()) ); #ifndef KDE_NO_DEPRECATED connect( this, SIGNAL(tabCloseRequested(int)), this, SIGNAL(closeRequest(int))); // just for backward compatibility, KDE5 remove #endif //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 { #ifndef KDE_NO_DEPRECATED emit mouseDoubleClick( tab ); //deprecated #endif 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::MidButton) { // 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::MidButton && !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::MidButton && 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 ); } #ifndef KDE_NO_DEPRECATED void KTabBar::closeButtonClicked() { // deprecated } #endif #ifndef KDE_NO_DEPRECATED void KTabBar::enableCloseButton() { // deprecated } #endif 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::MidButton: 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 #ifndef KDE_NO_DEPRECATED bool KTabBar::isTabReorderingEnabled() const { return d->mTabReorderingEnabled; } #endif #ifndef KDE_NO_DEPRECATED void KTabBar::setTabReorderingEnabled( bool on ) { d->mTabReorderingEnabled = on; } #endif #ifndef KDE_NO_DEPRECATED bool KTabBar::tabCloseActivatePrevious() const { return selectionBehaviorOnRemove() == QTabBar::SelectPreviousTab; } #endif #ifndef KDE_NO_DEPRECATED void KTabBar::setTabCloseActivatePrevious( bool on ) { setSelectionBehaviorOnRemove(on ? QTabBar::SelectPreviousTab : QTabBar::SelectRightTab); } #endif #ifndef KDE_NO_DEPRECATED void KTabBar::setHoverCloseButton( bool button ) { // deprecated setTabsClosable(button); } #endif #ifndef KDE_NO_DEPRECATED bool KTabBar::hoverCloseButton() const { // deprecated return tabsClosable(); } #endif #ifndef KDE_NO_DEPRECATED void KTabBar::setHoverCloseButtonDelayed( bool delayed ) { // deprecated Q_UNUSED( delayed ); } #endif #ifndef KDE_NO_DEPRECATED bool KTabBar::hoverCloseButtonDelayed() const { // deprecated return false; } #endif #ifndef KDE_NO_DEPRECATED void KTabBar::setCloseButtonEnabled( bool enable ) { QTabBar::setTabsClosable(enable); } #endif #ifndef KDE_NO_DEPRECATED bool KTabBar::isCloseButtonEnabled() const { return QTabBar::tabsClosable(); } #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 "ktabbar.moc"