1
/* Copyright (C) 2005 Kevin Smith
6
/* This file is heavily based on part of the KDE libraries
7
Copyright (C) 2003 Stephan Binner <binner@kde.org>
8
Copyright (C) 2003 Zack Rusin <zack@kde.org>
11
#include <qapplication.h>
16
#include <qpushbutton.h>
19
#include "psitabbar.h"
20
#include "psitabwidget.h"
22
KTabBar::KTabBar( QWidget *parent, const char *name )
23
: QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ),
24
mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ),
25
mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ),
26
mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false )
28
setAcceptDrops( true );
29
setMouseTracking( true );
31
mEnableCloseButtonTimer = new QTimer( this );
32
connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) );
34
mActivateDragSwitchTabTimer = new QTimer( this );
35
connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
37
connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
47
void KTabBar::setCloseIcon(const QIconSet& icon)
52
void KTabBar::setTabEnabled( int id, bool enabled )
56
if ( t->isEnabled() != enabled ) {
57
t->setEnabled( enabled );
59
if ( !enabled && id == currentTab() && count()>1 ) {
60
QPtrList<QTab> *tablist = tabList();
61
if ( mTabCloseActivatePrevious )
62
t = tablist->at( count()-2 );
64
int index = indexOf( id );
65
index += ( index+1 == count() ) ? -1 : 1;
69
if ( t->isEnabled() ) {
70
r = r.unite( t->rect() );
71
tablist->append( tablist->take( tablist->findRef( t ) ) );
72
emit selected( t->identifier() );
80
void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
82
if( e->button() != LeftButton )
85
QTab *tab = selectTab( e->pos() );
87
emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
90
QTabBar::mouseDoubleClickEvent( e );
93
void KTabBar::mousePressEvent( QMouseEvent *e )
95
if( e->button() == LeftButton ) {
96
mEnableCloseButtonTimer->stop();
97
mDragStart = e->pos();
99
else if( e->button() == RightButton ) {
100
QTab *tab = selectTab( e->pos() );
102
emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
106
QTabBar::mousePressEvent( e );
109
void KTabBar::mouseMoveEvent( QMouseEvent *e )
111
if ( e->state() == LeftButton ) {
112
QTab *tab = selectTab( e->pos() );
113
if ( mDragSwitchTab && tab != mDragSwitchTab ) {
114
mActivateDragSwitchTabTimer->stop();
118
QPoint newPos = e->pos();
119
if( newPos.x() > mDragStart.x()+dndEventDelay || newPos.x() < mDragStart.x()-dndEventDelay ||
120
newPos.y() > mDragStart.y()+dndEventDelay || newPos.y() < mDragStart.y()-dndEventDelay )
123
emit( initiateDrag( indexOf( tab->identifier() ) ) );
128
else if ( e->state() == MidButton ) {
129
if (mReorderStartTab==-1) {
130
QPoint newPos = e->pos();
131
if( newPos.x() > mDragStart.x()+dndEventDelay || newPos.x() < mDragStart.x()-dndEventDelay ||
132
newPos.y() > mDragStart.y()+dndEventDelay || newPos.y() < mDragStart.y()-dndEventDelay )
134
QTab *tab = selectTab( e->pos() );
135
if( tab && mTabReorderingEnabled ) {
136
mReorderStartTab = indexOf( tab->identifier() );
137
grabMouse( sizeAllCursor );
143
QTab *tab = selectTab( e->pos() );
145
int reorderStopTab = indexOf( tab->identifier() );
146
if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
147
emit( moveTab( mReorderStartTab, reorderStopTab ) );
148
mReorderPreviousTab=mReorderStartTab;
149
mReorderStartTab=reorderStopTab;
156
if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
157
QTab *t = selectTab( e->pos() );
158
if( t && t->iconSet() && t->isEnabled() ) {
159
QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
161
QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
163
QRect rect( 0, 0, pixmap.width(), pixmap.height());
165
int xoff = 0, yoff = 0;
166
// The additional offsets were found by try and error, TODO: find the rational behind them
167
if ( t == tab( currentTab() ) ) {
168
xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
169
yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
176
yoff=0; //kev hacks for OSX
179
rect.moveLeft( t->rect().left() + 2 + xoff );
180
rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
181
if ( rect.contains( e->pos() ) ) {
182
if ( mHoverCloseButton ) {
183
if ( mHoverCloseButtonTab == t )
185
mEnableCloseButtonTimer->stop();
186
delete mHoverCloseButton;
189
//This is the code that shows the close button.
190
// The problems with MAC, 'fix'ed above appear here
191
mHoverCloseButton = new QPushButton( this );
192
mHoverCloseButton->setIconSet( closeIcon);
193
mHoverCloseButton->setGeometry( rect );
194
QToolTip::add(mHoverCloseButton,tr("Close this tab"));
195
mHoverCloseButton->setFlat(true);
196
mHoverCloseButton->show();
197
if ( mHoverCloseButtonDelayed ) {
198
mHoverCloseButton->setEnabled(false);
199
mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
201
mHoverCloseButtonTab = t;
202
connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
206
if ( mHoverCloseButton ) {
207
mEnableCloseButtonTimer->stop();
208
delete mHoverCloseButton;
209
mHoverCloseButton = 0;
213
QTabBar::mouseMoveEvent( e );
216
void KTabBar::enableCloseButton()
218
mHoverCloseButton->setEnabled(true);
221
void KTabBar::activateDragSwitchTab()
223
QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) );
224
if ( tab && mDragSwitchTab == tab )
225
setCurrentTab( mDragSwitchTab );
229
void KTabBar::mouseReleaseEvent( QMouseEvent *e )
231
if( e->button() == MidButton ) {
232
if ( mReorderStartTab==-1 ) {
233
QTab *tab = selectTab( e->pos() );
235
emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
241
setCursor( arrowCursor );
243
mReorderPreviousTab=-1;
246
QTabBar::mouseReleaseEvent( e );
249
void KTabBar::dragMoveEvent( QDragMoveEvent *e )
251
QTab *tab = selectTab( e->pos() );
254
// The receivers of the testCanDecode() signal has to adjust
255
// 'accept' accordingly.
256
emit testCanDecode( e, accept);
257
if ( accept && tab != QTabBar::tab( currentTab() ) ) {
258
mDragSwitchTab = tab;
259
mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
265
QTabBar::dragMoveEvent( e );
268
void KTabBar::dropEvent( QDropEvent *e )
270
QTab *tab = selectTab( e->pos() );
272
mActivateDragSwitchTabTimer->stop();
274
emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
277
QTabBar::dropEvent( e );
280
#ifndef QT_NO_WHEELEVENT
281
void KTabBar::wheelEvent( QWheelEvent *e )
283
if ( e->orientation() == Horizontal )
286
emit( wheelDelta( e->delta() ) );
290
void KTabBar::setTabColor( int id, const QColor& color )
294
mTabColors.insert( id, color );
295
repaint( t->rect(), false );
299
const QColor &KTabBar::tabColor( int id ) const
301
if ( mTabColors.contains( id ) )
302
return mTabColors[id];
304
return colorGroup().foreground();
307
int KTabBar::insertTab( QTab *t, int index )
309
int res = QTabBar::insertTab( t, index );
311
if ( mTabCloseActivatePrevious && count() > 2 ) {
312
QPtrList<QTab> *tablist = tabList();
313
tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
319
void KTabBar::removeTab( QTab *t )
321
mTabColors.remove( t->identifier() );
322
QTabBar::removeTab( t );
325
void KTabBar::paintLabel( QPainter *p, const QRect& br,
326
QTab *t, bool has_focus ) const
329
bool selected = currentTab() == t->identifier();
330
if ( t->iconSet() ) {
331
// the tab has an iconset, draw it in the right mode
332
QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
333
? QIconSet::Normal : QIconSet::Disabled;
334
if ( mode == QIconSet::Normal && has_focus )
335
mode = QIconSet::Active;
336
QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
337
int pixw = pixmap.width();
338
int pixh = pixmap.height();
339
r.setLeft( r.left() + pixw + 4 );
340
r.setRight( r.right() + 2 );
342
int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
343
int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
345
int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
347
p->drawPixmap( right + (selected ? 0 : inactiveXShift),
348
br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
352
QStyle::SFlags flags = QStyle::Style_Default;
354
if ( isEnabled() && t->isEnabled() )
355
flags |= QStyle::Style_Enabled;
358
flags |= QStyle::Style_HasFocus;
361
QColorGroup cg( colorGroup() );
362
if ( mTabColors.contains( t->identifier() ) )
363
cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
365
style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
366
t->isEnabled() ? cg : palette().disabled(),
367
flags, QStyleOption(t) );
370
bool KTabBar::isTabReorderingEnabled() const
372
return mTabReorderingEnabled;
375
void KTabBar::setTabReorderingEnabled( bool on )
377
mTabReorderingEnabled = on;
380
bool KTabBar::tabCloseActivatePrevious() const
382
return mTabCloseActivatePrevious;
385
void KTabBar::setTabCloseActivatePrevious( bool on )
387
mTabCloseActivatePrevious = on;
390
void KTabBar::closeButtonClicked()
392
emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
395
void KTabBar::setHoverCloseButton( bool button )
397
mHoverCloseButtonEnabled = button;
402
bool KTabBar::hoverCloseButton() const
404
return mHoverCloseButtonEnabled;
407
void KTabBar::setHoverCloseButtonDelayed( bool delayed )
409
mHoverCloseButtonDelayed = delayed;
412
bool KTabBar::hoverCloseButtonDelayed() const
414
return mHoverCloseButtonDelayed;
417
void KTabBar::onLayoutChange()
419
mEnableCloseButtonTimer->stop();
420
delete mHoverCloseButton;
421
mHoverCloseButton = 0;
422
mHoverCloseButtonTab = 0;
423
mActivateDragSwitchTabTimer->stop();