1 | /****************************************************************************
|
---|
2 | ** $Id: qtabbar.cpp 2 2005-11-16 15:49:26Z dmik $
|
---|
3 | **
|
---|
4 | ** Implementation of QTab and QTabBar classes
|
---|
5 | **
|
---|
6 | ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
|
---|
7 | **
|
---|
8 | ** This file is part of the widgets module of the Qt GUI Toolkit.
|
---|
9 | **
|
---|
10 | ** This file may be distributed under the terms of the Q Public License
|
---|
11 | ** as defined by Trolltech AS of Norway and appearing in the file
|
---|
12 | ** LICENSE.QPL included in the packaging of this file.
|
---|
13 | **
|
---|
14 | ** This file may be distributed and/or modified under the terms of the
|
---|
15 | ** GNU General Public License version 2 as published by the Free Software
|
---|
16 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
17 | ** packaging of this file.
|
---|
18 | **
|
---|
19 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
---|
20 | ** licenses may use this file in accordance with the Qt Commercial License
|
---|
21 | ** Agreement provided with the Software.
|
---|
22 | **
|
---|
23 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
---|
24 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
---|
25 | **
|
---|
26 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
---|
27 | ** information about Qt Commercial License Agreements.
|
---|
28 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
---|
29 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
---|
30 | **
|
---|
31 | ** Contact info@trolltech.com if any conditions of this licensing are
|
---|
32 | ** not clear to you.
|
---|
33 | **
|
---|
34 | **********************************************************************/
|
---|
35 |
|
---|
36 | #include "qtabbar.h"
|
---|
37 | #ifndef QT_NO_TABBAR
|
---|
38 | #include "qaccel.h"
|
---|
39 | #include "qbitmap.h"
|
---|
40 | #include "qtoolbutton.h"
|
---|
41 | #include "qtooltip.h"
|
---|
42 | #include "qapplication.h"
|
---|
43 | #include "qstyle.h"
|
---|
44 | #include "qpainter.h"
|
---|
45 | #include "qiconset.h"
|
---|
46 | #include "qcursor.h"
|
---|
47 | #include "../kernel/qinternal_p.h"
|
---|
48 | #if defined(QT_ACCESSIBILITY_SUPPORT)
|
---|
49 | #include "qaccessible.h"
|
---|
50 | #endif
|
---|
51 |
|
---|
52 |
|
---|
53 | /*!
|
---|
54 | \class QTab qtabbar.h
|
---|
55 | \brief The QTab class provides the structures in a QTabBar.
|
---|
56 |
|
---|
57 | \ingroup advanced
|
---|
58 |
|
---|
59 | This class is used for custom QTabBar tab headings.
|
---|
60 |
|
---|
61 | \sa QTabBar
|
---|
62 | */
|
---|
63 |
|
---|
64 |
|
---|
65 | /*!
|
---|
66 | Constructs an empty tab. All fields are set to empty.
|
---|
67 | */
|
---|
68 |
|
---|
69 | QTab::QTab()
|
---|
70 | : enabled( TRUE ),
|
---|
71 | id ( 0 ),
|
---|
72 | iconset( 0 ),
|
---|
73 | tb( 0 )
|
---|
74 | {
|
---|
75 | }
|
---|
76 |
|
---|
77 | /*!
|
---|
78 | Constructs a tab with the text \a text.
|
---|
79 | */
|
---|
80 |
|
---|
81 | QTab::QTab( const QString &text )
|
---|
82 | : label( text ),
|
---|
83 | enabled( TRUE ),
|
---|
84 | id( 0 ),
|
---|
85 | iconset( 0 ),
|
---|
86 | tb( 0 )
|
---|
87 | {
|
---|
88 | }
|
---|
89 |
|
---|
90 | /*!
|
---|
91 | Constructs a tab with an \a icon and the text, \a text.
|
---|
92 | */
|
---|
93 |
|
---|
94 | QTab::QTab( const QIconSet& icon, const QString& text )
|
---|
95 | : label( text ),
|
---|
96 | enabled( TRUE ),
|
---|
97 | id( 0 ),
|
---|
98 | iconset( new QIconSet(icon) ),
|
---|
99 | tb( 0 )
|
---|
100 | {
|
---|
101 | }
|
---|
102 |
|
---|
103 | /*!
|
---|
104 | \fn QString QTab::text() const
|
---|
105 |
|
---|
106 | Returns the text of the QTab label.
|
---|
107 | */
|
---|
108 |
|
---|
109 | /*!
|
---|
110 | \fn QIconSet QTab::iconSet() const
|
---|
111 |
|
---|
112 | Return the QIconSet of the QTab.
|
---|
113 | */
|
---|
114 |
|
---|
115 | /*!
|
---|
116 | \fn void QTab::setRect( const QRect &rect )
|
---|
117 |
|
---|
118 | Set the QTab QRect to \a rect.
|
---|
119 | */
|
---|
120 |
|
---|
121 | /*!
|
---|
122 | \fn QRect QTab::rect() const
|
---|
123 |
|
---|
124 | Return the QRect for the QTab.
|
---|
125 | */
|
---|
126 |
|
---|
127 | /*!
|
---|
128 | \fn void QTab::setEnabled( bool enable )
|
---|
129 |
|
---|
130 | If \a enable is TRUE enable the QTab, otherwise disable it.
|
---|
131 | */
|
---|
132 |
|
---|
133 | /*!
|
---|
134 | \fn bool QTab::isEnabled() const
|
---|
135 |
|
---|
136 | Returns TRUE if the QTab is enabled; otherwise returns FALSE.
|
---|
137 | */
|
---|
138 |
|
---|
139 | /*!
|
---|
140 | \fn void QTab::setIdentifier( int i )
|
---|
141 |
|
---|
142 | Set the identifier for the QTab to \a i. Each QTab's identifier
|
---|
143 | within a QTabBar must be unique.
|
---|
144 | */
|
---|
145 |
|
---|
146 | /*!
|
---|
147 | \fn int QTab::identifier() const
|
---|
148 |
|
---|
149 | Return the QTab's identifier.
|
---|
150 | */
|
---|
151 |
|
---|
152 |
|
---|
153 |
|
---|
154 | /*!
|
---|
155 | Destroys the tab and frees up all allocated resources.
|
---|
156 | */
|
---|
157 |
|
---|
158 | QTab::~QTab()
|
---|
159 | {
|
---|
160 | delete iconset;
|
---|
161 | tb = 0;
|
---|
162 | }
|
---|
163 |
|
---|
164 | /*!
|
---|
165 | \class QTabBar qtabbar.h
|
---|
166 | \brief The QTabBar class provides a tab bar, e.g. for use in tabbed dialogs.
|
---|
167 |
|
---|
168 | \ingroup advanced
|
---|
169 |
|
---|
170 | QTabBar is straightforward to use; it draws the tabs using one of
|
---|
171 | the predefined \link QTabBar::Shape shapes\endlink, and emits a
|
---|
172 | signal when a tab is selected. It can be subclassed to tailor the
|
---|
173 | look and feel. Qt also provides a ready-made \l{QTabWidget} and a
|
---|
174 | \l{QTabDialog}.
|
---|
175 |
|
---|
176 | The choice of tab shape is a matter of taste, although tab dialogs
|
---|
177 | (for preferences and similar) invariably use \c RoundedAbove;
|
---|
178 | nobody uses \c TriangularAbove. Tab controls in windows other than
|
---|
179 | dialogs almost always use either \c RoundedBelow or \c
|
---|
180 | TriangularBelow. Many spreadsheets and other tab controls in which
|
---|
181 | all the pages are essentially similar use \c TriangularBelow,
|
---|
182 | whereas \c RoundedBelow is used mostly when the pages are
|
---|
183 | different (e.g. a multi-page tool palette).
|
---|
184 |
|
---|
185 | The most important part of QTabBar's API is the selected() signal.
|
---|
186 | This is emitted whenever the selected page changes (even at
|
---|
187 | startup, when the selected page changes from 'none'). There is
|
---|
188 | also a slot, setCurrentTab(), which can be used to select a page
|
---|
189 | programmatically.
|
---|
190 |
|
---|
191 | QTabBar creates automatic accelerator keys in the manner of
|
---|
192 | QButton; e.g. if a tab's label is "\&Graphics", Alt+G becomes an
|
---|
193 | accelerator key for switching to that tab.
|
---|
194 |
|
---|
195 | The following virtual functions may need to be reimplemented:
|
---|
196 | \list
|
---|
197 | \i paint() paints a single tab. paintEvent() calls paint() for
|
---|
198 | each tab so that any overlap will look right.
|
---|
199 | \i addTab() creates a new tab and adds it to the bar.
|
---|
200 | \i selectTab() decides which tab, if any, the user selects with the mouse.
|
---|
201 | \endlist
|
---|
202 |
|
---|
203 | The index of the current tab is returned by currentTab(). The tab
|
---|
204 | with a particular index is returned by tabAt(), the tab with a
|
---|
205 | particular id is returned by tab(). The index of a tab is returned
|
---|
206 | by indexOf(). The current tab can be set by index or tab pointer
|
---|
207 | using one of the setCurrentTab() functions.
|
---|
208 |
|
---|
209 | <img src=qtabbar-m.png> <img src=qtabbar-w.png>
|
---|
210 | */
|
---|
211 |
|
---|
212 | /*!
|
---|
213 | \enum QTabBar::Shape
|
---|
214 |
|
---|
215 | This enum type lists the built-in shapes supported by QTabBar:
|
---|
216 |
|
---|
217 | \value RoundedAbove the normal rounded look above the pages
|
---|
218 |
|
---|
219 | \value RoundedBelow the normal rounded look below the pages
|
---|
220 |
|
---|
221 | \value TriangularAbove triangular tabs above the pages (very
|
---|
222 | unusual; included for completeness)
|
---|
223 |
|
---|
224 | \value TriangularBelow triangular tabs similar to those used in
|
---|
225 | the Excel spreadsheet, for example
|
---|
226 | */
|
---|
227 |
|
---|
228 | class QTabBarToolTip;
|
---|
229 |
|
---|
230 | struct QTabPrivate {
|
---|
231 | int id;
|
---|
232 | int focus;
|
---|
233 | #ifndef QT_NO_ACCEL
|
---|
234 | QAccel * a;
|
---|
235 | #endif
|
---|
236 | QTab *pressed;
|
---|
237 | QTabBar::Shape s;
|
---|
238 | QToolButton* rightB;
|
---|
239 | QToolButton* leftB;
|
---|
240 | int btnWidth;
|
---|
241 | bool scrolls;
|
---|
242 | QTabBarToolTip * toolTips;
|
---|
243 | };
|
---|
244 |
|
---|
245 | #ifndef QT_NO_TOOLTIP
|
---|
246 | /* \internal
|
---|
247 | */
|
---|
248 | class QTabBarToolTip : public QToolTip
|
---|
249 | {
|
---|
250 | public:
|
---|
251 | QTabBarToolTip( QWidget * parent )
|
---|
252 | : QToolTip( parent ) {}
|
---|
253 | virtual ~QTabBarToolTip() {}
|
---|
254 |
|
---|
255 | void add( QTab * tab, const QString & tip )
|
---|
256 | {
|
---|
257 | tabTips.replace( tab, tip );
|
---|
258 | }
|
---|
259 |
|
---|
260 | void remove( QTab * tab )
|
---|
261 | {
|
---|
262 | tabTips.erase( tab );
|
---|
263 | }
|
---|
264 |
|
---|
265 | QString tipForTab( QTab * tab ) const
|
---|
266 | {
|
---|
267 | QMapConstIterator<QTab *, QString> it;
|
---|
268 | it = tabTips.find( tab );
|
---|
269 | if ( it != tabTips.end() )
|
---|
270 | return it.data();
|
---|
271 | else
|
---|
272 | return QString();
|
---|
273 | }
|
---|
274 |
|
---|
275 | protected:
|
---|
276 | void maybeTip( const QPoint & p )
|
---|
277 | {
|
---|
278 | QTabBar * tb = (QTabBar *) parentWidget();
|
---|
279 | if ( !tb )
|
---|
280 | return;
|
---|
281 |
|
---|
282 | // check if the scroll buttons in the tab bar are visible -
|
---|
283 | // don't display any tips if the pointer is over one of them
|
---|
284 | QRect rectL, rectR;
|
---|
285 | rectL.setRect( tb->d->leftB->x(), tb->d->leftB->y(),
|
---|
286 | tb->d->leftB->width(), tb->d->leftB->height() );
|
---|
287 | rectR.setRect( tb->d->rightB->x(), tb->d->rightB->y(),
|
---|
288 | tb->d->rightB->width(), tb->d->rightB->height() );
|
---|
289 | if ( tb->d->scrolls && (rectL.contains( p ) || rectR.contains( p )) )
|
---|
290 | return;
|
---|
291 |
|
---|
292 | #ifndef QT_NO_TOOLTIP
|
---|
293 | // find and show the tool tip for the tab under the point p
|
---|
294 | QMapIterator<QTab *, QString> it;
|
---|
295 | for ( it = tabTips.begin(); it != tabTips.end(); ++it ) {
|
---|
296 | if ( it.key()->rect().contains( p ) )
|
---|
297 | tip( it.key()->rect(), it.data() );
|
---|
298 | }
|
---|
299 | #endif
|
---|
300 | }
|
---|
301 |
|
---|
302 | private:
|
---|
303 | QMap<QTab *, QString> tabTips;
|
---|
304 | };
|
---|
305 | #endif
|
---|
306 |
|
---|
307 | /*!
|
---|
308 | \fn void QTabBar::selected( int id )
|
---|
309 |
|
---|
310 | QTabBar emits this signal whenever any tab is selected, whether by
|
---|
311 | the program or by the user. The argument \a id is the id of the
|
---|
312 | tab as returned by addTab().
|
---|
313 |
|
---|
314 | show() is guaranteed to emit this signal; you can display your
|
---|
315 | page in a slot connected to this signal.
|
---|
316 | */
|
---|
317 |
|
---|
318 | /*!
|
---|
319 | \fn void QTabBar::layoutChanged()
|
---|
320 |
|
---|
321 | QTabBar emits the signal whenever the layout of the tab bar has
|
---|
322 | been recalculated, for example when the contents of a tab change.
|
---|
323 | */
|
---|
324 |
|
---|
325 | /*!
|
---|
326 | Constructs a new, empty tab bar; the \a parent and \a name
|
---|
327 | arguments are passed on to the QWidget constructor.
|
---|
328 | */
|
---|
329 |
|
---|
330 | QTabBar::QTabBar( QWidget * parent, const char *name )
|
---|
331 | : QWidget( parent, name, WNoAutoErase | WNoMousePropagation )
|
---|
332 | {
|
---|
333 | d = new QTabPrivate;
|
---|
334 | d->pressed = 0;
|
---|
335 | d->id = 0;
|
---|
336 | d->focus = 0;
|
---|
337 | d->toolTips = 0;
|
---|
338 | #ifndef QT_NO_ACCEL
|
---|
339 | d->a = new QAccel( this, "tab accelerators" );
|
---|
340 | connect( d->a, SIGNAL(activated(int)), this, SLOT(setCurrentTab(int)) );
|
---|
341 | connect( d->a, SIGNAL(activatedAmbiguously(int)), this, SLOT(setCurrentTab(int)) );
|
---|
342 | #endif
|
---|
343 | d->s = RoundedAbove;
|
---|
344 | d->scrolls = FALSE;
|
---|
345 | d->leftB = new QToolButton( LeftArrow, this, "qt_left_btn" );
|
---|
346 | connect( d->leftB, SIGNAL( clicked() ), this, SLOT( scrollTabs() ) );
|
---|
347 | d->leftB->hide();
|
---|
348 | d->rightB = new QToolButton( RightArrow, this, "qt_right_btn" );
|
---|
349 | connect( d->rightB, SIGNAL( clicked() ), this, SLOT( scrollTabs() ) );
|
---|
350 | d->rightB->hide();
|
---|
351 | d->btnWidth = style().pixelMetric(QStyle::PM_TabBarScrollButtonWidth, this);
|
---|
352 | l = new QPtrList<QTab>;
|
---|
353 | lstatic = new QPtrList<QTab>;
|
---|
354 | lstatic->setAutoDelete( TRUE );
|
---|
355 | setFocusPolicy( TabFocus );
|
---|
356 | setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
|
---|
357 | }
|
---|
358 |
|
---|
359 |
|
---|
360 | /*!
|
---|
361 | Destroys the tab control, freeing memory used.
|
---|
362 | */
|
---|
363 |
|
---|
364 | QTabBar::~QTabBar()
|
---|
365 | {
|
---|
366 | #ifndef QT_NO_TOOLTIP
|
---|
367 | if ( d->toolTips )
|
---|
368 | delete d->toolTips;
|
---|
369 | #endif
|
---|
370 | delete d;
|
---|
371 | d = 0;
|
---|
372 | delete l;
|
---|
373 | l = 0;
|
---|
374 | delete lstatic;
|
---|
375 | lstatic = 0;
|
---|
376 | }
|
---|
377 |
|
---|
378 |
|
---|
379 | /*!
|
---|
380 | Adds the tab, \a newTab, to the tab control.
|
---|
381 |
|
---|
382 | Sets \a newTab's id to a new id and places the tab just to the
|
---|
383 | right of the existing tabs. If the tab's label contains an
|
---|
384 | ampersand, the letter following the ampersand is used as an
|
---|
385 | accelerator for the tab, e.g. if the label is "Bro\&wse" then
|
---|
386 | Alt+W becomes an accelerator which will move the focus to this
|
---|
387 | tab. Returns the id.
|
---|
388 |
|
---|
389 | \sa insertTab()
|
---|
390 | */
|
---|
391 |
|
---|
392 | int QTabBar::addTab( QTab * newTab )
|
---|
393 | {
|
---|
394 | return insertTab( newTab );
|
---|
395 | }
|
---|
396 |
|
---|
397 |
|
---|
398 | /*!
|
---|
399 | Inserts the tab, \a newTab, into the tab control.
|
---|
400 |
|
---|
401 | If \a index is not specified, the tab is simply appended.
|
---|
402 | Otherwise it's inserted at the specified position.
|
---|
403 |
|
---|
404 | Sets \a newTab's id to a new id. If the tab's label contains an
|
---|
405 | ampersand, the letter following the ampersand is used as an
|
---|
406 | accelerator for the tab, e.g. if the label is "Bro\&wse" then
|
---|
407 | Alt+W becomes an accelerator which will move the focus to this
|
---|
408 | tab. Returns the id.
|
---|
409 |
|
---|
410 | \sa addTab()
|
---|
411 | */
|
---|
412 |
|
---|
413 | int QTabBar::insertTab( QTab * newTab, int index )
|
---|
414 | {
|
---|
415 | newTab->id = d->id++;
|
---|
416 | if ( !tab( d->focus ) )
|
---|
417 | d->focus = newTab->id;
|
---|
418 |
|
---|
419 | newTab->setTabBar( this );
|
---|
420 | l->insert( 0, newTab );
|
---|
421 | if ( index < 0 || index > int(lstatic->count()) )
|
---|
422 | lstatic->append( newTab );
|
---|
423 | else
|
---|
424 | lstatic->insert( index, newTab );
|
---|
425 |
|
---|
426 | layoutTabs();
|
---|
427 | updateArrowButtons();
|
---|
428 | makeVisible( tab( currentTab() ) );
|
---|
429 |
|
---|
430 | #ifndef QT_NO_ACCEL
|
---|
431 | int p = QAccel::shortcutKey( newTab->label );
|
---|
432 | if ( p )
|
---|
433 | d->a->insertItem( p, newTab->id );
|
---|
434 | #endif
|
---|
435 |
|
---|
436 | return newTab->id;
|
---|
437 | }
|
---|
438 |
|
---|
439 |
|
---|
440 | /*!
|
---|
441 | Removes tab \a t from the tab control, and deletes the tab.
|
---|
442 | */
|
---|
443 | void QTabBar::removeTab( QTab * t )
|
---|
444 | {
|
---|
445 | //#### accelerator labels??
|
---|
446 | #ifndef QT_NO_TOOLTIP
|
---|
447 | if ( d->toolTips )
|
---|
448 | d->toolTips->remove( t );
|
---|
449 | #endif
|
---|
450 | #ifndef QT_NO_ACCEL
|
---|
451 | if ( d->a )
|
---|
452 | d->a->removeItem( t->id );
|
---|
453 | #endif
|
---|
454 | bool updateFocus = t->id == d->focus;
|
---|
455 | // remove the TabBar Reference
|
---|
456 | if(d->pressed == t)
|
---|
457 | d->pressed = 0;
|
---|
458 | t->setTabBar( 0 );
|
---|
459 | l->remove( t );
|
---|
460 | lstatic->remove( t );
|
---|
461 | layoutTabs();
|
---|
462 | updateArrowButtons();
|
---|
463 | makeVisible( tab( currentTab() ) );
|
---|
464 | if ( updateFocus )
|
---|
465 | d->focus = currentTab();
|
---|
466 | update();
|
---|
467 | }
|
---|
468 |
|
---|
469 |
|
---|
470 | /*!
|
---|
471 | Enables tab \a id if \a enabled is TRUE or disables it if \a
|
---|
472 | enabled is FALSE. If \a id is currently selected,
|
---|
473 | setTabEnabled(FALSE) makes another tab selected.
|
---|
474 |
|
---|
475 | setTabEnabled() updates the display if this causes a change in \a
|
---|
476 | id's status.
|
---|
477 |
|
---|
478 | \sa update(), isTabEnabled()
|
---|
479 | */
|
---|
480 |
|
---|
481 | void QTabBar::setTabEnabled( int id, bool enabled )
|
---|
482 | {
|
---|
483 | QTab * t;
|
---|
484 | for( t = l->first(); t; t = l->next() ) {
|
---|
485 | if ( t && t->id == id ) {
|
---|
486 | if ( t->enabled != enabled ) {
|
---|
487 | t->enabled = enabled;
|
---|
488 | #ifndef QT_NO_ACCEL
|
---|
489 | d->a->setItemEnabled( t->id, enabled );
|
---|
490 | #endif
|
---|
491 | QRect r( t->r );
|
---|
492 | if ( !enabled && id == currentTab() ) {
|
---|
493 | QPoint p1( t->r.center() ), p2;
|
---|
494 | int m = 2147483647;
|
---|
495 | int distance;
|
---|
496 | // look for the closest enabled tab - measure the
|
---|
497 | // distance between the centers of the two tabs
|
---|
498 | for( QTab * n = l->first(); n; n = l->next() ) {
|
---|
499 | if ( n->enabled ) {
|
---|
500 | p2 = n->r.center();
|
---|
501 | distance = (p2.x() - p1.x())*(p2.x() - p1.x()) +
|
---|
502 | (p2.y() - p1.y())*(p2.y() - p1.y());
|
---|
503 | if ( distance < m ) {
|
---|
504 | t = n;
|
---|
505 | m = distance;
|
---|
506 | }
|
---|
507 | }
|
---|
508 | }
|
---|
509 | if ( t->enabled ) {
|
---|
510 | r = r.unite( t->r );
|
---|
511 | l->append( l->take( l->findRef( t ) ) );
|
---|
512 | emit selected( t->id );
|
---|
513 | }
|
---|
514 | }
|
---|
515 | repaint( r, FALSE );
|
---|
516 | }
|
---|
517 | return;
|
---|
518 | }
|
---|
519 | }
|
---|
520 | }
|
---|
521 |
|
---|
522 |
|
---|
523 | /*!
|
---|
524 | Returns TRUE if the tab with id \a id exists and is enabled;
|
---|
525 | otherwise returns FALSE.
|
---|
526 |
|
---|
527 | \sa setTabEnabled()
|
---|
528 | */
|
---|
529 |
|
---|
530 | bool QTabBar::isTabEnabled( int id ) const
|
---|
531 | {
|
---|
532 | QTab * t = tab( id );
|
---|
533 | if ( t )
|
---|
534 | return t->enabled;
|
---|
535 | return FALSE;
|
---|
536 | }
|
---|
537 |
|
---|
538 |
|
---|
539 |
|
---|
540 | /*!
|
---|
541 | \reimp
|
---|
542 | */
|
---|
543 | QSize QTabBar::sizeHint() const
|
---|
544 | {
|
---|
545 | QSize sz(0, 0);
|
---|
546 | if ( QTab * t = l->first() ) {
|
---|
547 | QRect r( t->r );
|
---|
548 | while ( (t = l->next()) != 0 )
|
---|
549 | r = r.unite( t->r );
|
---|
550 | sz = r.size();
|
---|
551 | }
|
---|
552 | return sz.expandedTo(QApplication::globalStrut());
|
---|
553 | }
|
---|
554 |
|
---|
555 | /*!
|
---|
556 | \reimp
|
---|
557 | */
|
---|
558 |
|
---|
559 | QSize QTabBar::minimumSizeHint() const
|
---|
560 | {
|
---|
561 | if(style().styleHint( QStyle::SH_TabBar_PreferNoArrows, this ))
|
---|
562 | return sizeHint();
|
---|
563 | return QSize( d->rightB->sizeHint().width() * 2 + 75, sizeHint().height() );
|
---|
564 | }
|
---|
565 |
|
---|
566 | /*!
|
---|
567 | Paints the tab \a t using painter \a p. If and only if \a selected
|
---|
568 | is TRUE, \a t is drawn currently selected.
|
---|
569 |
|
---|
570 | This virtual function may be reimplemented to change the look of
|
---|
571 | QTabBar. If you decide to reimplement it, you may also need to
|
---|
572 | reimplement sizeHint().
|
---|
573 | */
|
---|
574 |
|
---|
575 | void QTabBar::paint( QPainter * p, QTab * t, bool selected ) const
|
---|
576 | {
|
---|
577 | QStyle::SFlags flags = QStyle::Style_Default;
|
---|
578 |
|
---|
579 | if (isEnabled() && t->isEnabled())
|
---|
580 | flags |= QStyle::Style_Enabled;
|
---|
581 | if ( selected )
|
---|
582 | flags |= QStyle::Style_Selected;
|
---|
583 | else if(t == d->pressed)
|
---|
584 | flags |= QStyle::Style_Sunken;
|
---|
585 | //selection flags
|
---|
586 | if(t->rect().contains(mapFromGlobal(QCursor::pos())))
|
---|
587 | flags |= QStyle::Style_MouseOver;
|
---|
588 | style().drawControl( QStyle::CE_TabBarTab, p, this, t->rect(),
|
---|
589 | colorGroup(), flags, QStyleOption(t) );
|
---|
590 |
|
---|
591 | QRect r( t->r );
|
---|
592 | p->setFont( font() );
|
---|
593 |
|
---|
594 | int iw = 0;
|
---|
595 | int ih = 0;
|
---|
596 | if ( t->iconset != 0 ) {
|
---|
597 | iw = t->iconset->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4;
|
---|
598 | ih = t->iconset->pixmap( QIconSet::Small, QIconSet::Normal ).height();
|
---|
599 | }
|
---|
600 | QFontMetrics fm = p->fontMetrics();
|
---|
601 | int fw = fm.width( t->label );
|
---|
602 | fw -= t->label.contains('&') * fm.width('&');
|
---|
603 | fw += t->label.contains("&&") * fm.width('&');
|
---|
604 | int w = iw + fw + 4;
|
---|
605 | int h = QMAX(fm.height() + 4, ih );
|
---|
606 | paintLabel( p, QRect( r.left() + (r.width()-w)/2 - 3,
|
---|
607 | r.top() + (r.height()-h)/2,
|
---|
608 | w, h ), t, t->id == keyboardFocusTab() );
|
---|
609 | }
|
---|
610 |
|
---|
611 | /*!
|
---|
612 | Paints the label of tab \a t centered in rectangle \a br using
|
---|
613 | painter \a p. A focus indication is drawn if \a has_focus is TRUE.
|
---|
614 | */
|
---|
615 |
|
---|
616 | void QTabBar::paintLabel( QPainter* p, const QRect& br,
|
---|
617 | QTab* t, bool has_focus ) const
|
---|
618 | {
|
---|
619 | QRect r = br;
|
---|
620 | bool selected = currentTab() == t->id;
|
---|
621 | if ( t->iconset) {
|
---|
622 | // the tab has an iconset, draw it in the right mode
|
---|
623 | QIconSet::Mode mode = (t->enabled && isEnabled())
|
---|
624 | ? QIconSet::Normal : QIconSet::Disabled;
|
---|
625 | if ( mode == QIconSet::Normal && has_focus )
|
---|
626 | mode = QIconSet::Active;
|
---|
627 | QPixmap pixmap = t->iconset->pixmap( QIconSet::Small, mode );
|
---|
628 | int pixw = pixmap.width();
|
---|
629 | int pixh = pixmap.height();
|
---|
630 | r.setLeft( r.left() + pixw + 4 );
|
---|
631 | r.setRight( r.right() + 2 );
|
---|
632 |
|
---|
633 | int xoff = 0, yoff = 0;
|
---|
634 | if(!selected) {
|
---|
635 | xoff = style().pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, this);
|
---|
636 | yoff = style().pixelMetric(QStyle::PM_TabBarTabShiftVertical, this);
|
---|
637 | }
|
---|
638 | p->drawPixmap( br.left() + 2 + xoff, br.center().y()-pixh/2 + yoff, pixmap );
|
---|
639 | }
|
---|
640 |
|
---|
641 | QStyle::SFlags flags = QStyle::Style_Default;
|
---|
642 |
|
---|
643 | if (isEnabled() && t->isEnabled())
|
---|
644 | flags |= QStyle::Style_Enabled;
|
---|
645 | if (has_focus)
|
---|
646 | flags |= QStyle::Style_HasFocus;
|
---|
647 | if ( selected )
|
---|
648 | flags |= QStyle::Style_Selected;
|
---|
649 | else if(t == d->pressed)
|
---|
650 | flags |= QStyle::Style_Sunken;
|
---|
651 | if(t->rect().contains(mapFromGlobal(QCursor::pos())))
|
---|
652 | flags |= QStyle::Style_MouseOver;
|
---|
653 | style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
|
---|
654 | t->isEnabled() ? colorGroup(): palette().disabled(),
|
---|
655 | flags, QStyleOption(t) );
|
---|
656 | }
|
---|
657 |
|
---|
658 |
|
---|
659 | /*!
|
---|
660 | Repaints the tab row. All the painting is done by paint();
|
---|
661 | paintEvent() only decides which tabs need painting and in what
|
---|
662 | order. The event is passed in \a e.
|
---|
663 |
|
---|
664 | \sa paint()
|
---|
665 | */
|
---|
666 |
|
---|
667 | void QTabBar::paintEvent( QPaintEvent * e )
|
---|
668 | {
|
---|
669 | if ( e->rect().isNull() )
|
---|
670 | return;
|
---|
671 |
|
---|
672 | QSharedDoubleBuffer buffer( this, e->rect() );
|
---|
673 |
|
---|
674 | QTab * t;
|
---|
675 | t = l->first();
|
---|
676 | do {
|
---|
677 | QTab * n = l->next();
|
---|
678 | if ( t && t->r.intersects( e->rect() ) )
|
---|
679 | paint( buffer.painter(), t, n == 0 );
|
---|
680 | t = n;
|
---|
681 | } while ( t != 0 );
|
---|
682 |
|
---|
683 | if ( d->scrolls && lstatic->first()->r.left() < 0 ) {
|
---|
684 | QPointArray a;
|
---|
685 | int h = height();
|
---|
686 | if ( d->s == RoundedAbove ) {
|
---|
687 | buffer.painter()->fillRect( 0, 3, 4, h-5,
|
---|
688 | colorGroup().brush( QColorGroup::Background ) );
|
---|
689 | a.setPoints( 5, 0,2, 3,h/4, 0,h/2, 3,3*h/4, 0,h );
|
---|
690 | } else if ( d->s == RoundedBelow ) {
|
---|
691 | buffer.painter()->fillRect( 0, 2, 4, h-5,
|
---|
692 | colorGroup().brush( QColorGroup::Background ) );
|
---|
693 | a.setPoints( 5, 0,0, 3,h/4, 0,h/2, 3,3*h/4, 0,h-3 );
|
---|
694 | }
|
---|
695 |
|
---|
696 | if ( !a.isEmpty() ) {
|
---|
697 | buffer.painter()->setPen( colorGroup().light() );
|
---|
698 | buffer.painter()->drawPolyline( a );
|
---|
699 | a.translate( 1, 0 );
|
---|
700 | buffer.painter()->setPen( colorGroup().midlight() );
|
---|
701 | buffer.painter()->drawPolyline( a );
|
---|
702 | }
|
---|
703 | }
|
---|
704 | }
|
---|
705 |
|
---|
706 |
|
---|
707 | /*!
|
---|
708 | This virtual function is called by the mouse event handlers to
|
---|
709 | determine which tab is pressed. The default implementation returns
|
---|
710 | a pointer to the tab whose bounding rectangle contains \a p, if
|
---|
711 | exactly one tab's bounding rectangle contains \a p. Otherwise it
|
---|
712 | returns 0.
|
---|
713 |
|
---|
714 | \sa mousePressEvent() mouseReleaseEvent()
|
---|
715 | */
|
---|
716 |
|
---|
717 | QTab * QTabBar::selectTab( const QPoint & p ) const
|
---|
718 | {
|
---|
719 | QTab * selected = 0;
|
---|
720 | bool moreThanOne = FALSE;
|
---|
721 |
|
---|
722 | QPtrListIterator<QTab> i( *l );
|
---|
723 | while( i.current() ) {
|
---|
724 | QTab * t = i.current();
|
---|
725 | ++i;
|
---|
726 |
|
---|
727 | if ( t && t->r.contains( p ) ) {
|
---|
728 | if ( selected )
|
---|
729 | moreThanOne = TRUE;
|
---|
730 | else
|
---|
731 | selected = t;
|
---|
732 | }
|
---|
733 | }
|
---|
734 |
|
---|
735 | return moreThanOne ? 0 : selected;
|
---|
736 | }
|
---|
737 |
|
---|
738 |
|
---|
739 | /*!
|
---|
740 | \reimp
|
---|
741 | */
|
---|
742 | void QTabBar::mousePressEvent( QMouseEvent * e )
|
---|
743 | {
|
---|
744 | if ( e->button() != LeftButton ) {
|
---|
745 | e->ignore();
|
---|
746 | return;
|
---|
747 | }
|
---|
748 | QTab *t = selectTab( e->pos() );
|
---|
749 | if ( t && t->enabled ) {
|
---|
750 | d->pressed = t;
|
---|
751 | if(e->type() == style().styleHint( QStyle::SH_TabBar_SelectMouseType, this ))
|
---|
752 | setCurrentTab( t );
|
---|
753 | else
|
---|
754 | repaint(t->rect(), FALSE);
|
---|
755 | }
|
---|
756 | }
|
---|
757 |
|
---|
758 |
|
---|
759 | /*!
|
---|
760 | \reimp
|
---|
761 | */
|
---|
762 |
|
---|
763 | void QTabBar::mouseMoveEvent ( QMouseEvent *e )
|
---|
764 | {
|
---|
765 | if ( e->state() != LeftButton ) {
|
---|
766 | e->ignore();
|
---|
767 | return;
|
---|
768 | }
|
---|
769 | if(style().styleHint( QStyle::SH_TabBar_SelectMouseType, this ) == QEvent::MouseButtonRelease) {
|
---|
770 | QTab *t = selectTab( e->pos() );
|
---|
771 | if(t != d->pressed) {
|
---|
772 | if(d->pressed)
|
---|
773 | repaint(d->pressed->rect(), FALSE);
|
---|
774 | if((d->pressed = t))
|
---|
775 | repaint(t->rect(), FALSE);
|
---|
776 | }
|
---|
777 | }
|
---|
778 | }
|
---|
779 |
|
---|
780 | /*!
|
---|
781 | \reimp
|
---|
782 | */
|
---|
783 |
|
---|
784 | void QTabBar::mouseReleaseEvent( QMouseEvent *e )
|
---|
785 | {
|
---|
786 | if ( e->button() != LeftButton )
|
---|
787 | e->ignore();
|
---|
788 | if(d->pressed) {
|
---|
789 | QTab *t = selectTab( e->pos() ) == d->pressed ? d->pressed : 0;
|
---|
790 | d->pressed = 0;
|
---|
791 | if(t && t->enabled && e->type() == style().styleHint( QStyle::SH_TabBar_SelectMouseType, this ))
|
---|
792 | setCurrentTab( t );
|
---|
793 | }
|
---|
794 | }
|
---|
795 |
|
---|
796 |
|
---|
797 | /*!
|
---|
798 | \reimp
|
---|
799 | */
|
---|
800 | void QTabBar::show()
|
---|
801 | {
|
---|
802 | // ensures that one tab is selected.
|
---|
803 | QTab * t = l->last();
|
---|
804 | QWidget::show();
|
---|
805 |
|
---|
806 | if ( t )
|
---|
807 | emit selected( t->id );
|
---|
808 | }
|
---|
809 |
|
---|
810 | /*!
|
---|
811 | \property QTabBar::currentTab
|
---|
812 | \brief the id of the tab bar's visible tab
|
---|
813 |
|
---|
814 | If no tab page is currently visible, the property's value is -1.
|
---|
815 | Even if the property's value is not -1, you cannot assume that the
|
---|
816 | user can see the relevant page, or that the tab is enabled. When
|
---|
817 | you need to display something the value of this property
|
---|
818 | represents the best page to display.
|
---|
819 |
|
---|
820 | When this property is set to \e id, it will raise the tab with the
|
---|
821 | id \e id and emit the selected() signal.
|
---|
822 |
|
---|
823 | \sa selected() isTabEnabled()
|
---|
824 | */
|
---|
825 |
|
---|
826 | int QTabBar::currentTab() const
|
---|
827 | {
|
---|
828 | const QTab * t = l->getLast();
|
---|
829 |
|
---|
830 | return t ? t->id : -1;
|
---|
831 | }
|
---|
832 |
|
---|
833 | void QTabBar::setCurrentTab( int id )
|
---|
834 | {
|
---|
835 | setCurrentTab( tab( id ) );
|
---|
836 | }
|
---|
837 |
|
---|
838 |
|
---|
839 | /*!
|
---|
840 | \overload
|
---|
841 |
|
---|
842 | Raises \a tab and emits the selected() signal unless the tab was
|
---|
843 | already current.
|
---|
844 |
|
---|
845 | \sa currentTab() selected()
|
---|
846 | */
|
---|
847 |
|
---|
848 | void QTabBar::setCurrentTab( QTab * tab )
|
---|
849 | {
|
---|
850 | if ( tab && l ) {
|
---|
851 | if ( l->last() == tab )
|
---|
852 | return;
|
---|
853 |
|
---|
854 | QRect r = l->last()->r;
|
---|
855 | if ( l->findRef( tab ) >= 0 )
|
---|
856 | l->append( l->take() );
|
---|
857 |
|
---|
858 | d->focus = tab->id;
|
---|
859 |
|
---|
860 | setMicroFocusHint( tab->rect().x(), tab->rect().y(), tab->rect().width(), tab->rect().height(), FALSE );
|
---|
861 |
|
---|
862 | if ( tab->r.intersects( r ) ) {
|
---|
863 | repaint( r.unite( tab->r ), FALSE );
|
---|
864 | } else {
|
---|
865 | repaint( r, FALSE );
|
---|
866 | repaint( tab->r, FALSE );
|
---|
867 | }
|
---|
868 | makeVisible( tab );
|
---|
869 | emit selected( tab->id );
|
---|
870 |
|
---|
871 | #ifdef QT_ACCESSIBILITY_SUPPORT
|
---|
872 | QAccessible::updateAccessibility( this, indexOf(tab->id)+1, QAccessible::Focus );
|
---|
873 | #endif
|
---|
874 | }
|
---|
875 | }
|
---|
876 |
|
---|
877 | /*!
|
---|
878 | \property QTabBar::keyboardFocusTab
|
---|
879 | \brief the id of the tab that has the keyboard focus
|
---|
880 |
|
---|
881 | This property contains the id of the tab that has the keyboard
|
---|
882 | focus or -1 if the tab bar does not have the keyboard focus.
|
---|
883 | */
|
---|
884 |
|
---|
885 | int QTabBar::keyboardFocusTab() const
|
---|
886 | {
|
---|
887 | return hasFocus() ? d->focus : -1;
|
---|
888 | }
|
---|
889 |
|
---|
890 |
|
---|
891 | /*!
|
---|
892 | \reimp
|
---|
893 | */
|
---|
894 | void QTabBar::keyPressEvent( QKeyEvent * e )
|
---|
895 | {
|
---|
896 | // The right and left arrow keys move a selector, the spacebar
|
---|
897 | // makes the tab with the selector active. All other keys are
|
---|
898 | // ignored.
|
---|
899 |
|
---|
900 | int old = d->focus;
|
---|
901 |
|
---|
902 | bool reverse = QApplication::reverseLayout();
|
---|
903 | if ( ( !reverse && e->key() == Key_Left ) || ( reverse && e->key() == Key_Right ) ) {
|
---|
904 | // left - skip past any disabled ones
|
---|
905 | if ( d->focus > 0 ) {
|
---|
906 | QTab * t = lstatic->last();
|
---|
907 | while ( t && t->id != d->focus )
|
---|
908 | t = lstatic->prev();
|
---|
909 | do {
|
---|
910 | t = lstatic->prev();
|
---|
911 | } while ( t && !t->enabled);
|
---|
912 | if (t)
|
---|
913 | d->focus = t->id;
|
---|
914 | }
|
---|
915 | if ( d->focus < 0 )
|
---|
916 | d->focus = old;
|
---|
917 | } else if ( ( !reverse && e->key() == Key_Right ) || ( reverse && e->key() == Key_Left ) ) {
|
---|
918 | QTab * t = lstatic->first();
|
---|
919 | while ( t && t->id != d->focus )
|
---|
920 | t = lstatic->next();
|
---|
921 | do {
|
---|
922 | t = lstatic->next();
|
---|
923 | } while ( t && !t->enabled);
|
---|
924 |
|
---|
925 | if (t)
|
---|
926 | d->focus = t->id;
|
---|
927 | if ( d->focus >= d->id )
|
---|
928 | d->focus = old;
|
---|
929 | } else {
|
---|
930 | // other keys - ignore
|
---|
931 | e->ignore();
|
---|
932 | return;
|
---|
933 | }
|
---|
934 |
|
---|
935 | // if the focus moved, repaint and signal
|
---|
936 | if ( old != d->focus ) {
|
---|
937 | setCurrentTab( d->focus );
|
---|
938 | }
|
---|
939 | }
|
---|
940 |
|
---|
941 |
|
---|
942 | /*!
|
---|
943 | Returns the tab with id \a id or 0 if there is no such tab.
|
---|
944 |
|
---|
945 | \sa count()
|
---|
946 | */
|
---|
947 |
|
---|
948 | QTab * QTabBar::tab( int id ) const
|
---|
949 | {
|
---|
950 | QTab * t;
|
---|
951 | for( t = l->first(); t; t = l->next() )
|
---|
952 | if ( t && t->id == id )
|
---|
953 | return t;
|
---|
954 | return 0;
|
---|
955 | }
|
---|
956 |
|
---|
957 |
|
---|
958 | /*!
|
---|
959 | Returns the tab at position \a index.
|
---|
960 |
|
---|
961 | \sa indexOf()
|
---|
962 | */
|
---|
963 |
|
---|
964 | QTab * QTabBar::tabAt( int index ) const
|
---|
965 | {
|
---|
966 | QTab * t;
|
---|
967 | t = lstatic->at( index );
|
---|
968 | return t;
|
---|
969 | }
|
---|
970 |
|
---|
971 |
|
---|
972 | /*!
|
---|
973 | Returns the position index of the tab with id \a id or -1 if no
|
---|
974 | tab has this \a id.
|
---|
975 |
|
---|
976 | \sa tabAt()
|
---|
977 | */
|
---|
978 | int QTabBar::indexOf( int id ) const
|
---|
979 | {
|
---|
980 | QTab * t;
|
---|
981 | int idx = 0;
|
---|
982 | for( t = lstatic->first(); t; t = lstatic->next() ) {
|
---|
983 | if ( t && t->id == id )
|
---|
984 | return idx;
|
---|
985 | idx++;
|
---|
986 | }
|
---|
987 | return -1;
|
---|
988 | }
|
---|
989 |
|
---|
990 |
|
---|
991 | /*!
|
---|
992 | \property QTabBar::count
|
---|
993 | \brief the number of tabs in the tab bar
|
---|
994 |
|
---|
995 | \sa tab()
|
---|
996 | */
|
---|
997 | int QTabBar::count() const
|
---|
998 | {
|
---|
999 | return l->count();
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 |
|
---|
1003 | /*!
|
---|
1004 | The list of QTab objects in the tab bar.
|
---|
1005 |
|
---|
1006 | This list is unlikely to be in the order that the QTab elements
|
---|
1007 | appear visually. One way of iterating over the tabs is like this:
|
---|
1008 | \code
|
---|
1009 | for ( uint i = 0; i < myTabBar->count(); ++i ) {
|
---|
1010 | nextTab = myTabBar->tabAt( i );
|
---|
1011 | // do something with nextTab
|
---|
1012 | }
|
---|
1013 | \endcode
|
---|
1014 | */
|
---|
1015 | QPtrList<QTab> * QTabBar::tabList()
|
---|
1016 | {
|
---|
1017 | return l;
|
---|
1018 | }
|
---|
1019 |
|
---|
1020 |
|
---|
1021 | /*!
|
---|
1022 | \property QTabBar::shape
|
---|
1023 | \brief the shape of the tabs in the tab bar
|
---|
1024 |
|
---|
1025 | The value of this property is one of the following: \c
|
---|
1026 | RoundedAbove (default), \c RoundedBelow, \c TriangularAbove or \c
|
---|
1027 | TriangularBelow.
|
---|
1028 |
|
---|
1029 | \sa Shape
|
---|
1030 | */
|
---|
1031 | QTabBar::Shape QTabBar::shape() const
|
---|
1032 | {
|
---|
1033 | return d ? d->s : RoundedAbove;
|
---|
1034 | }
|
---|
1035 |
|
---|
1036 | void QTabBar::setShape( Shape s )
|
---|
1037 | {
|
---|
1038 | if ( !d || d->s == s )
|
---|
1039 | return;
|
---|
1040 | //######### must recalculate heights
|
---|
1041 | d->s = s;
|
---|
1042 | update();
|
---|
1043 | }
|
---|
1044 |
|
---|
1045 | /*!
|
---|
1046 | Lays out all existing tabs according to their label and their
|
---|
1047 | iconset.
|
---|
1048 | */
|
---|
1049 | void QTabBar::layoutTabs()
|
---|
1050 | {
|
---|
1051 | if ( lstatic->isEmpty() )
|
---|
1052 | return;
|
---|
1053 |
|
---|
1054 | QSize oldSh(0, 0);
|
---|
1055 | if ( QTab * t = l->first() ) {
|
---|
1056 | QRect r( t->r );
|
---|
1057 | while ( (t = l->next()) != 0 )
|
---|
1058 | r = r.unite( t->r );
|
---|
1059 | oldSh = r.size();
|
---|
1060 | }
|
---|
1061 |
|
---|
1062 | d->btnWidth = style().pixelMetric(QStyle::PM_TabBarScrollButtonWidth, this);
|
---|
1063 | int hframe, vframe, overlap;
|
---|
1064 | hframe = style().pixelMetric( QStyle::PM_TabBarTabHSpace, this );
|
---|
1065 | vframe = style().pixelMetric( QStyle::PM_TabBarTabVSpace, this );
|
---|
1066 | overlap = style().pixelMetric( QStyle::PM_TabBarTabOverlap, this );
|
---|
1067 |
|
---|
1068 | QFontMetrics fm = fontMetrics();
|
---|
1069 | QRect r;
|
---|
1070 | QTab *t;
|
---|
1071 | bool reverse = QApplication::reverseLayout();
|
---|
1072 | if ( reverse )
|
---|
1073 | t = lstatic->last();
|
---|
1074 | else
|
---|
1075 | t = lstatic->first();
|
---|
1076 | int x = 0;
|
---|
1077 | int offset = (t && d->scrolls) ? t->r.x() : 0;
|
---|
1078 | while ( t ) {
|
---|
1079 | int lw = fm.width( t->label );
|
---|
1080 | lw -= t->label.contains('&') * fm.width('&');
|
---|
1081 | lw += t->label.contains("&&") * fm.width('&');
|
---|
1082 | int iw = 0;
|
---|
1083 | int ih = 0;
|
---|
1084 | if ( t->iconset != 0 ) {
|
---|
1085 | iw = t->iconset->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4;
|
---|
1086 | ih = t->iconset->pixmap( QIconSet::Small, QIconSet::Normal ).height();
|
---|
1087 | }
|
---|
1088 | int h = QMAX( fm.height(), ih );
|
---|
1089 | h = QMAX( h, QApplication::globalStrut().height() );
|
---|
1090 |
|
---|
1091 | h += vframe;
|
---|
1092 | t->r = QRect(QPoint(x, 0), style().sizeFromContents(QStyle::CT_TabBarTab, this,
|
---|
1093 | QSize( QMAX( lw + hframe + iw, QApplication::globalStrut().width() ), h ),
|
---|
1094 | QStyleOption(t) ));
|
---|
1095 | x += t->r.width() - overlap;
|
---|
1096 | r = r.unite( t->r );
|
---|
1097 | if ( reverse )
|
---|
1098 | t = lstatic->prev();
|
---|
1099 | else
|
---|
1100 | t = lstatic->next();
|
---|
1101 | }
|
---|
1102 | x += overlap;
|
---|
1103 | int w = (d->scrolls) ? d->leftB->x() : width();
|
---|
1104 | if (x + offset < w)
|
---|
1105 | offset = w - x;
|
---|
1106 | if (offset > 0)
|
---|
1107 | offset = 0;
|
---|
1108 |
|
---|
1109 | for ( t = lstatic->first(); t; t = lstatic->next() ) {
|
---|
1110 | t->r.moveBy( offset, 0 );
|
---|
1111 | t->r.setHeight( r.height() );
|
---|
1112 | }
|
---|
1113 |
|
---|
1114 | if ( sizeHint() != oldSh )
|
---|
1115 | updateGeometry();
|
---|
1116 |
|
---|
1117 | emit layoutChanged();
|
---|
1118 | }
|
---|
1119 |
|
---|
1120 | /*!
|
---|
1121 | \reimp
|
---|
1122 | */
|
---|
1123 |
|
---|
1124 | bool QTabBar::event( QEvent *e )
|
---|
1125 | {
|
---|
1126 | if ( e->type() == QEvent::LanguageChange ) {
|
---|
1127 | layoutTabs();
|
---|
1128 | updateArrowButtons();
|
---|
1129 | makeVisible( tab( currentTab() ));
|
---|
1130 | }
|
---|
1131 |
|
---|
1132 | return QWidget::event( e );
|
---|
1133 | }
|
---|
1134 |
|
---|
1135 | /*!
|
---|
1136 | \reimp
|
---|
1137 | */
|
---|
1138 |
|
---|
1139 | void QTabBar::styleChange( QStyle& old )
|
---|
1140 | {
|
---|
1141 | layoutTabs();
|
---|
1142 | updateArrowButtons();
|
---|
1143 | QWidget::styleChange( old );
|
---|
1144 | }
|
---|
1145 |
|
---|
1146 | /*!
|
---|
1147 | \reimp
|
---|
1148 | */
|
---|
1149 | void QTabBar::focusInEvent( QFocusEvent * )
|
---|
1150 | {
|
---|
1151 | QTab *t = tab( d->focus );
|
---|
1152 | if ( t )
|
---|
1153 | repaint( t->r, FALSE );
|
---|
1154 | }
|
---|
1155 |
|
---|
1156 | /*!
|
---|
1157 | \reimp
|
---|
1158 | */
|
---|
1159 | void QTabBar::focusOutEvent( QFocusEvent * )
|
---|
1160 | {
|
---|
1161 | QTab *t = tab( d->focus );
|
---|
1162 | if ( t )
|
---|
1163 | repaint( t->r, FALSE );
|
---|
1164 | }
|
---|
1165 |
|
---|
1166 | /*!
|
---|
1167 | \reimp
|
---|
1168 | */
|
---|
1169 | void QTabBar::resizeEvent( QResizeEvent * )
|
---|
1170 | {
|
---|
1171 | const int arrowWidth = QMAX( d->btnWidth, QApplication::globalStrut().width() );;
|
---|
1172 | d->rightB->setGeometry( width() - arrowWidth, 0, arrowWidth, height() );
|
---|
1173 | d->leftB->setGeometry( width() - 2*arrowWidth, 0, arrowWidth, height() );
|
---|
1174 | layoutTabs();
|
---|
1175 | updateArrowButtons();
|
---|
1176 | makeVisible( tab( currentTab() ));
|
---|
1177 | }
|
---|
1178 |
|
---|
1179 | void QTabBar::scrollTabs()
|
---|
1180 | {
|
---|
1181 | QTab* left = 0;
|
---|
1182 | QTab* right = 0;
|
---|
1183 | for ( QTab* t = lstatic->first(); t; t = lstatic->next() ) {
|
---|
1184 | if ( t->r.left() < 0 && t->r.right() > 0 )
|
---|
1185 | left = t;
|
---|
1186 | if ( t->r.left() < d->leftB->x()+2 )
|
---|
1187 | right = t;
|
---|
1188 | }
|
---|
1189 |
|
---|
1190 | if ( sender() == d->leftB )
|
---|
1191 | makeVisible( left );
|
---|
1192 | else if ( sender() == d->rightB )
|
---|
1193 | makeVisible( right );
|
---|
1194 | }
|
---|
1195 |
|
---|
1196 | void QTabBar::makeVisible( QTab* tab )
|
---|
1197 | {
|
---|
1198 | bool tooFarLeft = ( tab && tab->r.left() < 0 );
|
---|
1199 | bool tooFarRight = ( tab && tab->r.right() >= d->leftB->x() );
|
---|
1200 |
|
---|
1201 | if ( !d->scrolls || ( !tooFarLeft && ! tooFarRight ) )
|
---|
1202 | return;
|
---|
1203 |
|
---|
1204 | bool bs = signalsBlocked();
|
---|
1205 | blockSignals(TRUE);
|
---|
1206 | layoutTabs();
|
---|
1207 | blockSignals(bs);
|
---|
1208 |
|
---|
1209 | int offset = 0;
|
---|
1210 |
|
---|
1211 | if ( tooFarLeft ) {
|
---|
1212 | offset = tab->r.left();
|
---|
1213 | if (tab != lstatic->first())
|
---|
1214 | offset -= 8;
|
---|
1215 | } else if ( tooFarRight ) {
|
---|
1216 | offset = tab->r.right() - d->leftB->x() + 1;
|
---|
1217 | }
|
---|
1218 |
|
---|
1219 | for ( QTab* t = lstatic->first(); t; t = lstatic->next() )
|
---|
1220 | t->r.moveBy( -offset, 0 );
|
---|
1221 |
|
---|
1222 | d->leftB->setEnabled( lstatic->first()->r.left() < 0);
|
---|
1223 | d->rightB->setEnabled( lstatic->last()->r.right() >= d->leftB->x() );
|
---|
1224 |
|
---|
1225 | // Make sure disabled buttons pop up again
|
---|
1226 | if ( !d->leftB->isEnabled() && d->leftB->isDown() )
|
---|
1227 | d->leftB->setDown( FALSE );
|
---|
1228 | if ( !d->rightB->isEnabled() && d->rightB->isDown() )
|
---|
1229 | d->rightB->setDown( FALSE );
|
---|
1230 |
|
---|
1231 | update();
|
---|
1232 | emit layoutChanged();
|
---|
1233 | }
|
---|
1234 |
|
---|
1235 | void QTabBar::updateArrowButtons()
|
---|
1236 | {
|
---|
1237 | if (lstatic->isEmpty()) {
|
---|
1238 | d->scrolls = FALSE;
|
---|
1239 | } else {
|
---|
1240 | d->scrolls = (lstatic->last()->r.right() - lstatic->first()->r.left() > width());
|
---|
1241 | }
|
---|
1242 | if ( d->scrolls ) {
|
---|
1243 | const int arrowWidth = QMAX( d->btnWidth, QApplication::globalStrut().width() );
|
---|
1244 | if ( QApplication::reverseLayout() ) {
|
---|
1245 | d->rightB->setGeometry( arrowWidth, 0, arrowWidth, height() );
|
---|
1246 | d->leftB->setGeometry( 0, 0, arrowWidth, height() );
|
---|
1247 | } else {
|
---|
1248 | d->rightB->setGeometry( width() - arrowWidth, 0, arrowWidth, height() );
|
---|
1249 | d->leftB->setGeometry( width() - 2*arrowWidth, 0, arrowWidth, height() );
|
---|
1250 | }
|
---|
1251 |
|
---|
1252 | d->leftB->setEnabled( lstatic->first()->r.left() < 0);
|
---|
1253 | d->rightB->setEnabled( lstatic->last()->r.right() >= d->leftB->x() );
|
---|
1254 | d->leftB->show();
|
---|
1255 | d->rightB->show();
|
---|
1256 | } else {
|
---|
1257 | d->leftB->hide();
|
---|
1258 | d->rightB->hide();
|
---|
1259 | layoutTabs();
|
---|
1260 | }
|
---|
1261 | }
|
---|
1262 |
|
---|
1263 | /*!
|
---|
1264 | Removes the tool tip for the tab at index position \a index.
|
---|
1265 | */
|
---|
1266 | void QTabBar::removeToolTip( int index )
|
---|
1267 | {
|
---|
1268 | #ifndef QT_NO_TOOLTIP
|
---|
1269 | QTab * tab = tabAt( index );
|
---|
1270 | if ( !tab || !d->toolTips )
|
---|
1271 | return;
|
---|
1272 | d->toolTips->remove( tab );
|
---|
1273 | #endif
|
---|
1274 | }
|
---|
1275 |
|
---|
1276 | /*!
|
---|
1277 | Sets the tool tip for the tab at index position \a index to \a
|
---|
1278 | tip.
|
---|
1279 | */
|
---|
1280 | void QTabBar::setToolTip( int index, const QString & tip )
|
---|
1281 | {
|
---|
1282 | #ifndef QT_NO_TOOLTIP
|
---|
1283 | QTab * tab = tabAt( index );
|
---|
1284 | if ( !tab )
|
---|
1285 | return;
|
---|
1286 | if ( d->toolTips == 0 )
|
---|
1287 | d->toolTips = new QTabBarToolTip( this );
|
---|
1288 | d->toolTips->add( tab, tip );
|
---|
1289 | #endif
|
---|
1290 | }
|
---|
1291 |
|
---|
1292 | /*!
|
---|
1293 | Returns the tool tip for the tab at index position \a index.
|
---|
1294 | */
|
---|
1295 | QString QTabBar::toolTip( int index ) const
|
---|
1296 | {
|
---|
1297 | #ifndef QT_NO_TOOLTIP
|
---|
1298 | if ( d->toolTips )
|
---|
1299 | return d->toolTips->tipForTab( tabAt( index ) );
|
---|
1300 | else
|
---|
1301 | #endif
|
---|
1302 | return QString();
|
---|
1303 | }
|
---|
1304 |
|
---|
1305 | /*!
|
---|
1306 | Sets the text of the tab to \a text.
|
---|
1307 | */
|
---|
1308 | void QTab::setText( const QString& text )
|
---|
1309 | {
|
---|
1310 | label = text;
|
---|
1311 | if ( tb ) {
|
---|
1312 | #ifndef QT_NO_ACCEL
|
---|
1313 | tb->d->a->removeItem( id );
|
---|
1314 | int p = QAccel::shortcutKey( text );
|
---|
1315 | if ( p )
|
---|
1316 | tb->d->a->insertItem( p, id );
|
---|
1317 | #endif
|
---|
1318 | tb->layoutTabs();
|
---|
1319 | tb->repaint(FALSE);
|
---|
1320 |
|
---|
1321 | #if defined(QT_ACCESSIBILITY_SUPPORT)
|
---|
1322 | QAccessible::updateAccessibility( tb, tb->indexOf(id)+1, QAccessible::NameChanged );
|
---|
1323 | #endif
|
---|
1324 | }
|
---|
1325 | }
|
---|
1326 |
|
---|
1327 | /*!
|
---|
1328 | Sets the tab's iconset to \a icon
|
---|
1329 | */
|
---|
1330 | void QTab::setIconSet( const QIconSet &icon )
|
---|
1331 | {
|
---|
1332 | iconset = new QIconSet( icon );
|
---|
1333 | }
|
---|
1334 |
|
---|
1335 | // this allows us to handle accelerators that are in a QTabBar.
|
---|
1336 | void QTab::setTabBar( QTabBar *newTb )
|
---|
1337 | {
|
---|
1338 | tb = newTb;
|
---|
1339 | }
|
---|
1340 |
|
---|
1341 | /*!
|
---|
1342 | \internal
|
---|
1343 | */
|
---|
1344 | void QTabBar::fontChange( const QFont & oldFont )
|
---|
1345 | {
|
---|
1346 | layoutTabs();
|
---|
1347 | QWidget::fontChange( oldFont );
|
---|
1348 | }
|
---|
1349 |
|
---|
1350 | #endif
|
---|