source: vendor/trolltech/current/src/widgets/qtabwidget.cpp

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

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 29.1 KB
Line 
1/****************************************************************************
2** $Id: qtabwidget.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QTabWidget class
5**
6** Created : 990318
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qtabwidget.h"
39#ifndef QT_NO_TABWIDGET
40#include "qobjectlist.h"
41#include "qtabbar.h"
42#include "qapplication.h"
43#include "qwidgetstack.h"
44#include "qbitmap.h"
45#include "qaccel.h"
46#include "qstyle.h"
47#include "qpainter.h"
48#include "qtoolbutton.h"
49
50/*!
51 \class QTabWidget qtabwidget.h
52 \brief The QTabWidget class provides a stack of tabbed widgets.
53
54 \ingroup organizers
55 \ingroup advanced
56 \mainclass
57
58 A tab widget provides a tab bar of tabs and a `page area' below
59 (or above, see \l{TabPosition}) the tabs. Each tab is associated
60 with a different widget (called a `page'). Only the current tab's
61 page is shown in the page area; all the other tabs' pages are
62 hidden. The user can show a different page by clicking on its tab
63 or by pressing its Alt+\e{letter} accelerator if it has one.
64
65 The normal way to use QTabWidget is to do the following in the
66 constructor:
67 \list 1
68 \i Create a QTabWidget.
69 \i Create a QWidget for each of the pages in the tab dialog,
70 insert children into it, set up geometry management for it and use
71 addTab() (or insertTab()) to set up a tab and keyboard accelerator
72 for it.
73 \i Connect to the signals and slots.
74 \endlist
75
76 The position of the tabs is set with setTabPosition(), their shape
77 with setTabShape(), and their margin with setMargin().
78
79 If you don't call addTab() and the QTabWidget is already visible,
80 then the page you have created will not be visible. Don't
81 confuse the object name you supply to the QWidget constructor and
82 the tab label you supply to addTab(). addTab() takes a name which
83 indicates an accelerator and is meaningful and descriptive to the
84 user, whereas the widget name is used primarily for debugging.
85
86 The signal currentChanged() is emitted when the user selects a
87 page.
88
89 The current page is available as an index position with
90 currentPageIndex() or as a wiget pointer with currentPage(). You
91 can retrieve a pointer to a page with a given index using page(),
92 and can find the index position of a page with indexOf(). Use
93 setCurrentPage() to show a particular page by index, or showPage()
94 to show a page by widget pointer.
95
96 You can change a tab's label and iconset using changeTab() or
97 setTabLabel() and setTabIconSet(). A tab page can be removed with
98 removePage().
99
100 Each tab is either enabled or disabled at any given time (see
101 setTabEnabled()). If a tab is enabled, the tab text is drawn
102 normally and the user can select that tab. If it is disabled, the
103 tab is drawn in a different way and the user cannot select that
104 tab. Note that even if a tab is disabled, the page can still be
105 visible, for example if all of the tabs happen to be disabled.
106
107 Although tab widgets can be a very good way to split up a complex
108 dialog, it's also very easy to get into a mess. See QTabDialog for
109 some design hints. An alternative is to use a QWidgetStack for
110 which you provide some means of navigating between pages, for
111 example, a QToolBar or a QListBox.
112
113 Most of the functionality in QTabWidget is provided by a QTabBar
114 (at the top, providing the tabs) and a QWidgetStack (most of the
115 area, organizing the individual pages).
116
117 <img src=qtabwidget-m.png> <img src=qtabwidget-w.png>
118
119 \sa QTabDialog, QToolBox
120*/
121
122/*!
123 \enum Qt::Corner
124 This enum type specifies a corner in a rectangle:
125 \value TopLeft top left corner
126 \value TopRight top right corner
127 \value BottomLeft bottom left corner
128 \value BottomRight bottom right corner
129*/
130
131/*!
132 \enum QTabWidget::TabPosition
133
134 This enum type defines where QTabWidget draws the tab row:
135 \value Top above the pages
136 \value Bottom below the pages
137*/
138
139/*!
140 \enum QTabWidget::TabShape
141
142 This enum type defines the shape of the tabs:
143 \value Rounded rounded look (normal)
144 \value Triangular triangular look (very unusual, included for completeness)
145*/
146
147/* undocumented now
148 \obsolete
149
150 \fn void QTabWidget::selected( const QString &tabLabel );
151
152 This signal is emitted whenever a tab is selected (raised),
153 including during the first show().
154
155 \sa raise()
156*/
157
158
159/*!
160 \fn void QTabWidget::currentChanged( QWidget* );
161
162 This signal is emitted whenever the current page changes. The
163 parameter is the new current page.
164
165 \sa currentPage(), showPage(), tabLabel()
166*/
167
168class QTabBarBase : public QWidget
169{
170public:
171 QTabBarBase( QTabWidget* parent=0, const char* name=0 )
172 : QWidget( parent, name ) {};
173protected:
174 void paintEvent( QPaintEvent * )
175 {
176 QObject * obj = parent();
177 if( obj ){
178 QTabWidget * t = (QTabWidget *) obj;
179 QPainter p( this );
180 QStyle::SFlags flags = QStyle::Style_Default;
181
182 if ( t->tabPosition() == QTabWidget::Top )
183 flags |= QStyle::Style_Top;
184 if ( t->tabPosition() == QTabWidget::Bottom )
185 flags |= QStyle::Style_Bottom;
186 if(parentWidget()->isEnabled())
187 flags |= QStyle::Style_Enabled;
188
189 style().drawPrimitive( QStyle::PE_TabBarBase, &p, rect(),
190 colorGroup(), flags );
191 }
192 }
193};
194
195class QTabWidgetData
196{
197public:
198 QTabWidgetData()
199 : tabs(0), tabBase(0), stack(0), dirty( TRUE ),
200 pos( QTabWidget::Top ), shape( QTabWidget::Rounded ),
201 leftCornerWidget(0), rightCornerWidget(0) {};
202 ~QTabWidgetData(){};
203 QTabBar* tabs;
204 QTabBarBase* tabBase;
205 QWidgetStack* stack;
206 bool dirty;
207 QTabWidget::TabPosition pos;
208 QTabWidget::TabShape shape;
209 int alignment;
210 QWidget* leftCornerWidget;
211 QWidget* rightCornerWidget;
212};
213
214/*!
215 Constructs a tabbed widget called \a name with parent \a parent,
216 and widget flags \a f.
217*/
218QTabWidget::QTabWidget( QWidget *parent, const char *name, WFlags f )
219 : QWidget( parent, name, f )
220{
221 d = new QTabWidgetData;
222 d->stack = new QWidgetStack( this, "tab pages" );
223 d->stack->installEventFilter( this );
224 d->tabBase = new QTabBarBase( this, "tab base" );
225 d->tabBase->resize( 1, 1 );
226 setTabBar( new QTabBar( this, "tab control" ) );
227
228 d->stack->setFrameStyle( QFrame::TabWidgetPanel | QFrame::Raised );
229#ifdef Q_OS_TEMP
230 d->pos = Bottom;
231#endif
232
233 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
234 setFocusPolicy( TabFocus );
235 setFocusProxy( d->tabs );
236
237 installEventFilter( this );
238}
239
240/*!
241 \reimp
242*/
243QTabWidget::~QTabWidget()
244{
245 delete d;
246}
247
248/*!
249 Adds another tab and page to the tab view.
250
251 The new page is \a child; the tab's label is \a label. Note the
252 difference between the widget name (which you supply to widget
253 constructors and to setTabEnabled(), for example) and the tab
254 label. The name is internal to the program and invariant, whereas
255 the label is shown on-screen and may vary according to language
256 and other factors.
257
258 If the tab's \a label contains an ampersand, the letter following
259 the ampersand is used as an accelerator for the tab, e.g. if the
260 label is "Bro\&wse" then Alt+W becomes an accelerator which will
261 move the focus to this tab.
262
263 If you call addTab() after show() the screen will flicker and the
264 user may be confused.
265
266 \sa insertTab()
267*/
268void QTabWidget::addTab( QWidget *child, const QString &label)
269{
270 insertTab( child, label );
271}
272
273
274/*!
275 \overload
276
277 Adds another tab and page to the tab view.
278
279 This function is the same as addTab(), but with an additional \a
280 iconset.
281*/
282void QTabWidget::addTab( QWidget *child, const QIconSet& iconset, const QString &label )
283{
284 insertTab( child, iconset, label );
285}
286
287/*!
288 \overload
289
290 This is a low-level function for adding tabs. It is useful if you
291 are using setTabBar() to set a QTabBar subclass with an overridden
292 QTabBar::paint() function for a subclass of QTab. The \a child is
293 the new page and \a tab is the tab to put the \a child on.
294*/
295void QTabWidget::addTab( QWidget *child, QTab* tab )
296{
297 insertTab( child, tab );
298}
299
300
301
302/*!
303 Inserts another tab and page to the tab view.
304
305 The new page is \a child; the tab's label is \a label. Note the
306 difference between the widget name (which you supply to widget
307 constructors and to setTabEnabled(), for example) and the tab
308 label. The name is internal to the program and invariant, whereas
309 the label is shown on-screen and may vary according to language
310 and other factors.
311
312 If the tab's \a label contains an ampersand, the letter following
313 the ampersand is used as an accelerator for the tab, e.g. if the
314 label is "Bro\&wse" then Alt+W becomes an accelerator which will
315 move the focus to this tab.
316
317 If \a index is not specified, the tab is simply appended.
318 Otherwise it is inserted at the specified position.
319
320 If you call insertTab() after show(), the screen will flicker and
321 the user may be confused.
322
323 \sa addTab()
324*/
325void QTabWidget::insertTab( QWidget *child, const QString &label, int index)
326{
327 QTab * t = new QTab();
328 Q_CHECK_PTR( t );
329 t->label = label;
330 insertTab( child, t, index );
331}
332
333
334/*!
335 \overload
336
337 Inserts another tab and page to the tab view.
338
339 This function is the same as insertTab(), but with an additional
340 \a iconset.
341*/
342void QTabWidget::insertTab( QWidget *child, const QIconSet& iconset, const QString &label, int index )
343{
344 QTab * t = new QTab();
345 Q_CHECK_PTR( t );
346 t->label = label;
347 t->iconset = new QIconSet( iconset );
348 insertTab( child, t, index );
349}
350
351/*!
352 \overload
353
354 This is a lower-level method for inserting tabs, similar to the
355 other insertTab() method. It is useful if you are using
356 setTabBar() to set a QTabBar subclass with an overridden
357 QTabBar::paint() function for a subclass of QTab. The \a child is
358 the new page, \a tab is the tab to put the \a child on and \a
359 index is the position in the tab bar that this page should occupy.
360*/
361void QTabWidget::insertTab( QWidget *child, QTab* tab, int index)
362{
363 tab->enabled = TRUE;
364 int id = d->tabs->insertTab( tab, index );
365 d->stack->addWidget( child, id );
366 if ( d->stack->frameStyle() != ( QFrame::TabWidgetPanel | QFrame::Raised ) )
367 d->stack->setFrameStyle( QFrame::TabWidgetPanel | QFrame::Raised );
368 setUpLayout();
369}
370
371
372/*!
373 Defines a new \a label for page \a{w}'s tab.
374*/
375void QTabWidget::changeTab( QWidget *w, const QString &label)
376{
377 int id = d->stack->id( w );
378 if ( id < 0 )
379 return;
380 QTab* t = d->tabs->tab( id );
381 if ( !t )
382 return;
383 // this will update the accelerators
384 t->setText( label );
385
386 d->tabs->layoutTabs();
387 d->tabs->update();
388 setUpLayout();
389}
390
391/*!
392 \overload
393
394 Defines a new \a iconset and a new \a label for page \a{w}'s tab.
395*/
396void QTabWidget::changeTab( QWidget *w, const QIconSet& iconset, const QString &label)
397{
398 int id = d->stack->id( w );
399 if ( id < 0 )
400 return;
401 QTab* t = d->tabs->tab( id );
402 if ( !t )
403 return;
404 if ( t->iconset ) {
405 delete t->iconset;
406 t->iconset = 0;
407 }
408 // this will update the accelerators
409 t->iconset = new QIconSet( iconset );
410 t->setText( label );
411
412 d->tabs->layoutTabs();
413 d->tabs->update();
414 setUpLayout();
415}
416
417/*!
418 Returns TRUE if the page \a w is enabled; otherwise returns FALSE.
419
420 \sa setTabEnabled(), QWidget::isEnabled()
421*/
422
423bool QTabWidget::isTabEnabled( QWidget* w ) const
424{
425 int id = d->stack->id( w );
426 if ( id >= 0 )
427 return w->isEnabled();
428 else
429 return FALSE;
430}
431
432/*!
433 If \a enable is TRUE, page \a w is enabled; otherwise page \a w is
434 disabled. The page's tab is redrawn appropriately.
435
436 QTabWidget uses QWidget::setEnabled() internally, rather than
437 keeping a separate flag.
438
439 Note that even a disabled tab/page may be visible. If the page is
440 visible already, QTabWidget will not hide it; if all the pages are
441 disabled, QTabWidget will show one of them.
442
443 \sa isTabEnabled(), QWidget::setEnabled()
444*/
445
446void QTabWidget::setTabEnabled( QWidget* w, bool enable)
447{
448 int id = d->stack->id( w );
449 if ( id >= 0 ) {
450 w->setEnabled( enable );
451 d->tabs->setTabEnabled( id, enable );
452 }
453}
454
455/*!
456 Sets widget \a w to be the shown in the specified \a corner of the
457 tab widget.
458
459 Only the horizontal element of the \a corner will be used.
460
461 \sa cornerWidget(), setTabPosition()
462*/
463void QTabWidget::setCornerWidget( QWidget * w, Qt::Corner corner )
464{
465 if ( !w )
466 return;
467 if ( (uint)corner & 1 )
468 d->rightCornerWidget = w;
469 else
470 d->leftCornerWidget = w;
471}
472
473/*!
474 Returns the widget shown in the \a corner of the tab widget or 0.
475*/
476QWidget * QTabWidget::cornerWidget( Qt::Corner corner ) const
477{
478 if ( (uint)corner & 1 )
479 return d->rightCornerWidget;
480 return d->leftCornerWidget;
481}
482
483/*!
484 Ensures that page \a w is shown. This is useful mainly for
485 accelerators.
486
487 \warning Used carelessly, this function can easily surprise or
488 confuse the user.
489
490 \sa QTabBar::setCurrentTab()
491*/
492void QTabWidget::showPage( QWidget * w)
493{
494 int id = d->stack->id( w );
495 if ( id >= 0 ) {
496 d->stack->raiseWidget( w );
497 d->tabs->setCurrentTab( id );
498 // ### why overwrite the frame style?
499 if ( d->stack->frameStyle() != ( QFrame::TabWidgetPanel |QFrame::Raised ) )
500 d->stack->setFrameStyle( QFrame::TabWidgetPanel | QFrame::Raised );
501 }
502}
503
504/*!
505 Removes page \a w from this stack of widgets. Does not delete \a
506 w.
507
508 \sa addTab(), showPage(), QWidgetStack::removeWidget()
509*/
510void QTabWidget::removePage( QWidget * w )
511{
512 int id = d->stack->id( w );
513 if ( id >= 0 ) {
514 int oldId = d->stack->id(currentPage());
515 bool fixCurrentTab = oldId == id;
516 //switches to the next enabled tab
517 d->tabs->setTabEnabled( id, FALSE );
518 //if no next enabled page we fix the current page
519 fixCurrentTab = fixCurrentTab && oldId == d->stack->id(currentPage());
520
521 d->stack->removeWidget( w );
522 d->tabs->removeTab( d->tabs->tab(id) );
523 if ( fixCurrentTab )
524 showTab( d->tabs->currentTab() );
525 setUpLayout();
526
527 if ( d->tabs->count() == 0 )
528 d->stack->setFrameStyle( QFrame::NoFrame );
529 }
530}
531
532/*!
533 Returns the label text for the tab on page \a w.
534*/
535
536QString QTabWidget::tabLabel( QWidget * w ) const
537{
538 QTab * t = d->tabs->tab( d->stack->id( w ) );
539 return t ? t->label : QString::null;
540}
541
542/*!
543 Sets the tab label for page \a w to \a l
544*/
545
546void QTabWidget::setTabLabel( QWidget * w, const QString &l )
547{
548 QTab * t = d->tabs->tab( d->stack->id( w ) );
549 if ( t )
550 t->label = l;
551 d->tabs->layoutTabs();
552 d->tabs->update();
553 setUpLayout();
554}
555
556/*!
557 Returns a pointer to the page currently being displayed by the tab
558 dialog. The tab dialog does its best to make sure that this value
559 is never 0 (but if you try hard enough, it can be).
560*/
561
562QWidget * QTabWidget::currentPage() const
563{
564 return page( currentPageIndex() );
565}
566
567/*!
568 \property QTabWidget::autoMask
569 \brief whether the tab widget is automatically masked
570
571 \sa QWidget::setAutoMask()
572*/
573
574/*!
575 \property QTabWidget::currentPage
576 \brief the index position of the current tab page
577
578 \sa QTabBar::currentTab()
579*/
580
581int QTabWidget::currentPageIndex() const
582{
583 return d->tabs->indexOf( d->tabs->currentTab() );
584}
585
586void QTabWidget::setCurrentPage( int index )
587{
588 d->tabs->setCurrentTab( d->tabs->tabAt( index ) );
589 showTab( d->tabs->currentTab() );
590}
591
592
593/*!
594 Returns the index position of page \a w, or -1 if the widget
595 cannot be found.
596*/
597int QTabWidget::indexOf( QWidget* w ) const
598{
599 return d->tabs->indexOf( d->stack->id( w ) );
600}
601
602
603/*!
604 \reimp
605*/
606void QTabWidget::resizeEvent( QResizeEvent *e )
607{
608 QWidget::resizeEvent( e );
609 setUpLayout();
610}
611
612/*!
613 Replaces the dialog's QTabBar heading with the tab bar \a tb. Note
614 that this must be called \e before any tabs have been added, or
615 the behavior is undefined.
616
617 \sa tabBar()
618*/
619void QTabWidget::setTabBar( QTabBar* tb)
620{
621 if ( tb->parentWidget() != this )
622 tb->reparent( this, QPoint(0,0), TRUE );
623 delete d->tabs;
624 d->tabs = tb;
625 setFocusProxy( d->tabs );
626 connect( d->tabs, SIGNAL(selected(int)),
627 this, SLOT(showTab(int)) );
628 setUpLayout();
629}
630
631
632/*!
633 Returns the current QTabBar.
634
635 \sa setTabBar()
636*/
637QTabBar* QTabWidget::tabBar() const
638{
639 return d->tabs;
640}
641
642/*!
643 Ensures that the selected tab's page is visible and appropriately
644 sized.
645*/
646
647void QTabWidget::showTab( int i )
648{
649 if ( d->stack->widget( i ) ) {
650 d->stack->raiseWidget( i );
651 emit selected( d->tabs->tab( i )->label );
652 emit currentChanged( d->stack->widget( i ) );
653 }
654}
655
656/*
657 Set up the layout.
658*/
659void QTabWidget::setUpLayout( bool onlyCheck )
660{
661 if ( onlyCheck && !d->dirty )
662 return; // nothing to do
663
664 if ( !isVisible() ) {
665 d->dirty = TRUE;
666 return; // we'll do it later
667 }
668
669 QSize t( 0, d->stack->frameWidth() );
670 if ( d->tabs->isVisibleTo(this) )
671 t = d->tabs->sizeHint();
672 int lcw = 0;
673 if ( d->leftCornerWidget && d->leftCornerWidget->isVisible() ) {
674 QSize sz = d->leftCornerWidget->sizeHint();
675 d->leftCornerWidget->resize(sz);
676 lcw = sz.width();
677 if ( t.height() > lcw )
678 lcw = t.height();
679 }
680 int rcw = 0;
681 if ( d->rightCornerWidget && d->rightCornerWidget->isVisible() ) {
682 QSize sz = d->rightCornerWidget->sizeHint();
683 d->rightCornerWidget->resize(sz);
684 rcw = sz.width();
685 if ( t.height() > rcw )
686 rcw = t.height();
687 }
688 int tw = width() - lcw - rcw;
689 if ( t.width() > tw )
690 t.setWidth( tw );
691 int lw = d->stack->lineWidth();
692 bool reverse = QApplication::reverseLayout();
693 int tabx, taby, stacky, exty, exth, overlap;
694
695 exth = style().pixelMetric( QStyle::PM_TabBarBaseHeight, this );
696 overlap = style().pixelMetric( QStyle::PM_TabBarBaseOverlap, this );
697
698 if ( reverse )
699 tabx = QMIN( width() - t.width(), width() - t.width() - lw + 2 ) - lcw;
700 else
701 tabx = QMAX( 0, lw - 2 ) + lcw;
702 if ( d->pos == Bottom ) {
703 taby = height() - t.height() - lw;
704 stacky = 0;
705 exty = taby - (exth - overlap);
706 } else { // Top
707 taby = 0;
708 stacky = t.height()-lw + (exth - overlap);
709 exty = taby + t.height() - overlap;
710 }
711
712 // do alignment
713 int alignment = style().styleHint( QStyle::SH_TabBar_Alignment, this );
714 if ( alignment != AlignLeft && t.width() < width() ) {
715 if ( alignment == AlignHCenter )
716 tabx += (width()-lcw-rcw)/2 - t.width()/2;
717 else if ( alignment == AlignRight )
718 tabx += width() - t.width() - rcw;
719 }
720
721 d->tabs->setGeometry( tabx, taby, t.width(), t.height() );
722 d->tabBase->setGeometry( 0, exty, width(), exth );
723 if ( exth == 0 )
724 d->tabBase->hide();
725 else
726 d->tabBase->show();
727
728 d->stack->setGeometry( 0, stacky, width(), height() - (exth-overlap) -
729 t.height()+QMAX(0, lw-2));
730
731 d->dirty = FALSE;
732
733 // move cornerwidgets
734 if ( d->leftCornerWidget ) {
735 int y = ( t.height() / 2 ) - ( d->leftCornerWidget->height() / 2 );
736 int x = ( reverse ? width() - lcw + y : y );
737 d->leftCornerWidget->move( x, y + taby );
738 }
739 if ( d->rightCornerWidget ) {
740 int y = ( t.height() / 2 ) - ( d->rightCornerWidget->height() / 2 );
741
742 if ( !onlyCheck )
743 update();
744 updateGeometry();
745 if ( autoMask() )
746 updateMask();
747 int x = ( reverse ? y : width() - rcw + y );
748 d->rightCornerWidget->move( x, y + taby );
749 }
750}
751
752/*!
753 \reimp
754*/
755QSize QTabWidget::sizeHint() const
756{
757 QSize lc(0, 0), rc(0, 0);
758
759 if (d->leftCornerWidget)
760 lc = d->leftCornerWidget->sizeHint();
761 if(d->rightCornerWidget)
762 rc = d->rightCornerWidget->sizeHint();
763 if ( !d->dirty ) {
764 QTabWidget *that = (QTabWidget*)this;
765 that->setUpLayout( TRUE );
766 }
767 QSize s( d->stack->sizeHint() );
768 QSize t( d->tabs->sizeHint() );
769 if(!style().styleHint(QStyle::SH_TabBar_PreferNoArrows, d->tabs))
770 t = t.boundedTo( QSize(200,200) );
771
772 QSize sz( QMAX( s.width(), t.width() + rc.width() + lc.width() ),
773 s.height() + (QMAX( rc.height(), QMAX(lc.height(), t.height()))) + ( d->tabBase->isVisible() ? d->tabBase->height() : 0 ) );
774 return style().sizeFromContents(QStyle::CT_TabWidget, this, sz).expandedTo(QApplication::globalStrut());
775}
776
777
778/*!
779 \reimp
780
781 Returns a suitable minimum size for the tab widget.
782*/
783QSize QTabWidget::minimumSizeHint() const
784{
785 QSize lc(0, 0), rc(0, 0);
786
787 if(d->leftCornerWidget)
788 lc = d->leftCornerWidget->minimumSizeHint();
789 if(d->rightCornerWidget)
790 rc = d->rightCornerWidget->minimumSizeHint();
791 if ( !d->dirty ) {
792 QTabWidget *that = (QTabWidget*)this;
793 that->setUpLayout( TRUE );
794 }
795 QSize s( d->stack->minimumSizeHint() );
796 QSize t( d->tabs->minimumSizeHint() );
797
798 QSize sz( QMAX( s.width(), t.width() + rc.width() + lc.width() ),
799 s.height() + (QMAX( rc.height(), QMAX(lc.height(), t.height()))) + ( d->tabBase->isVisible() ? d->tabBase->height() : 0 ) );
800 return style().sizeFromContents(QStyle::CT_TabWidget, this, sz).expandedTo(QApplication::globalStrut());
801}
802
803/*!
804 \reimp
805 */
806void QTabWidget::showEvent( QShowEvent * )
807{
808 setUpLayout();
809}
810
811
812/*!
813 \property QTabWidget::tabPosition
814 \brief the position of the tabs in this tab widget
815
816 Possible values for this property are \c QTabWidget::Top and \c
817 QTabWidget::Bottom.
818
819 \sa TabPosition
820*/
821QTabWidget::TabPosition QTabWidget::tabPosition() const
822{
823 return d->pos;
824}
825
826void QTabWidget::setTabPosition( TabPosition pos)
827{
828 if (d->pos == pos)
829 return;
830 d->pos = pos;
831 if (d->tabs->shape() == QTabBar::TriangularAbove || d->tabs->shape() == QTabBar::TriangularBelow ) {
832 if ( pos == Bottom )
833 d->tabs->setShape( QTabBar::TriangularBelow );
834 else
835 d->tabs->setShape( QTabBar::TriangularAbove );
836 }
837 else {
838 if ( pos == Bottom )
839 d->tabs->setShape( QTabBar::RoundedBelow );
840 else
841 d->tabs->setShape( QTabBar::RoundedAbove );
842 }
843 d->tabs->layoutTabs();
844 setUpLayout();
845}
846
847/*!
848 \property QTabWidget::tabShape
849 \brief the shape of the tabs in this tab widget
850
851 Possible values for this property are \c QTabWidget::Rounded
852 (default) or \c QTabWidget::Triangular.
853
854 \sa TabShape
855*/
856
857QTabWidget::TabShape QTabWidget::tabShape() const
858{
859 return d->shape;
860}
861
862void QTabWidget::setTabShape( TabShape s )
863{
864 if ( d->shape == s )
865 return;
866 d->shape = s;
867 if ( d->pos == Top ) {
868 if ( s == Rounded )
869 d->tabs->setShape( QTabBar::RoundedAbove );
870 else
871 d->tabs->setShape( QTabBar::TriangularAbove );
872 } else {
873 if ( s == Rounded )
874 d->tabs->setShape( QTabBar::RoundedBelow );
875 else
876 d->tabs->setShape( QTabBar::TriangularBelow );
877 }
878 d->tabs->layoutTabs();
879 setUpLayout();
880}
881
882
883/*!
884 \property QTabWidget::margin
885 \brief the margin in this tab widget
886
887 The margin is the distance between the innermost pixel of the
888 frame and the outermost pixel of the pages.
889*/
890int QTabWidget::margin() const
891{
892 return d->stack->margin();
893}
894
895void QTabWidget::setMargin( int w )
896{
897 d->stack->setMargin( w );
898 setUpLayout();
899}
900
901
902/*!
903 \reimp
904 */
905void QTabWidget::styleChange( QStyle& old )
906{
907 QWidget::styleChange( old );
908 setUpLayout();
909}
910
911
912/*!
913 \reimp
914 */
915void QTabWidget::updateMask()
916{
917 if ( !autoMask() )
918 return;
919
920 QRect r;
921 QRegion reg( r );
922 reg += QRegion( d->tabs->geometry() );
923 reg += QRegion( d->stack->geometry() );
924 setMask( reg );
925}
926
927
928/*!
929 \reimp
930 */
931bool QTabWidget::eventFilter( QObject *o, QEvent * e)
932{
933 if ( o == this ) {
934 if ( e->type() == QEvent::LanguageChange || e->type() == QEvent::LayoutHint ) {
935 d->dirty = TRUE;
936 setUpLayout();
937 updateGeometry();
938 } else if ( e->type() == QEvent::KeyPress ) {
939 QKeyEvent *ke = (QKeyEvent*) e;
940 if ( ( ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab ) &&
941 count() > 1 &&
942 ke->state() & Qt::ControlButton ) {
943 int page = currentPageIndex();
944 if ( ke->key() == Qt::Key_Backtab || ke->state() & Qt::ShiftButton ) {
945 page--;
946 if ( page < 0 )
947 page = count() - 1;
948 } else {
949 page++;
950 if ( page >= count() )
951 page = 0;
952 }
953 setCurrentPage( page );
954 if ( !qApp->focusWidget() )
955 d->tabs->setFocus();
956 return TRUE;
957 }
958 }
959
960 } else if ( o == d->stack ) {
961 if ( e->type() == QEvent::ChildRemoved
962 && ( (QChildEvent*)e )->child()->isWidgetType() ) {
963 removePage( (QWidget*) ( (QChildEvent*)e )->child() );
964 return TRUE;
965 } else if ( e->type() == QEvent::LayoutHint ) {
966 updateGeometry();
967 }
968 }
969 return FALSE;
970}
971
972/*!
973 Returns the tab page at index position \a index or 0 if the \a
974 index is out of range.
975*/
976QWidget *QTabWidget::page( int index ) const
977{
978 QTab *t = d->tabs->tabAt(index);
979 if ( t )
980 return d->stack->widget( t->id );
981 // else
982 return 0;
983}
984
985/*!
986 Returns the label of the tab at index position \a index or
987 QString::null if the \a index is out of range.
988*/
989QString QTabWidget::label( int index ) const
990{
991 QTab *t = d->tabs->tabAt( index );
992 if ( t )
993 return t->label;
994 // else
995 return QString::null;
996}
997
998/*!
999 \property QTabWidget::count
1000 \brief the number of tabs in the tab bar
1001*/
1002int QTabWidget::count() const
1003{
1004 return d->tabs->count();
1005}
1006
1007/*!
1008 Returns the iconset of page \a w or a \link QIconSet::QIconSet()
1009 null iconset\endlink if \a w is not a tab page or does not have an
1010 iconset.
1011*/
1012QIconSet QTabWidget::tabIconSet( QWidget * w ) const
1013{
1014 int id = d->stack->id( w );
1015 if ( id < 0 )
1016 return QIconSet();
1017 QTab* t = d->tabs->tab( id );
1018 if ( !t )
1019 return QIconSet();
1020 if ( t->iconset )
1021 return QIconSet( *t->iconset );
1022 else
1023 return QIconSet();
1024}
1025
1026/*!
1027 Sets the iconset for page \a w to \a iconset.
1028*/
1029void QTabWidget::setTabIconSet( QWidget * w, const QIconSet & iconset )
1030{
1031 int id = d->stack->id( w );
1032 if ( id < 0 )
1033 return;
1034 QTab* t = d->tabs->tab( id );
1035 if ( !t )
1036 return;
1037 if ( t->iconset )
1038 delete t->iconset;
1039 t->iconset = new QIconSet( iconset );
1040
1041 d->tabs->layoutTabs();
1042 d->tabs->update();
1043 setUpLayout();
1044}
1045
1046/*!
1047 Sets the tab tool tip for page \a w to \a tip.
1048
1049 \sa removeTabToolTip(), tabToolTip()
1050*/
1051void QTabWidget::setTabToolTip( QWidget * w, const QString & tip )
1052{
1053 int index = d->tabs->indexOf( d->stack->id( w ) );
1054 if ( index < 0 )
1055 return;
1056 d->tabs->setToolTip( index, tip );
1057}
1058
1059/*!
1060 Returns the tab tool tip for page \a w or QString::null if no tool
1061 tip has been set.
1062
1063 \sa setTabToolTip(), removeTabToolTip()
1064*/
1065QString QTabWidget::tabToolTip( QWidget * w ) const
1066{
1067 int index = d->tabs->indexOf( d->stack->id( w ) );
1068 if ( index < 0 )
1069 return QString();
1070 return d->tabs->toolTip( index );
1071}
1072
1073/*!
1074 Removes the tab tool tip for page \a w. If the page does not have
1075 a tip, nothing happens.
1076
1077 \sa setTabToolTip(), tabToolTip()
1078*/
1079void QTabWidget::removeTabToolTip( QWidget * w )
1080{
1081 int index = d->tabs->indexOf( d->stack->id( w ) );
1082 if ( index < 0 )
1083 return;
1084 d->tabs->removeToolTip( index );
1085}
1086
1087#endif
Note: See TracBrowser for help on using the repository browser.