kdelibs/kdeui/widgets/ktabbar.cpp

321 lines
9.1 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/* This file is part of the KDE libraries
Copyright (C) 2003 Stephan Binner <binner@kde.org>
Copyright (C) 2003 Zack Rusin <zack@kde.org>
Copyright (C) 2009 Urs Wolfer <uwolfer @ kde.org>
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 <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QCursor>
#include <QtGui/qevent.h>
2014-11-13 01:04:59 +02:00
#include <kglobalsettings.h>
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) {
2014-11-13 01:04:59 +02:00
// 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() ) {
2014-11-13 01:04:59 +02:00
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() ) {
2014-11-13 01:04:59 +02:00
// 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:
2014-11-13 01:04:59 +02:00
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 );
}
#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 // QT_NO_WHEELEVENT
2014-11-13 01:04:59 +02:00
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;
}
#include "moc_ktabbar.cpp"