summaryrefslogtreecommitdiffstats
path: root/kdeui/ktabbar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdeui/ktabbar.cpp')
-rw-r--r--kdeui/ktabbar.cpp427
1 files changed, 427 insertions, 0 deletions
diff --git a/kdeui/ktabbar.cpp b/kdeui/ktabbar.cpp
new file mode 100644
index 000000000..fcac5a975
--- /dev/null
+++ b/kdeui/ktabbar.cpp
@@ -0,0 +1,427 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Stephan Binner <binner@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@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 <qapplication.h>
+#include <qcursor.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qtimer.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include "ktabbar.h"
+#include "ktabwidget.h"
+
+KTabBar::KTabBar( QWidget *parent, const char *name )
+ : QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ),
+ mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ),
+ mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ),
+ mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false )
+{
+ setAcceptDrops( true );
+ setMouseTracking( true );
+
+ mEnableCloseButtonTimer = new QTimer( this );
+ connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) );
+
+ mActivateDragSwitchTabTimer = new QTimer( this );
+ connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
+
+ connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
+}
+
+KTabBar::~KTabBar()
+{
+ //For the future
+ //delete d;
+}
+
+void KTabBar::setTabEnabled( int id, bool enabled )
+{
+ QTab * t = tab( id );
+ if ( t ) {
+ if ( t->isEnabled() != enabled ) {
+ t->setEnabled( enabled );
+ QRect r( t->rect() );
+ if ( !enabled && id == currentTab() && count()>1 ) {
+ QPtrList<QTab> *tablist = tabList();
+ if ( mTabCloseActivatePrevious )
+ t = tablist->at( count()-2 );
+ else {
+ int index = indexOf( id );
+ index += ( index+1 == count() ) ? -1 : 1;
+ t = tabAt( index );
+ }
+
+ if ( t->isEnabled() ) {
+ r = r.unite( t->rect() );
+ tablist->append( tablist->take( tablist->findRef( t ) ) );
+ emit selected( t->identifier() );
+ }
+ }
+ repaint( r );
+ }
+ }
+}
+
+void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
+{
+ if( e->button() != LeftButton )
+ return;
+
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
+ return;
+ }
+ QTabBar::mouseDoubleClickEvent( e );
+}
+
+void KTabBar::mousePressEvent( QMouseEvent *e )
+{
+ if( e->button() == LeftButton ) {
+ mEnableCloseButtonTimer->stop();
+ mDragStart = e->pos();
+ }
+ else if( e->button() == RightButton ) {
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
+ return;
+ }
+ }
+ QTabBar::mousePressEvent( e );
+}
+
+void KTabBar::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( e->state() == LeftButton ) {
+ QTab *tab = selectTab( e->pos() );
+ if ( mDragSwitchTab && tab != mDragSwitchTab ) {
+ mActivateDragSwitchTabTimer->stop();
+ mDragSwitchTab = 0;
+ }
+
+ int delay = KGlobalSettings::dndEventDelay();
+ QPoint newPos = e->pos();
+ if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
+ newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
+ {
+ if( tab ) {
+ emit( initiateDrag( indexOf( tab->identifier() ) ) );
+ return;
+ }
+ }
+ }
+ else if ( e->state() == MidButton ) {
+ if (mReorderStartTab==-1) {
+ int delay = KGlobalSettings::dndEventDelay();
+ QPoint newPos = e->pos();
+ if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
+ newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
+ {
+ QTab *tab = selectTab( e->pos() );
+ if( tab && mTabReorderingEnabled ) {
+ mReorderStartTab = indexOf( tab->identifier() );
+ grabMouse( sizeAllCursor );
+ return;
+ }
+ }
+ }
+ else {
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ int reorderStopTab = indexOf( tab->identifier() );
+ if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
+ emit( moveTab( mReorderStartTab, reorderStopTab ) );
+ mReorderPreviousTab=mReorderStartTab;
+ mReorderStartTab=reorderStopTab;
+ return;
+ }
+ }
+ }
+ }
+
+ if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
+ QTab *t = selectTab( e->pos() );
+ if( t && t->iconSet() && t->isEnabled() ) {
+ QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
+ QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
+
+ int xoff = 0, yoff = 0;
+ // The additional offsets were found by try and error, TODO: find the rational behind them
+ if ( t == tab( currentTab() ) ) {
+ xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
+ yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
+ }
+ else {
+ xoff = 7;
+ yoff = 0;
+ }
+ rect.moveLeft( t->rect().left() + 2 + xoff );
+ rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
+ if ( rect.contains( e->pos() ) ) {
+ if ( mHoverCloseButton ) {
+ if ( mHoverCloseButtonTab == t )
+ return;
+ mEnableCloseButtonTimer->stop();
+ mHoverCloseButton->deleteLater();
+ mHoverCloseButton = 0;
+ }
+
+ mHoverCloseButton = new QPushButton( this );
+ mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIconSet("fileclose", KIcon::Toolbar, KIcon::SizeSmall) );
+ mHoverCloseButton->setGeometry( rect );
+ QToolTip::add(mHoverCloseButton,i18n("Close this tab"));
+ mHoverCloseButton->setFlat(true);
+ mHoverCloseButton->show();
+ if ( mHoverCloseButtonDelayed ) {
+ mHoverCloseButton->setEnabled(false);
+ mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
+ }
+ mHoverCloseButtonTab = t;
+ connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
+ return;
+ }
+ }
+ if ( mHoverCloseButton ) {
+ mEnableCloseButtonTimer->stop();
+ mHoverCloseButton->deleteLater();
+ mHoverCloseButton = 0;
+ }
+ }
+
+ QTabBar::mouseMoveEvent( e );
+}
+
+void KTabBar::enableCloseButton()
+{
+ mHoverCloseButton->setEnabled(true);
+}
+
+void KTabBar::activateDragSwitchTab()
+{
+ QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) );
+ if ( tab && mDragSwitchTab == tab )
+ setCurrentTab( mDragSwitchTab );
+ mDragSwitchTab = 0;
+}
+
+void KTabBar::mouseReleaseEvent( QMouseEvent *e )
+{
+ if( e->button() == MidButton ) {
+ if ( mReorderStartTab==-1 ) {
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
+ return;
+ }
+ }
+ else {
+ releaseMouse();
+ setCursor( arrowCursor );
+ mReorderStartTab=-1;
+ mReorderPreviousTab=-1;
+ }
+ }
+ QTabBar::mouseReleaseEvent( e );
+}
+
+void KTabBar::dragMoveEvent( QDragMoveEvent *e )
+{
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ bool accept = false;
+ // The receivers of the testCanDecode() signal has to adjust
+ // 'accept' accordingly.
+ emit testCanDecode( e, accept);
+ if ( accept && tab != QTabBar::tab( currentTab() ) ) {
+ mDragSwitchTab = tab;
+ mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
+ }
+ e->accept( accept );
+ return;
+ }
+ e->accept( false );
+ QTabBar::dragMoveEvent( e );
+}
+
+void KTabBar::dropEvent( QDropEvent *e )
+{
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ mActivateDragSwitchTabTimer->stop();
+ mDragSwitchTab = 0;
+ emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
+ return;
+ }
+ QTabBar::dropEvent( e );
+}
+
+#ifndef QT_NO_WHEELEVENT
+void KTabBar::wheelEvent( QWheelEvent *e )
+{
+ if ( e->orientation() == Horizontal )
+ return;
+
+ emit( wheelDelta( e->delta() ) );
+}
+#endif
+
+void KTabBar::setTabColor( int id, const QColor& color )
+{
+ QTab *t = tab( id );
+ if ( t ) {
+ mTabColors.insert( id, color );
+ repaint( t->rect(), false );
+ }
+}
+
+const QColor &KTabBar::tabColor( int id ) const
+{
+ if ( mTabColors.contains( id ) )
+ return mTabColors[id];
+
+ return colorGroup().foreground();
+}
+
+int KTabBar::insertTab( QTab *t, int index )
+{
+ int res = QTabBar::insertTab( t, index );
+
+ if ( mTabCloseActivatePrevious && count() > 2 ) {
+ QPtrList<QTab> *tablist = tabList();
+ tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
+ }
+
+ return res;
+}
+
+void KTabBar::removeTab( QTab *t )
+{
+ mTabColors.remove( t->identifier() );
+ QTabBar::removeTab( t );
+}
+
+void KTabBar::paintLabel( QPainter *p, const QRect& br,
+ QTab *t, bool has_focus ) const
+{
+ QRect r = br;
+ bool selected = currentTab() == t->identifier();
+ if ( t->iconSet() ) {
+ // the tab has an iconset, draw it in the right mode
+ QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
+ ? QIconSet::Normal : QIconSet::Disabled;
+ if ( mode == QIconSet::Normal && has_focus )
+ mode = QIconSet::Active;
+ QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
+ int pixw = pixmap.width();
+ int pixh = pixmap.height();
+ r.setLeft( r.left() + pixw + 4 );
+ r.setRight( r.right() + 2 );
+
+ int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
+ int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
+
+ int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
+
+ p->drawPixmap( right + (selected ? 0 : inactiveXShift),
+ br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
+ pixmap );
+ }
+
+ QStyle::SFlags flags = QStyle::Style_Default;
+
+ if ( isEnabled() && t->isEnabled() )
+ flags |= QStyle::Style_Enabled;
+ if ( has_focus )
+ flags |= QStyle::Style_HasFocus;
+
+ QColorGroup cg( colorGroup() );
+ if ( mTabColors.contains( t->identifier() ) )
+ cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
+
+ style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
+ t->isEnabled() ? cg : palette().disabled(),
+ flags, QStyleOption(t) );
+}
+
+bool KTabBar::isTabReorderingEnabled() const
+{
+ return mTabReorderingEnabled;
+}
+
+void KTabBar::setTabReorderingEnabled( bool on )
+{
+ mTabReorderingEnabled = on;
+}
+
+bool KTabBar::tabCloseActivatePrevious() const
+{
+ return mTabCloseActivatePrevious;
+}
+
+void KTabBar::setTabCloseActivatePrevious( bool on )
+{
+ mTabCloseActivatePrevious = on;
+}
+
+void KTabBar::closeButtonClicked()
+{
+ emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
+}
+
+void KTabBar::setHoverCloseButton( bool button )
+{
+ mHoverCloseButtonEnabled = button;
+ if ( !button )
+ onLayoutChange();
+}
+
+bool KTabBar::hoverCloseButton() const
+{
+ return mHoverCloseButtonEnabled;
+}
+
+void KTabBar::setHoverCloseButtonDelayed( bool delayed )
+{
+ mHoverCloseButtonDelayed = delayed;
+}
+
+bool KTabBar::hoverCloseButtonDelayed() const
+{
+ return mHoverCloseButtonDelayed;
+}
+
+void KTabBar::onLayoutChange()
+{
+ mEnableCloseButtonTimer->stop();
+ delete mHoverCloseButton;
+ mHoverCloseButton = 0;
+ mHoverCloseButtonTab = 0;
+ mActivateDragSwitchTabTimer->stop();
+ mDragSwitchTab = 0;
+}
+
+#include "ktabbar.moc"