source: trunk/src/gui/widgets/qtabwidget.cpp@ 500

Last change on this file since 500 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 39.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtabwidget.h"
43
44#ifndef QT_NO_TABWIDGET
45#include "private/qwidget_p.h"
46#include "private/qtabbar_p.h"
47#include "qapplication.h"
48#include "qbitmap.h"
49#include "qdesktopwidget.h"
50#include "qevent.h"
51#include "qlayout.h"
52#include "qstackedwidget.h"
53#include "qstyle.h"
54#include "qstyleoption.h"
55#include "qstylepainter.h"
56#include "qtabbar.h"
57#include "qtoolbutton.h"
58
59QT_BEGIN_NAMESPACE
60
61/*!
62 \class QTabWidget
63 \brief The QTabWidget class provides a stack of tabbed widgets.
64
65 \ingroup organizers
66 \ingroup basicwidgets
67 \mainclass
68
69 A tab widget provides a tab bar (see QTabBar) and a "page area"
70 that is used to display pages related to each tab. By default, the
71 tab bar is shown above the page area, but different configurations
72 are available (see \l{TabPosition}). Each tab is associated with a
73 different widget (called a page). Only the current page is shown in
74 the page area; all the other pages are hidden. The user can show a
75 different page by clicking on its tab or by pressing its
76 Alt+\e{letter} shortcut if it has one.
77
78 The normal way to use QTabWidget is to do the following:
79 \list 1
80 \i Create a QTabWidget.
81 \i Create a QWidget for each of the pages in the tab dialog, but
82 do not specify parent widgets for them.
83 \i Insert child widgets into the page widget, using layouts to
84 position them as normal.
85 \i Call addTab() or insertTab() to put the page widgets into the
86 tab widget, giving each tab a suitable label with an optional
87 keyboard shortcut.
88 \endlist
89
90 The position of the tabs is defined by \l tabPosition, their shape
91 by \l tabShape.
92
93 The signal currentChanged() is emitted when the user selects a
94 page.
95
96 The current page index is available as currentIndex(), the current
97 page widget with currentWidget(). You can retrieve a pointer to a
98 page widget with a given index using widget(), and can find the
99 index position of a widget with indexOf(). Use setCurrentWidget()
100 or setCurrentIndex() to show a particular page.
101
102 You can change a tab's text and icon using setTabText() or
103 setTabIcon(). A tab and its associated page can be removed with
104 removeTab().
105
106 Each tab is either enabled or disabled at any given time (see
107 setTabEnabled()). If a tab is enabled, the tab text is drawn
108 normally and the user can select that tab. If it is disabled, the
109 tab is drawn in a different way and the user cannot select that
110 tab. Note that even if a tab is disabled, the page can still be
111 visible, for example if all of the tabs happen to be disabled.
112
113 Tab widgets can be a very good way to split up a complex dialog.
114 An alternative is to use a QStackedWidget for which you provide some
115 means of navigating between pages, for example, a QToolBar or a
116 QListWidget.
117
118 Most of the functionality in QTabWidget is provided by a QTabBar
119 (at the top, providing the tabs) and a QStackedWidget (most of the
120 area, organizing the individual pages).
121
122 \table 100%
123 \row \o \inlineimage windowsxp-tabwidget.png Screenshot of a Windows XP style tab widget
124 \o \inlineimage macintosh-tabwidget.png Screenshot of a Macintosh style tab widget
125 \o \inlineimage plastique-tabwidget.png Screenshot of a Plastique style tab widget
126 \row \o A Windows XP style tab widget.
127 \o A Macintosh style tab widget.
128 \o A Plastique style tab widget.
129 \endtable
130
131 \sa QTabBar, QStackedWidget, QToolBox, {Tab Dialog Example}
132*/
133
134/*!
135 \enum QTabWidget::TabPosition
136
137 This enum type defines where QTabWidget draws the tab row:
138
139 \value North The tabs are drawn above the pages.
140 \value South The tabs are drawn below the pages.
141 \value West The tabs are drawn to the left of the pages.
142 \value East The tabs are drawn to the right of the pages.
143 \omitvalue Bottom
144 \omitvalue Top
145*/
146
147/*!
148 \enum QTabWidget::TabShape
149
150 This enum type defines the shape of the tabs:
151 \value Rounded The tabs are drawn with a rounded look. This is the default
152 shape.
153 \value Triangular The tabs are drawn with a triangular look.
154*/
155
156/*!
157 \fn void QTabWidget::selected(const QString &tabLabel)
158
159 This signal is emitted whenever a tab is selected (raised),
160 including during the first show().
161
162 You can normally use currentChanged() instead.
163*/
164
165/*!
166 \fn void QTabWidget::currentChanged(int index)
167
168 This signal is emitted whenever the current page index changes.
169 The parameter is the new current page \a index position, or -1
170 if there isn't a new one (for example, if there are no widgets
171 in the QTabWidget)
172
173 \sa currentWidget() currentIndex
174*/
175
176/*!
177 \fn void QTabWidget::tabCloseRequested(int index)
178 \since 4.5
179
180 This signal is emitted when the close button on a tab is clicked.
181 The \a index is the index that should be removed.
182
183 \sa setTabsClosable()
184*/
185
186class QTabWidgetPrivate : public QWidgetPrivate
187{
188 Q_DECLARE_PUBLIC(QTabWidget)
189
190public:
191 QTabWidgetPrivate();
192 ~QTabWidgetPrivate();
193 void updateTabBarPosition();
194 void _q_showTab(int);
195 void _q_removeTab(int);
196 void _q_tabMoved(int from, int to);
197 void init();
198
199 QTabBar *tabs;
200 QStackedWidget *stack;
201 QRect panelRect;
202 bool dirty;
203 QTabWidget::TabPosition pos;
204 QTabWidget::TabShape shape;
205 int alignment;
206 QWidget *leftCornerWidget;
207 QWidget *rightCornerWidget;
208};
209
210QTabWidgetPrivate::QTabWidgetPrivate()
211 : tabs(0), stack(0), dirty(true),
212 pos(QTabWidget::North), shape(QTabWidget::Rounded),
213 leftCornerWidget(0), rightCornerWidget(0)
214{}
215
216QTabWidgetPrivate::~QTabWidgetPrivate()
217{}
218
219void QTabWidgetPrivate::init()
220{
221 Q_Q(QTabWidget);
222
223 stack = new QStackedWidget(q);
224 stack->setObjectName(QLatin1String("qt_tabwidget_stackedwidget"));
225 stack->setLineWidth(0);
226 // hack so that QMacStyle::layoutSpacing() can detect tab widget pages
227 stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::TabWidget));
228
229 QObject::connect(stack, SIGNAL(widgetRemoved(int)), q, SLOT(_q_removeTab(int)));
230 QTabBar *tabBar = new QTabBar(q);
231 tabBar->setObjectName(QLatin1String("qt_tabwidget_tabbar"));
232 tabBar->setDrawBase(false);
233 q->setTabBar(tabBar);
234
235 q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding,
236 QSizePolicy::TabWidget));
237#ifdef QT_KEYPAD_NAVIGATION
238 if (QApplication::keypadNavigationEnabled())
239 q->setFocusPolicy(Qt::NoFocus);
240 else
241#endif
242 q->setFocusPolicy(Qt::TabFocus);
243 q->setFocusProxy(tabs);
244 q->setTabPosition(static_cast<QTabWidget::TabPosition> (q->style()->styleHint(
245 QStyle::SH_TabWidget_DefaultTabPosition, 0, q )));
246
247}
248
249/*!
250 Initialize \a option with the values from this QTabWidget. This method is useful
251 for subclasses when they need a QStyleOptionTabWidgetFrame, but don't want to fill
252 in all the information themselves.
253
254 \sa QStyleOption::initFrom() QTabBar::initStyleOption()
255*/
256void QTabWidget::initStyleOption(QStyleOptionTabWidgetFrame *option) const
257{
258 if (!option)
259 return;
260
261 Q_D(const QTabWidget);
262 option->initFrom(this);
263
264 if (documentMode())
265 option->lineWidth = 0;
266 else
267 option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this);
268
269 int exth = style()->pixelMetric(QStyle::PM_TabBarBaseHeight, 0, this);
270 QSize t(0, d->stack->frameWidth());
271 if (d->tabs->isVisibleTo(const_cast<QTabWidget *>(this))) {
272 t = d->tabs->sizeHint();
273 if (documentMode()) {
274 if (tabPosition() == East || tabPosition() == West) {
275 t.setHeight(height());
276 } else {
277 t.setWidth(width());
278 }
279 }
280 }
281
282 if (d->rightCornerWidget) {
283 const QSize rightCornerSizeHint = d->rightCornerWidget->sizeHint();
284 const QSize bounds(rightCornerSizeHint.width(), t.height() - exth);
285 option->rightCornerWidgetSize = rightCornerSizeHint.boundedTo(bounds);
286 } else {
287 option->rightCornerWidgetSize = QSize(0, 0);
288 }
289
290 if (d->leftCornerWidget) {
291 const QSize leftCornerSizeHint = d->leftCornerWidget->sizeHint();
292 const QSize bounds(leftCornerSizeHint.width(), t.height() - exth);
293 option->leftCornerWidgetSize = leftCornerSizeHint.boundedTo(bounds);
294 } else {
295 option->leftCornerWidgetSize = QSize(0, 0);
296 }
297
298 switch (d->pos) {
299 case QTabWidget::North:
300 option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedNorth
301 : QTabBar::TriangularNorth;
302 break;
303 case QTabWidget::South:
304 option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedSouth
305 : QTabBar::TriangularSouth;
306 break;
307 case QTabWidget::West:
308 option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedWest
309 : QTabBar::TriangularWest;
310 break;
311 case QTabWidget::East:
312 option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedEast
313 : QTabBar::TriangularEast;
314 break;
315 }
316 option->tabBarSize = t;
317}
318
319/*!
320 Constructs a tabbed widget with parent \a parent.
321*/
322QTabWidget::QTabWidget(QWidget *parent)
323 : QWidget(*new QTabWidgetPrivate, parent, 0)
324{
325 Q_D(QTabWidget);
326 d->init();
327}
328
329#ifdef QT3_SUPPORT
330/*!
331 Use one of the constructors that doesn't take the \a name
332 argument and then use setObjectName() instead.
333*/
334QTabWidget::QTabWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
335 : QWidget(*new QTabWidgetPrivate, parent, f)
336{
337 Q_D(QTabWidget);
338 setObjectName(QString::fromAscii(name));
339 d->init();
340}
341#endif
342
343/*!
344 Destroys the tabbed widget.
345*/
346QTabWidget::~QTabWidget()
347{
348}
349
350/*!
351 \fn int QTabWidget::addTab(QWidget *page, const QString &label)
352
353 Adds a tab with the given \a page and \a label to the tab widget,
354 and returns the index of the tab in the tab bar.
355
356 If the tab's \a label contains an ampersand, the letter following
357 the ampersand is used as a shortcut for the tab, e.g. if the
358 label is "Bro\&wse" then Alt+W becomes a shortcut which will
359 move the focus to this tab.
360
361 \note If you call addTab() after show(), the layout system will try
362 to adjust to the changes in its widgets hierarchy and may cause
363 flicker. To prevent this, you can set the QWidget::updatesEnabled
364 property to false prior to changes; remember to set the property
365 to true when the changes are done, making the widget receive paint
366 events again.
367
368 \sa insertTab()
369*/
370int QTabWidget::addTab(QWidget *child, const QString &label)
371{
372 return insertTab(-1, child, label);
373}
374
375
376/*!
377 \fn int QTabWidget::addTab(QWidget *page, const QIcon &icon, const QString &label)
378 \overload
379
380 Adds a tab with the given \a page, \a icon, and \a label to the tab
381 widget, and returns the index of the tab in the tab bar.
382
383 This function is the same as addTab(), but with an additional \a
384 icon.
385*/
386int QTabWidget::addTab(QWidget *child, const QIcon& icon, const QString &label)
387{
388 return insertTab(-1, child, icon, label);
389}
390
391
392/*!
393 \fn int QTabWidget::insertTab(int index, QWidget *page, const QString &label)
394
395 Inserts a tab with the given \a label and \a page into the tab
396 widget at the specified \a index, and returns the index of the
397 inserted tab in the tab bar.
398
399 The label is displayed in the tab and may vary in appearance depending
400 on the configuration of the tab widget.
401
402 If the tab's \a label contains an ampersand, the letter following
403 the ampersand is used as a shortcut for the tab, e.g. if the
404 label is "Bro\&wse" then Alt+W becomes a shortcut which will
405 move the focus to this tab.
406
407 If \a index is out of range, the tab is simply appended.
408 Otherwise it is inserted at the specified position.
409
410 If the QTabWidget was empty before this function is called, the
411 new page becomes the current page. Inserting a new tab at an index
412 less than or equal to the current index will increment the current
413 index, but keep the current page.
414
415 \note If you call insertTab() after show(), the layout system will try
416 to adjust to the changes in its widgets hierarchy and may cause
417 flicker. To prevent this, you can set the QWidget::updatesEnabled
418 property to false prior to changes; remember to set the property
419 to true when the changes are done, making the widget receive paint
420 events again.
421
422 \sa addTab()
423*/
424int QTabWidget::insertTab(int index, QWidget *w, const QString &label)
425{
426 return insertTab(index, w, QIcon(), label);
427}
428
429
430/*!
431 \fn int QTabWidget::insertTab(int index, QWidget *page, const QIcon& icon, const QString &label)
432 \overload
433
434 Inserts a tab with the given \a label, \a page, and \a icon into
435 the tab widget at the specified \a index, and returns the index of the
436 inserted tab in the tab bar.
437
438 This function is the same as insertTab(), but with an additional
439 \a icon.
440*/
441int QTabWidget::insertTab(int index, QWidget *w, const QIcon& icon, const QString &label)
442{
443 Q_D(QTabWidget);
444 if(!w)
445 return -1;
446 index = d->stack->insertWidget(index, w);
447 d->tabs->insertTab(index, icon, label);
448 setUpLayout();
449 tabInserted(index);
450
451 return index;
452}
453
454
455/*!
456 Defines a new \a label for the page at position \a index's tab.
457
458 If the provided text contains an ampersand character ('&'), a
459 shortcut is automatically created for it. The character that
460 follows the '&' will be used as the shortcut key. Any previous
461 shortcut will be overwritten, or cleared if no shortcut is defined
462 by the text. See the \l {QShortcut#mnemonic}{QShortcut}
463 documentation for details (to display an actual ampersand, use
464 '&&').
465
466*/
467void QTabWidget::setTabText(int index, const QString &label)
468{
469 Q_D(QTabWidget);
470 d->tabs->setTabText(index, label);
471 setUpLayout();
472}
473
474/*!
475 Returns the label text for the tab on the page at position \a index.
476*/
477
478QString QTabWidget::tabText(int index) const
479{
480 Q_D(const QTabWidget);
481 return d->tabs->tabText(index);
482}
483
484/*!
485 \overload
486
487 Sets the \a icon for the tab at position \a index.
488*/
489void QTabWidget::setTabIcon(int index, const QIcon &icon)
490{
491 Q_D(QTabWidget);
492 d->tabs->setTabIcon(index, icon);
493 setUpLayout();
494}
495
496/*!
497 Returns the icon for the tab on the page at position \a index.
498*/
499
500QIcon QTabWidget::tabIcon(int index) const
501{
502 Q_D(const QTabWidget);
503 return d->tabs->tabIcon(index);
504}
505
506/*!
507 Returns true if the the page at position \a index is enabled; otherwise returns false.
508
509 \sa setTabEnabled(), QWidget::isEnabled()
510*/
511
512bool QTabWidget::isTabEnabled(int index) const
513{
514 Q_D(const QTabWidget);
515 return d->tabs->isTabEnabled(index);
516}
517
518/*!
519 If \a enable is true, the page at position \a index is enabled; otherwise the page at position \a index is
520 disabled. The page's tab is redrawn appropriately.
521
522 QTabWidget uses QWidget::setEnabled() internally, rather than
523 keeping a separate flag.
524
525 Note that even a disabled tab/page may be visible. If the page is
526 visible already, QTabWidget will not hide it; if all the pages are
527 disabled, QTabWidget will show one of them.
528
529 \sa isTabEnabled(), QWidget::setEnabled()
530*/
531
532void QTabWidget::setTabEnabled(int index, bool enable)
533{
534 Q_D(QTabWidget);
535 d->tabs->setTabEnabled(index, enable);
536}
537
538/*!
539 \fn void QTabWidget::setCornerWidget(QWidget *widget, Qt::Corner corner)
540
541 Sets the given \a widget to be shown in the specified \a corner of the
542 tab widget. The geometry of the widget is determined based on the widget's
543 sizeHint() and the style().
544
545 Only the horizontal element of the \a corner will be used.
546
547 Passing 0 shows no widget in the corner.
548
549 Any previously set corner widget is hidden.
550
551 All widgets set here will be deleted by the tab widget when it is
552 destroyed unless you separately reparent the widget after setting
553 some other corner widget (or 0).
554
555 Note: Corner widgets are designed for \l North and \l South tab positions;
556 other orientations are known to not work properly.
557
558 \sa cornerWidget(), setTabPosition()
559*/
560void QTabWidget::setCornerWidget(QWidget * widget, Qt::Corner corner)
561{
562 Q_D(QTabWidget);
563 if (widget && widget->parentWidget() != this)
564 widget->setParent(this);
565
566 if (corner & Qt::TopRightCorner) {
567 if (d->rightCornerWidget)
568 d->rightCornerWidget->hide();
569 d->rightCornerWidget = widget;
570 } else {
571 if (d->leftCornerWidget)
572 d->leftCornerWidget->hide();
573 d->leftCornerWidget = widget;
574 }
575 setUpLayout();
576}
577
578/*!
579 Returns the widget shown in the \a corner of the tab widget or 0.
580*/
581QWidget * QTabWidget::cornerWidget(Qt::Corner corner) const
582{
583 Q_D(const QTabWidget);
584 if (corner & Qt::TopRightCorner)
585 return d->rightCornerWidget;
586 return d->leftCornerWidget;
587}
588
589/*!
590 Removes the tab at position \a index from this stack of widgets.
591 The page widget itself is not deleted.
592
593 \sa addTab(), insertTab()
594*/
595void QTabWidget::removeTab(int index)
596{
597 Q_D(QTabWidget);
598 if (QWidget *w = d->stack->widget(index))
599 d->stack->removeWidget(w);
600}
601
602/*!
603 Returns a pointer to the page currently being displayed by the tab
604 dialog. The tab dialog does its best to make sure that this value
605 is never 0 (but if you try hard enough, it can be).
606
607 \sa currentIndex(), setCurrentWidget()
608*/
609
610QWidget * QTabWidget::currentWidget() const
611{
612 Q_D(const QTabWidget);
613 return d->stack->currentWidget();
614}
615
616/*!
617 Makes \a widget the current widget. The \a widget used must be a page in
618 this tab widget.
619
620 \sa addTab(), setCurrentIndex(), currentWidget()
621 */
622void QTabWidget::setCurrentWidget(QWidget *widget)
623{
624 Q_D(const QTabWidget);
625 d->tabs->setCurrentIndex(indexOf(widget));
626}
627
628
629/*!
630 \property QTabWidget::currentIndex
631 \brief the index position of the current tab page
632
633 The current index is -1 if there is no current widget.
634
635 By default, this property contains a value of -1 because there are initially
636 no tabs in the widget.
637*/
638
639int QTabWidget::currentIndex() const
640{
641 Q_D(const QTabWidget);
642 return d->tabs->currentIndex();
643}
644
645void QTabWidget::setCurrentIndex(int index)
646{
647 Q_D(QTabWidget);
648 d->tabs->setCurrentIndex(index);
649}
650
651
652/*!
653 Returns the index position of the page occupied by the widget \a
654 w, or -1 if the widget cannot be found.
655*/
656int QTabWidget::indexOf(QWidget* w) const
657{
658 Q_D(const QTabWidget);
659 return d->stack->indexOf(w);
660}
661
662
663/*!
664 \reimp
665*/
666void QTabWidget::resizeEvent(QResizeEvent *e)
667{
668 QWidget::resizeEvent(e);
669 setUpLayout();
670}
671
672/*!
673 Replaces the dialog's QTabBar heading with the tab bar \a tb. Note
674 that this must be called \e before any tabs have been added, or
675 the behavior is undefined.
676
677 \sa tabBar()
678*/
679void QTabWidget::setTabBar(QTabBar* tb)
680{
681 Q_D(QTabWidget);
682 Q_ASSERT(tb);
683
684 if (tb->parentWidget() != this) {
685 tb->setParent(this);
686 tb->show();
687 }
688 delete d->tabs;
689 d->tabs = tb;
690 setFocusProxy(d->tabs);
691 connect(d->tabs, SIGNAL(currentChanged(int)),
692 this, SLOT(_q_showTab(int)));
693 connect(d->tabs, SIGNAL(tabMoved(int, int)),
694 this, SLOT(_q_tabMoved(int, int)));
695 if (d->tabs->tabsClosable())
696 connect(d->tabs, SIGNAL(tabCloseRequested(int)),
697 this, SIGNAL(tabCloseRequested(int)));
698 tb->setExpanding(!documentMode());
699 setUpLayout();
700}
701
702
703/*!
704 Returns the current QTabBar.
705
706 \sa setTabBar()
707*/
708QTabBar* QTabWidget::tabBar() const
709{
710 Q_D(const QTabWidget);
711 return d->tabs;
712}
713
714/*!
715 Ensures that the selected tab's page is visible and appropriately
716 sized.
717*/
718
719void QTabWidgetPrivate::_q_showTab(int index)
720{
721 Q_Q(QTabWidget);
722 if (index < stack->count() && index >= 0)
723 stack->setCurrentIndex(index);
724 emit q->currentChanged(index);
725#ifdef QT3_SUPPORT
726 emit q->selected(q->tabText(index));
727 emit q->currentChanged(stack->widget(index));
728#endif
729}
730
731void QTabWidgetPrivate::_q_removeTab(int index)
732{
733 Q_Q(QTabWidget);
734 tabs->removeTab(index);
735 q->setUpLayout();
736 q->tabRemoved(index);
737}
738
739void QTabWidgetPrivate::_q_tabMoved(int from, int to)
740{
741 stack->blockSignals(true);
742 QWidget *w = stack->widget(from);
743 stack->removeWidget(w);
744 stack->insertWidget(to, w);
745 stack->blockSignals(false);
746}
747
748/*
749 Set up the layout.
750 Get subrect from the current style, and set the geometry for the
751 stack widget, tab bar and corner widgets.
752*/
753void QTabWidget::setUpLayout(bool onlyCheck)
754{
755 Q_D(QTabWidget);
756 if (onlyCheck && !d->dirty)
757 return; // nothing to do
758
759 QStyleOptionTabWidgetFrame option;
760 initStyleOption(&option);
761
762 // this must be done immediately, because QWidgetItem relies on it (even if !isVisible())
763 d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &option);
764
765 if (!isVisible()) {
766 d->dirty = true;
767 return; // we'll do it later
768 }
769
770 QRect tabRect = style()->subElementRect(QStyle::SE_TabWidgetTabBar, &option, this);
771 d->panelRect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option, this);
772 QRect contentsRect = style()->subElementRect(QStyle::SE_TabWidgetTabContents, &option, this);
773 QRect leftCornerRect = style()->subElementRect(QStyle::SE_TabWidgetLeftCorner, &option, this);
774 QRect rightCornerRect = style()->subElementRect(QStyle::SE_TabWidgetRightCorner, &option, this);
775
776 d->tabs->setGeometry(tabRect);
777 d->stack->setGeometry(contentsRect);
778 if (d->leftCornerWidget)
779 d->leftCornerWidget->setGeometry(leftCornerRect);
780 if (d->rightCornerWidget)
781 d->rightCornerWidget->setGeometry(rightCornerRect);
782
783 if (!onlyCheck)
784 update();
785 updateGeometry();
786}
787
788/*!
789 \internal
790*/
791static inline QSize basicSize(
792 bool horizontal, const QSize &lc, const QSize &rc, const QSize &s, const QSize &t)
793{
794 return horizontal
795 ? QSize(qMax(s.width(), t.width() + rc.width() + lc.width()),
796 s.height() + (qMax(rc.height(), qMax(lc.height(), t.height()))))
797 : QSize(s.width() + (qMax(rc.width(), qMax(lc.width(), t.width()))),
798 qMax(s.height(), t.height() + rc.height() + lc.height()));
799}
800
801/*!
802 \reimp
803*/
804QSize QTabWidget::sizeHint() const
805{
806 Q_D(const QTabWidget);
807 QSize lc(0, 0), rc(0, 0);
808 QStyleOption opt(0);
809 opt.init(this);
810 opt.state = QStyle::State_None;
811
812 if (d->leftCornerWidget)
813 lc = d->leftCornerWidget->sizeHint();
814 if(d->rightCornerWidget)
815 rc = d->rightCornerWidget->sizeHint();
816 if (!d->dirty) {
817 QTabWidget *that = (QTabWidget*)this;
818 that->setUpLayout(true);
819 }
820 QSize s(d->stack->sizeHint());
821 QSize t(d->tabs->sizeHint());
822 if(usesScrollButtons())
823 t = t.boundedTo(QSize(200,200));
824 else
825 t = t.boundedTo(QApplication::desktop()->size());
826
827 QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
828
829 return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
830 .expandedTo(QApplication::globalStrut());
831}
832
833
834/*!
835 \reimp
836
837 Returns a suitable minimum size for the tab widget.
838*/
839QSize QTabWidget::minimumSizeHint() const
840{
841 Q_D(const QTabWidget);
842 QSize lc(0, 0), rc(0, 0);
843
844 if(d->leftCornerWidget)
845 lc = d->leftCornerWidget->minimumSizeHint();
846 if(d->rightCornerWidget)
847 rc = d->rightCornerWidget->minimumSizeHint();
848 if (!d->dirty) {
849 QTabWidget *that = (QTabWidget*)this;
850 that->setUpLayout(true);
851 }
852 QSize s(d->stack->minimumSizeHint());
853 QSize t(d->tabs->minimumSizeHint());
854
855 QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
856
857 QStyleOption opt(0);
858 opt.rect = rect();
859 opt.palette = palette();
860 opt.state = QStyle::State_None;
861 return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
862 .expandedTo(QApplication::globalStrut());
863}
864
865/*!
866 \reimp
867 */
868void QTabWidget::showEvent(QShowEvent *)
869{
870 setUpLayout();
871}
872
873void QTabWidgetPrivate::updateTabBarPosition()
874{
875 Q_Q(QTabWidget);
876 switch (pos) {
877 case QTabWidget::North:
878 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedNorth
879 : QTabBar::TriangularNorth);
880 break;
881 case QTabWidget::South:
882 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedSouth
883 : QTabBar::TriangularSouth);
884 break;
885 case QTabWidget::West:
886 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedWest
887 : QTabBar::TriangularWest);
888 break;
889 case QTabWidget::East:
890 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedEast
891 : QTabBar::TriangularEast);
892 break;
893 }
894 q->setUpLayout();
895}
896
897/*!
898 \property QTabWidget::tabPosition
899 \brief the position of the tabs in this tab widget
900
901 Possible values for this property are described by the TabPosition
902 enum.
903
904 By default, this property is set to \l North.
905
906 \sa TabPosition
907*/
908QTabWidget::TabPosition QTabWidget::tabPosition() const
909{
910 Q_D(const QTabWidget);
911 return d->pos;
912}
913
914void QTabWidget::setTabPosition(TabPosition pos)
915{
916 Q_D(QTabWidget);
917 if (d->pos == pos)
918 return;
919 d->pos = pos;
920 d->updateTabBarPosition();
921}
922
923/*!
924 \property QTabWidget::tabsClosable
925 \brief whether close buttons are automatically added to each tab.
926
927 \since 4.5
928
929 \sa QTabBar::tabsClosable()
930*/
931bool QTabWidget::tabsClosable() const
932{
933 return tabBar()->tabsClosable();
934}
935
936void QTabWidget::setTabsClosable(bool closeable)
937{
938 if (tabsClosable() == closeable)
939 return;
940
941 tabBar()->setTabsClosable(closeable);
942 if (closeable)
943 connect(tabBar(), SIGNAL(tabCloseRequested(int)),
944 this, SIGNAL(tabCloseRequested(int)));
945 else
946 disconnect(tabBar(), SIGNAL(tabCloseRequested(int)),
947 this, SIGNAL(tabCloseRequested(int)));
948 setUpLayout();
949}
950
951/*!
952 \property QTabWidget::movable
953 \brief This property holds whether the user can move the tabs
954 within the tabbar area.
955
956 \since 4.5
957
958 By default, this property is false;
959*/
960
961bool QTabWidget::isMovable() const
962{
963 return tabBar()->isMovable();
964}
965
966void QTabWidget::setMovable(bool movable)
967{
968 tabBar()->setMovable(movable);
969}
970
971/*!
972 \property QTabWidget::tabShape
973 \brief the shape of the tabs in this tab widget
974
975 Possible values for this property are QTabWidget::Rounded
976 (default) or QTabWidget::Triangular.
977
978 \sa TabShape
979*/
980
981QTabWidget::TabShape QTabWidget::tabShape() const
982{
983 Q_D(const QTabWidget);
984 return d->shape;
985}
986
987void QTabWidget::setTabShape(TabShape s)
988{
989 Q_D(QTabWidget);
990 if (d->shape == s)
991 return;
992 d->shape = s;
993 d->updateTabBarPosition();
994}
995
996/*!
997 \reimp
998 */
999bool QTabWidget::event(QEvent *ev)
1000{
1001 if (ev->type() == QEvent::LayoutRequest)
1002 setUpLayout();
1003 return QWidget::event(ev);
1004}
1005
1006/*!
1007 \reimp
1008 */
1009void QTabWidget::changeEvent(QEvent *ev)
1010{
1011 if (ev->type() == QEvent::StyleChange
1012#ifdef Q_WS_MAC
1013 || ev->type() == QEvent::MacSizeChange
1014#endif
1015 )
1016 setUpLayout();
1017 QWidget::changeEvent(ev);
1018}
1019
1020
1021/*!
1022 \reimp
1023 */
1024void QTabWidget::keyPressEvent(QKeyEvent *e)
1025{
1026 Q_D(QTabWidget);
1027 if (((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) &&
1028 count() > 1 && e->modifiers() & Qt::ControlModifier)
1029#ifdef QT_KEYPAD_NAVIGATION
1030 || QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right) && count() > 1
1031#endif
1032 ) {
1033 int pageCount = d->tabs->count();
1034 int page = currentIndex();
1035 int dx = (e->key() == Qt::Key_Backtab || e->modifiers() & Qt::ShiftModifier) ? -1 : 1;
1036#ifdef QT_KEYPAD_NAVIGATION
1037 if (QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))
1038 dx = e->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;
1039#endif
1040 for (int pass = 0; pass < pageCount; ++pass) {
1041 page+=dx;
1042 if (page < 0
1043#ifdef QT_KEYPAD_NAVIGATION
1044 && !e->isAutoRepeat()
1045#endif
1046 ) {
1047 page = count() - 1;
1048 } else if (page >= pageCount
1049#ifdef QT_KEYPAD_NAVIGATION
1050 && !e->isAutoRepeat()
1051#endif
1052 ) {
1053 page = 0;
1054 }
1055 if (d->tabs->isTabEnabled(page)) {
1056 setCurrentIndex(page);
1057 break;
1058 }
1059 }
1060 if (!qApp->focusWidget())
1061 d->tabs->setFocus();
1062 } else {
1063 e->ignore();
1064 }
1065}
1066
1067/*!
1068 Returns the tab page at index position \a index or 0 if the \a
1069 index is out of range.
1070*/
1071QWidget *QTabWidget::widget(int index) const
1072{
1073 Q_D(const QTabWidget);
1074 return d->stack->widget(index);
1075}
1076
1077/*!
1078 \property QTabWidget::count
1079 \brief the number of tabs in the tab bar
1080
1081 By default, this property contains a value of 0.
1082*/
1083int QTabWidget::count() const
1084{
1085 Q_D(const QTabWidget);
1086 return d->tabs->count();
1087}
1088
1089#ifndef QT_NO_TOOLTIP
1090/*!
1091 Sets the tab tool tip for the page at position \a index to \a tip.
1092
1093 \sa tabToolTip()
1094*/
1095void QTabWidget::setTabToolTip(int index, const QString & tip)
1096{
1097 Q_D(QTabWidget);
1098 d->tabs->setTabToolTip(index, tip);
1099}
1100
1101/*!
1102 Returns the tab tool tip for the page at position \a index or
1103 an empty string if no tool tip has been set.
1104
1105 \sa setTabToolTip()
1106*/
1107QString QTabWidget::tabToolTip(int index) const
1108{
1109 Q_D(const QTabWidget);
1110 return d->tabs->tabToolTip(index);
1111}
1112#endif // QT_NO_TOOLTIP
1113
1114#ifndef QT_NO_WHATSTHIS
1115/*!
1116 \since 4.1
1117
1118 Sets the What's This help text for the page at position \a index
1119 to \a text.
1120*/
1121void QTabWidget::setTabWhatsThis(int index, const QString &text)
1122{
1123 Q_D(QTabWidget);
1124 d->tabs->setTabWhatsThis(index, text);
1125}
1126
1127/*!
1128 \since 4.1
1129
1130 Returns the What's This help text for the page at position \a index,
1131 or an empty string if no help text has been set.
1132*/
1133QString QTabWidget::tabWhatsThis(int index) const
1134{
1135 Q_D(const QTabWidget);
1136 return d->tabs->tabWhatsThis(index);
1137}
1138#endif // QT_NO_WHATSTHIS
1139
1140/*!
1141 This virtual handler is called after a new tab was added or
1142 inserted at position \a index.
1143
1144 \sa tabRemoved()
1145 */
1146void QTabWidget::tabInserted(int index)
1147{
1148 Q_UNUSED(index)
1149}
1150
1151/*!
1152 This virtual handler is called after a tab was removed from
1153 position \a index.
1154
1155 \sa tabInserted()
1156 */
1157void QTabWidget::tabRemoved(int index)
1158{
1159 Q_UNUSED(index)
1160}
1161
1162/*!
1163 \fn void QTabWidget::paintEvent(QPaintEvent *event)
1164
1165 Paints the tab widget's tab bar in response to the paint \a event.
1166*/
1167void QTabWidget::paintEvent(QPaintEvent *)
1168{
1169 Q_D(QTabWidget);
1170 QStylePainter p(this);
1171 if (documentMode()) {
1172 if (QWidget *w = cornerWidget(Qt::TopLeftCorner)) {
1173 QStyleOptionTabBarBaseV2 opt;
1174 QTabBarPrivate::initStyleBaseOption(&opt, tabBar(), w->size());
1175 opt.rect.moveLeft(w->x() + opt.rect.x());
1176 opt.rect.moveTop(w->y() + opt.rect.y());
1177 p.drawPrimitive(QStyle::PE_FrameTabBarBase, opt);
1178 }
1179 if (QWidget *w = cornerWidget(Qt::TopRightCorner)) {
1180 QStyleOptionTabBarBaseV2 opt;
1181 QTabBarPrivate::initStyleBaseOption(&opt, tabBar(), w->size());
1182 opt.rect.moveLeft(w->x() + opt.rect.x());
1183 opt.rect.moveTop(w->y() + opt.rect.y());
1184 p.drawPrimitive(QStyle::PE_FrameTabBarBase, opt);
1185 }
1186 return;
1187 }
1188
1189 QStyleOptionTabWidgetFrame opt;
1190 initStyleOption(&opt);
1191 opt.rect = d->panelRect;
1192 p.drawPrimitive(QStyle::PE_FrameTabWidget, opt);
1193}
1194
1195/*!
1196 \property QTabWidget::iconSize
1197 \brief The size for icons in the tab bar
1198 \since 4.2
1199
1200 The default value is style-dependent. This is the maximum size
1201 that the icons will have. Icons are not scaled up if they are of
1202 smaller size.
1203
1204 \sa QTabBar::iconSize
1205*/
1206QSize QTabWidget::iconSize() const
1207{
1208 return d_func()->tabs->iconSize();
1209}
1210
1211void QTabWidget::setIconSize(const QSize &size)
1212{
1213 d_func()->tabs->setIconSize(size);
1214}
1215
1216/*!
1217 \property QTabWidget::elideMode
1218 \brief how to elide text in the tab bar
1219 \since 4.2
1220
1221 This property controls how items are elided when there is not
1222 enough space to show them for a given tab bar size.
1223
1224 By default the value is style dependant.
1225
1226 \sa QTabBar::elideMode usesScrollButtons QStyle::SH_TabBar_ElideMode
1227*/
1228Qt::TextElideMode QTabWidget::elideMode() const
1229{
1230 return d_func()->tabs->elideMode();
1231}
1232
1233void QTabWidget::setElideMode(Qt::TextElideMode mode)
1234{
1235 d_func()->tabs->setElideMode(mode);
1236}
1237
1238/*!
1239 \property QTabWidget::usesScrollButtons
1240 \brief Whether or not a tab bar should use buttons to scroll tabs when it
1241 has many tabs.
1242 \since 4.2
1243
1244 When there are too many tabs in a tab bar for its size, the tab bar can either choose
1245 to expand its size or to add buttons that allow you to scroll through the tabs.
1246
1247 By default the value is style dependant.
1248
1249 \sa elideMode QTabBar::usesScrollButtons QStyle::SH_TabBar_PreferNoArrows
1250*/
1251bool QTabWidget::usesScrollButtons() const
1252{
1253 return d_func()->tabs->usesScrollButtons();
1254}
1255
1256void QTabWidget::setUsesScrollButtons(bool useButtons)
1257{
1258 d_func()->tabs->setUsesScrollButtons(useButtons);
1259}
1260
1261/*!
1262 \property QTabWidget::documentMode
1263 \brief Whether or not the tab widget is rendered in a mode suitable for document
1264 pages. This is the same as document mode on Mac OS X.
1265 \since 4.5
1266
1267 When this property is set the tab widget frame is not rendered. This mode is useful
1268 for showing document-type pages where the page covers most of the tab widget
1269 area.
1270
1271 \sa elideMode, QTabBar::documentMode, QTabBar::usesScrollButtons, QStyle::SH_TabBar_PreferNoArrows
1272*/
1273bool QTabWidget::documentMode() const
1274{
1275 Q_D(const QTabWidget);
1276 return d->tabs->documentMode();
1277}
1278
1279void QTabWidget::setDocumentMode(bool enabled)
1280{
1281 Q_D(QTabWidget);
1282 d->tabs->setDocumentMode(enabled);
1283 d->tabs->setExpanding(!enabled);
1284 d->tabs->setDrawBase(enabled);
1285 setUpLayout();
1286}
1287
1288/*!
1289 Removes all the pages, but does not delete them. Calling this function
1290 is equivalent to calling removeTab() until the tab widget is empty.
1291*/
1292void QTabWidget::clear()
1293{
1294 // ### optimize by introduce QStackedLayout::clear()
1295 while (count())
1296 removeTab(0);
1297}
1298
1299/*!
1300 \fn void QTabWidget::insertTab(QWidget *widget, const QString &label, int index)
1301
1302 Use insertTab(index, widget, label) instead.
1303*/
1304
1305/*!
1306 \fn void QTabWidget::insertTab(QWidget *widget, const QIcon& icon, const QString &label, int index)
1307
1308 Use insertTab(index, widget, icon, label) instead.
1309*/
1310
1311/*!
1312 \fn void QTabWidget::changeTab(QWidget *widget, const QString
1313 &label)
1314
1315 Use setTabText() instead.
1316
1317*/
1318
1319/*!
1320 \fn void QTabWidget::changeTab(QWidget *widget, const QIcon& icon, const QString &label)
1321
1322 Use setTabText() and setTabIcon() instead.
1323*/
1324
1325/*!
1326 \fn bool QTabWidget::isTabEnabled( QWidget *widget) const
1327
1328 Use isTabEnabled(tabWidget->indexOf(widget)) instead.
1329*/
1330
1331/*!
1332 \fn void QTabWidget::setTabEnabled(QWidget *widget, bool b)
1333
1334 Use setTabEnabled(tabWidget->indexOf(widget), b) instead.
1335*/
1336
1337/*!
1338 \fn QString QTabWidget::tabLabel(QWidget *widget) const
1339
1340 Use tabText(tabWidget->indexOf(widget)) instead.
1341*/
1342
1343/*!
1344 \fn void QTabWidget::setTabLabel(QWidget *widget, const QString
1345 &label)
1346
1347 Use setTabText(tabWidget->indexOf(widget), label) instead.
1348*/
1349
1350/*!
1351 \fn QIcon QTabWidget::tabIconSet(QWidget * widget) const
1352
1353 Use tabIcon(tabWidget->indexOf(widget)) instead.
1354*/
1355
1356/*!
1357 \fn void QTabWidget::setTabIconSet(QWidget * widget, const QIcon & icon)
1358
1359 Use setTabIcon(tabWidget->indexOf(widget), icon) instead.
1360*/
1361
1362/*!
1363 \fn void QTabWidget::removeTabToolTip(QWidget * widget)
1364
1365 Use setTabToolTip(tabWidget->indexOf(widget), QString()) instead.
1366*/
1367
1368/*!
1369 \fn void QTabWidget::setTabToolTip(QWidget * widget, const QString & tip)
1370
1371 Use setTabToolTip(tabWidget->indexOf(widget), tip) instead.
1372*/
1373
1374/*!
1375 \fn QString QTabWidget::tabToolTip(QWidget * widget) const
1376
1377 Use tabToolTip(tabWidget->indexOf(widget)) instead.
1378*/
1379
1380/*!
1381 \fn QWidget * QTabWidget::currentPage() const
1382
1383 Use currentWidget() instead.
1384*/
1385
1386/*!
1387 \fn QWidget *QTabWidget::page(int index) const
1388
1389 Use widget() instead.
1390*/
1391
1392/*!
1393 \fn QString QTabWidget::label(int index) const
1394
1395 Use tabText() instead.
1396*/
1397
1398/*!
1399 \fn int QTabWidget::currentPageIndex() const
1400
1401 Use currentIndex() instead.
1402*/
1403
1404/*!
1405 \fn int QTabWidget::margin() const
1406
1407 This function is kept only to make old code compile.
1408 This functionality is no longer supported by QTabWidget.
1409
1410 \sa contentsRect(), setContentsMargins()
1411*/
1412
1413/*!
1414 \fn void QTabWidget::setMargin(int margin)
1415
1416 This function is kept only to make old code compile.
1417 This functionality is no longer supported by QTabWidget.
1418
1419 \sa contentsRect(), setContentsMargins()
1420*/
1421
1422/*!
1423 \fn void QTabWidget::setCurrentPage(int index)
1424
1425 Use setCurrentIndex() instead.
1426*/
1427
1428/*!
1429 \fn void QTabWidget::showPage(QWidget *widget)
1430
1431 Use setCurrentIndex(indexOf(widget)) instead.
1432*/
1433
1434/*!
1435 \fn void QTabWidget::removePage(QWidget *widget)
1436
1437 Use removeTab(indexOf(widget)) instead.
1438*/
1439
1440/*!
1441 \fn void QTabWidget::currentChanged(QWidget *widget)
1442
1443 Use currentChanged(int) instead.
1444*/
1445
1446QT_END_NAMESPACE
1447
1448#include "moc_qtabwidget.cpp"
1449
1450#endif //QT_NO_TABWIDGET
Note: See TracBrowser for help on using the repository browser.