source: psi/vendor/affinix/current/libpsi/psiwidgets/psitabbar.cpp@ 2

Last change on this file since 2 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 12.4 KB
Line 
1/* Copyright (C) 2005 Kevin Smith
2 notice goes here
3 */
4
5
6/* This file is heavily based on part of the KDE libraries
7 Copyright (C) 2003 Stephan Binner <[email protected]>
8 Copyright (C) 2003 Zack Rusin <[email protected]>
9*/
10
11#include <qapplication.h>
12#include <qcursor.h>
13#include <qpainter.h>
14#include <qstyle.h>
15#include <qtimer.h>
16#include <qpushbutton.h>
17#include <qtooltip.h>
18
19#include "psitabbar.h"
20#include "psitabwidget.h"
21
22KTabBar::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 )
27{
28 setAcceptDrops( true );
29 setMouseTracking( true );
30
31 mEnableCloseButtonTimer = new QTimer( this );
32 connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) );
33
34 mActivateDragSwitchTabTimer = new QTimer( this );
35 connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
36
37 connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
38 dndEventDelay=5;
39}
40
41KTabBar::~KTabBar()
42{
43 //For the future
44 //delete d;
45}
46
47void KTabBar::setCloseIcon(const QIconSet& icon)
48{
49 closeIcon=icon;
50}
51
52void KTabBar::setTabEnabled( int id, bool enabled )
53{
54 QTab * t = tab( id );
55 if ( t ) {
56 if ( t->isEnabled() != enabled ) {
57 t->setEnabled( enabled );
58 QRect r( t->rect() );
59 if ( !enabled && id == currentTab() && count()>1 ) {
60 QPtrList<QTab> *tablist = tabList();
61 if ( mTabCloseActivatePrevious )
62 t = tablist->at( count()-2 );
63 else {
64 int index = indexOf( id );
65 index += ( index+1 == count() ) ? -1 : 1;
66 t = tabAt( index );
67 }
68
69 if ( t->isEnabled() ) {
70 r = r.unite( t->rect() );
71 tablist->append( tablist->take( tablist->findRef( t ) ) );
72 emit selected( t->identifier() );
73 }
74 }
75 repaint( r );
76 }
77 }
78}
79
80void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
81{
82 if( e->button() != LeftButton )
83 return;
84
85 QTab *tab = selectTab( e->pos() );
86 if( tab ) {
87 emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
88 return;
89 }
90 QTabBar::mouseDoubleClickEvent( e );
91}
92
93void KTabBar::mousePressEvent( QMouseEvent *e )
94{
95 if( e->button() == LeftButton ) {
96 mEnableCloseButtonTimer->stop();
97 mDragStart = e->pos();
98 }
99 else if( e->button() == RightButton ) {
100 QTab *tab = selectTab( e->pos() );
101 if( tab ) {
102 emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
103 return;
104 }
105 }
106 QTabBar::mousePressEvent( e );
107}
108
109void KTabBar::mouseMoveEvent( QMouseEvent *e )
110{
111 if ( e->state() == LeftButton ) {
112 QTab *tab = selectTab( e->pos() );
113 if ( mDragSwitchTab && tab != mDragSwitchTab ) {
114 mActivateDragSwitchTabTimer->stop();
115 mDragSwitchTab = 0;
116 }
117
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 )
121 {
122 if( tab ) {
123 emit( initiateDrag( indexOf( tab->identifier() ) ) );
124 return;
125 }
126 }
127 }
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 )
133 {
134 QTab *tab = selectTab( e->pos() );
135 if( tab && mTabReorderingEnabled ) {
136 mReorderStartTab = indexOf( tab->identifier() );
137 grabMouse( sizeAllCursor );
138 return;
139 }
140 }
141 }
142 else {
143 QTab *tab = selectTab( e->pos() );
144 if( tab ) {
145 int reorderStopTab = indexOf( tab->identifier() );
146 if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
147 emit( moveTab( mReorderStartTab, reorderStopTab ) );
148 mReorderPreviousTab=mReorderStartTab;
149 mReorderStartTab=reorderStopTab;
150 return;
151 }
152 }
153 }
154 }
155
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 );
160#ifndef Q_WS_MAC
161 QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
162#else
163 QRect rect( 0, 0, pixmap.width(), pixmap.height());
164#endif
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;
170 }
171 else {
172 xoff = 7;
173 yoff = 0;
174 }
175#ifdef Q_WS_MAC
176 yoff=0; //kev hacks for OSX
177 xoff=7; //also kev
178#endif
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 )
184 return;
185 mEnableCloseButtonTimer->stop();
186 delete mHoverCloseButton;
187 }
188
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 );
200 }
201 mHoverCloseButtonTab = t;
202 connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
203 return;
204 }
205 }
206 if ( mHoverCloseButton ) {
207 mEnableCloseButtonTimer->stop();
208 delete mHoverCloseButton;
209 mHoverCloseButton = 0;
210 }
211 }
212
213 QTabBar::mouseMoveEvent( e );
214}
215
216void KTabBar::enableCloseButton()
217{
218 mHoverCloseButton->setEnabled(true);
219}
220
221void KTabBar::activateDragSwitchTab()
222{
223 QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) );
224 if ( tab && mDragSwitchTab == tab )
225 setCurrentTab( mDragSwitchTab );
226 mDragSwitchTab = 0;
227}
228
229void KTabBar::mouseReleaseEvent( QMouseEvent *e )
230{
231 if( e->button() == MidButton ) {
232 if ( mReorderStartTab==-1 ) {
233 QTab *tab = selectTab( e->pos() );
234 if( tab ) {
235 emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
236 return;
237 }
238 }
239 else {
240 releaseMouse();
241 setCursor( arrowCursor );
242 mReorderStartTab=-1;
243 mReorderPreviousTab=-1;
244 }
245 }
246 QTabBar::mouseReleaseEvent( e );
247}
248
249void KTabBar::dragMoveEvent( QDragMoveEvent *e )
250{
251 QTab *tab = selectTab( e->pos() );
252 if( tab ) {
253 bool accept = false;
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 );
260 }
261 e->accept( accept );
262 return;
263 }
264 e->accept( false );
265 QTabBar::dragMoveEvent( e );
266}
267
268void KTabBar::dropEvent( QDropEvent *e )
269{
270 QTab *tab = selectTab( e->pos() );
271 if( tab ) {
272 mActivateDragSwitchTabTimer->stop();
273 mDragSwitchTab = 0;
274 emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
275 return;
276 }
277 QTabBar::dropEvent( e );
278}
279
280#ifndef QT_NO_WHEELEVENT
281void KTabBar::wheelEvent( QWheelEvent *e )
282{
283 if ( e->orientation() == Horizontal )
284 return;
285
286 emit( wheelDelta( e->delta() ) );
287}
288#endif
289
290void KTabBar::setTabColor( int id, const QColor& color )
291{
292 QTab *t = tab( id );
293 if ( t ) {
294 mTabColors.insert( id, color );
295 repaint( t->rect(), false );
296 }
297}
298
299const QColor &KTabBar::tabColor( int id ) const
300{
301 if ( mTabColors.contains( id ) )
302 return mTabColors[id];
303
304 return colorGroup().foreground();
305}
306
307int KTabBar::insertTab( QTab *t, int index )
308{
309 int res = QTabBar::insertTab( t, index );
310
311 if ( mTabCloseActivatePrevious && count() > 2 ) {
312 QPtrList<QTab> *tablist = tabList();
313 tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
314 }
315
316 return res;
317}
318
319void KTabBar::removeTab( QTab *t )
320{
321 mTabColors.remove( t->identifier() );
322 QTabBar::removeTab( t );
323}
324
325void KTabBar::paintLabel( QPainter *p, const QRect& br,
326 QTab *t, bool has_focus ) const
327{
328 QRect r = br;
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 );
341
342 int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
343 int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
344
345 int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
346
347 p->drawPixmap( right + (selected ? 0 : inactiveXShift),
348 br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
349 pixmap );
350 }
351
352 QStyle::SFlags flags = QStyle::Style_Default;
353
354 if ( isEnabled() && t->isEnabled() )
355 flags |= QStyle::Style_Enabled;
356 if ( has_focus )
357 {
358 flags |= QStyle::Style_HasFocus;
359 }
360
361 QColorGroup cg( colorGroup() );
362 if ( mTabColors.contains( t->identifier() ) )
363 cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
364
365 style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
366 t->isEnabled() ? cg : palette().disabled(),
367 flags, QStyleOption(t) );
368}
369
370bool KTabBar::isTabReorderingEnabled() const
371{
372 return mTabReorderingEnabled;
373}
374
375void KTabBar::setTabReorderingEnabled( bool on )
376{
377 mTabReorderingEnabled = on;
378}
379
380bool KTabBar::tabCloseActivatePrevious() const
381{
382 return mTabCloseActivatePrevious;
383}
384
385void KTabBar::setTabCloseActivatePrevious( bool on )
386{
387 mTabCloseActivatePrevious = on;
388}
389
390void KTabBar::closeButtonClicked()
391{
392 emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
393}
394
395void KTabBar::setHoverCloseButton( bool button )
396{
397 mHoverCloseButtonEnabled = button;
398 if ( !button )
399 onLayoutChange();
400}
401
402bool KTabBar::hoverCloseButton() const
403{
404 return mHoverCloseButtonEnabled;
405}
406
407void KTabBar::setHoverCloseButtonDelayed( bool delayed )
408{
409 mHoverCloseButtonDelayed = delayed;
410}
411
412bool KTabBar::hoverCloseButtonDelayed() const
413{
414 return mHoverCloseButtonDelayed;
415}
416
417void KTabBar::onLayoutChange()
418{
419 mEnableCloseButtonTimer->stop();
420 delete mHoverCloseButton;
421 mHoverCloseButton = 0;
422 mHoverCloseButtonTab = 0;
423 mActivateDragSwitchTabTimer->stop();
424 mDragSwitchTab = 0;
425}
426
Note: See TracBrowser for help on using the repository browser.