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

Last change on this file since 769 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 39.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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
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
317 option->tabBarSize = t;
318
319 if (QStyleOptionTabWidgetFrameV2 *tabframe = qstyleoption_cast<QStyleOptionTabWidgetFrameV2*>(option)) {
320 QRect tbRect = tabBar()->geometry();
321 QRect selectedTabRect = tabBar()->tabRect(tabBar()->currentIndex());
322 tabframe->tabBarRect = tbRect;
323 selectedTabRect.moveTopLeft(selectedTabRect.topLeft() + tbRect.topLeft());
324 tabframe->selectedTabRect = selectedTabRect;
325 }
326}
327
328/*!
329 Constructs a tabbed widget with parent \a parent.
330*/
331QTabWidget::QTabWidget(QWidget *parent)
332 : QWidget(*new QTabWidgetPrivate, parent, 0)
333{
334 Q_D(QTabWidget);
335 d->init();
336}
337
338#ifdef QT3_SUPPORT
339/*!
340 Use one of the constructors that doesn't take the \a name
341 argument and then use setObjectName() instead.
342*/
343QTabWidget::QTabWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
344 : QWidget(*new QTabWidgetPrivate, parent, f)
345{
346 Q_D(QTabWidget);
347 setObjectName(QString::fromAscii(name));
348 d->init();
349}
350#endif
351
352/*!
353 Destroys the tabbed widget.
354*/
355QTabWidget::~QTabWidget()
356{
357}
358
359/*!
360 \fn int QTabWidget::addTab(QWidget *page, const QString &label)
361
362 Adds a tab with the given \a page and \a label to the tab widget,
363 and returns the index of the tab in the tab bar.
364
365 If the tab's \a label contains an ampersand, the letter following
366 the ampersand is used as a shortcut for the tab, e.g. if the
367 label is "Bro\&wse" then Alt+W becomes a shortcut which will
368 move the focus to this tab.
369
370 \note If you call addTab() after show(), the layout system will try
371 to adjust to the changes in its widgets hierarchy and may cause
372 flicker. To prevent this, you can set the QWidget::updatesEnabled
373 property to false prior to changes; remember to set the property
374 to true when the changes are done, making the widget receive paint
375 events again.
376
377 \sa insertTab()
378*/
379int QTabWidget::addTab(QWidget *child, const QString &label)
380{
381 return insertTab(-1, child, label);
382}
383
384
385/*!
386 \fn int QTabWidget::addTab(QWidget *page, const QIcon &icon, const QString &label)
387 \overload
388
389 Adds a tab with the given \a page, \a icon, and \a label to the tab
390 widget, and returns the index of the tab in the tab bar.
391
392 This function is the same as addTab(), but with an additional \a
393 icon.
394*/
395int QTabWidget::addTab(QWidget *child, const QIcon& icon, const QString &label)
396{
397 return insertTab(-1, child, icon, label);
398}
399
400
401/*!
402 \fn int QTabWidget::insertTab(int index, QWidget *page, const QString &label)
403
404 Inserts a tab with the given \a label and \a page into the tab
405 widget at the specified \a index, and returns the index of the
406 inserted tab in the tab bar.
407
408 The label is displayed in the tab and may vary in appearance depending
409 on the configuration of the tab widget.
410
411 If the tab's \a label contains an ampersand, the letter following
412 the ampersand is used as a shortcut for the tab, e.g. if the
413 label is "Bro\&wse" then Alt+W becomes a shortcut which will
414 move the focus to this tab.
415
416 If \a index is out of range, the tab is simply appended.
417 Otherwise it is inserted at the specified position.
418
419 If the QTabWidget was empty before this function is called, the
420 new page becomes the current page. Inserting a new tab at an index
421 less than or equal to the current index will increment the current
422 index, but keep the current page.
423
424 \note If you call insertTab() after show(), the layout system will try
425 to adjust to the changes in its widgets hierarchy and may cause
426 flicker. To prevent this, you can set the QWidget::updatesEnabled
427 property to false prior to changes; remember to set the property
428 to true when the changes are done, making the widget receive paint
429 events again.
430
431 \sa addTab()
432*/
433int QTabWidget::insertTab(int index, QWidget *w, const QString &label)
434{
435 return insertTab(index, w, QIcon(), label);
436}
437
438
439/*!
440 \fn int QTabWidget::insertTab(int index, QWidget *page, const QIcon& icon, const QString &label)
441 \overload
442
443 Inserts a tab with the given \a label, \a page, and \a icon into
444 the tab widget at the specified \a index, and returns the index of the
445 inserted tab in the tab bar.
446
447 This function is the same as insertTab(), but with an additional
448 \a icon.
449*/
450int QTabWidget::insertTab(int index, QWidget *w, const QIcon& icon, const QString &label)
451{
452 Q_D(QTabWidget);
453 if(!w)
454 return -1;
455 index = d->stack->insertWidget(index, w);
456 d->tabs->insertTab(index, icon, label);
457 setUpLayout();
458 tabInserted(index);
459
460 return index;
461}
462
463
464/*!
465 Defines a new \a label for the page at position \a index's tab.
466
467 If the provided text contains an ampersand character ('&'), a
468 shortcut is automatically created for it. The character that
469 follows the '&' will be used as the shortcut key. Any previous
470 shortcut will be overwritten, or cleared if no shortcut is defined
471 by the text. See the \l {QShortcut#mnemonic}{QShortcut}
472 documentation for details (to display an actual ampersand, use
473 '&&').
474
475*/
476void QTabWidget::setTabText(int index, const QString &label)
477{
478 Q_D(QTabWidget);
479 d->tabs->setTabText(index, label);
480 setUpLayout();
481}
482
483/*!
484 Returns the label text for the tab on the page at position \a index.
485*/
486
487QString QTabWidget::tabText(int index) const
488{
489 Q_D(const QTabWidget);
490 return d->tabs->tabText(index);
491}
492
493/*!
494 \overload
495
496 Sets the \a icon for the tab at position \a index.
497*/
498void QTabWidget::setTabIcon(int index, const QIcon &icon)
499{
500 Q_D(QTabWidget);
501 d->tabs->setTabIcon(index, icon);
502 setUpLayout();
503}
504
505/*!
506 Returns the icon for the tab on the page at position \a index.
507*/
508
509QIcon QTabWidget::tabIcon(int index) const
510{
511 Q_D(const QTabWidget);
512 return d->tabs->tabIcon(index);
513}
514
515/*!
516 Returns true if the page at position \a index is enabled; otherwise returns false.
517
518 \sa setTabEnabled(), QWidget::isEnabled()
519*/
520
521bool QTabWidget::isTabEnabled(int index) const
522{
523 Q_D(const QTabWidget);
524 return d->tabs->isTabEnabled(index);
525}
526
527/*!
528 If \a enable is true, the page at position \a index is enabled; otherwise the page at position \a index is
529 disabled. The page's tab is redrawn appropriately.
530
531 QTabWidget uses QWidget::setEnabled() internally, rather than
532 keeping a separate flag.
533
534 Note that even a disabled tab/page may be visible. If the page is
535 visible already, QTabWidget will not hide it; if all the pages are
536 disabled, QTabWidget will show one of them.
537
538 \sa isTabEnabled(), QWidget::setEnabled()
539*/
540
541void QTabWidget::setTabEnabled(int index, bool enable)
542{
543 Q_D(QTabWidget);
544 d->tabs->setTabEnabled(index, enable);
545}
546
547/*!
548 \fn void QTabWidget::setCornerWidget(QWidget *widget, Qt::Corner corner)
549
550 Sets the given \a widget to be shown in the specified \a corner of the
551 tab widget. The geometry of the widget is determined based on the widget's
552 sizeHint() and the style().
553
554 Only the horizontal element of the \a corner will be used.
555
556 Passing 0 shows no widget in the corner.
557
558 Any previously set corner widget is hidden.
559
560 All widgets set here will be deleted by the tab widget when it is
561 destroyed unless you separately reparent the widget after setting
562 some other corner widget (or 0).
563
564 Note: Corner widgets are designed for \l North and \l South tab positions;
565 other orientations are known to not work properly.
566
567 \sa cornerWidget(), setTabPosition()
568*/
569void QTabWidget::setCornerWidget(QWidget * widget, Qt::Corner corner)
570{
571 Q_D(QTabWidget);
572 if (widget && widget->parentWidget() != this)
573 widget->setParent(this);
574
575 if (corner & Qt::TopRightCorner) {
576 if (d->rightCornerWidget)
577 d->rightCornerWidget->hide();
578 d->rightCornerWidget = widget;
579 } else {
580 if (d->leftCornerWidget)
581 d->leftCornerWidget->hide();
582 d->leftCornerWidget = widget;
583 }
584 setUpLayout();
585}
586
587/*!
588 Returns the widget shown in the \a corner of the tab widget or 0.
589*/
590QWidget * QTabWidget::cornerWidget(Qt::Corner corner) const
591{
592 Q_D(const QTabWidget);
593 if (corner & Qt::TopRightCorner)
594 return d->rightCornerWidget;
595 return d->leftCornerWidget;
596}
597
598/*!
599 Removes the tab at position \a index from this stack of widgets.
600 The page widget itself is not deleted.
601
602 \sa addTab(), insertTab()
603*/
604void QTabWidget::removeTab(int index)
605{
606 Q_D(QTabWidget);
607 if (QWidget *w = d->stack->widget(index))
608 d->stack->removeWidget(w);
609}
610
611/*!
612 Returns a pointer to the page currently being displayed by the tab
613 dialog. The tab dialog does its best to make sure that this value
614 is never 0 (but if you try hard enough, it can be).
615
616 \sa currentIndex(), setCurrentWidget()
617*/
618
619QWidget * QTabWidget::currentWidget() const
620{
621 Q_D(const QTabWidget);
622 return d->stack->currentWidget();
623}
624
625/*!
626 Makes \a widget the current widget. The \a widget used must be a page in
627 this tab widget.
628
629 \sa addTab(), setCurrentIndex(), currentWidget()
630 */
631void QTabWidget::setCurrentWidget(QWidget *widget)
632{
633 Q_D(const QTabWidget);
634 d->tabs->setCurrentIndex(indexOf(widget));
635}
636
637
638/*!
639 \property QTabWidget::currentIndex
640 \brief the index position of the current tab page
641
642 The current index is -1 if there is no current widget.
643
644 By default, this property contains a value of -1 because there are initially
645 no tabs in the widget.
646*/
647
648int QTabWidget::currentIndex() const
649{
650 Q_D(const QTabWidget);
651 return d->tabs->currentIndex();
652}
653
654void QTabWidget::setCurrentIndex(int index)
655{
656 Q_D(QTabWidget);
657 d->tabs->setCurrentIndex(index);
658}
659
660
661/*!
662 Returns the index position of the page occupied by the widget \a
663 w, or -1 if the widget cannot be found.
664*/
665int QTabWidget::indexOf(QWidget* w) const
666{
667 Q_D(const QTabWidget);
668 return d->stack->indexOf(w);
669}
670
671
672/*!
673 \reimp
674*/
675void QTabWidget::resizeEvent(QResizeEvent *e)
676{
677 QWidget::resizeEvent(e);
678 setUpLayout();
679}
680
681/*!
682 Replaces the dialog's QTabBar heading with the tab bar \a tb. Note
683 that this must be called \e before any tabs have been added, or
684 the behavior is undefined.
685
686 \sa tabBar()
687*/
688void QTabWidget::setTabBar(QTabBar* tb)
689{
690 Q_D(QTabWidget);
691 Q_ASSERT(tb);
692
693 if (tb->parentWidget() != this) {
694 tb->setParent(this);
695 tb->show();
696 }
697 delete d->tabs;
698 d->tabs = tb;
699 setFocusProxy(d->tabs);
700 connect(d->tabs, SIGNAL(currentChanged(int)),
701 this, SLOT(_q_showTab(int)));
702 connect(d->tabs, SIGNAL(tabMoved(int,int)),
703 this, SLOT(_q_tabMoved(int,int)));
704 if (d->tabs->tabsClosable())
705 connect(d->tabs, SIGNAL(tabCloseRequested(int)),
706 this, SIGNAL(tabCloseRequested(int)));
707 tb->setExpanding(!documentMode());
708 setUpLayout();
709}
710
711
712/*!
713 Returns the current QTabBar.
714
715 \sa setTabBar()
716*/
717QTabBar* QTabWidget::tabBar() const
718{
719 Q_D(const QTabWidget);
720 return d->tabs;
721}
722
723/*!
724 Ensures that the selected tab's page is visible and appropriately
725 sized.
726*/
727
728void QTabWidgetPrivate::_q_showTab(int index)
729{
730 Q_Q(QTabWidget);
731 if (index < stack->count() && index >= 0)
732 stack->setCurrentIndex(index);
733 emit q->currentChanged(index);
734#ifdef QT3_SUPPORT
735 emit q->selected(q->tabText(index));
736 emit q->currentChanged(stack->widget(index));
737#endif
738}
739
740void QTabWidgetPrivate::_q_removeTab(int index)
741{
742 Q_Q(QTabWidget);
743 tabs->removeTab(index);
744 q->setUpLayout();
745 q->tabRemoved(index);
746}
747
748void QTabWidgetPrivate::_q_tabMoved(int from, int to)
749{
750 stack->blockSignals(true);
751 QWidget *w = stack->widget(from);
752 stack->removeWidget(w);
753 stack->insertWidget(to, w);
754 stack->blockSignals(false);
755}
756
757/*
758 Set up the layout.
759 Get subrect from the current style, and set the geometry for the
760 stack widget, tab bar and corner widgets.
761*/
762void QTabWidget::setUpLayout(bool onlyCheck)
763{
764 Q_D(QTabWidget);
765 if (onlyCheck && !d->dirty)
766 return; // nothing to do
767
768 QStyleOptionTabWidgetFrameV2 option;
769 initStyleOption(&option);
770
771 // this must be done immediately, because QWidgetItem relies on it (even if !isVisible())
772 d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &option);
773
774 if (!isVisible()) {
775 d->dirty = true;
776 return; // we'll do it later
777 }
778
779 QRect tabRect = style()->subElementRect(QStyle::SE_TabWidgetTabBar, &option, this);
780 d->panelRect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option, this);
781 QRect contentsRect = style()->subElementRect(QStyle::SE_TabWidgetTabContents, &option, this);
782 QRect leftCornerRect = style()->subElementRect(QStyle::SE_TabWidgetLeftCorner, &option, this);
783 QRect rightCornerRect = style()->subElementRect(QStyle::SE_TabWidgetRightCorner, &option, this);
784
785 d->tabs->setGeometry(tabRect);
786 d->stack->setGeometry(contentsRect);
787 if (d->leftCornerWidget)
788 d->leftCornerWidget->setGeometry(leftCornerRect);
789 if (d->rightCornerWidget)
790 d->rightCornerWidget->setGeometry(rightCornerRect);
791
792 if (!onlyCheck)
793 update();
794 updateGeometry();
795}
796
797/*!
798 \internal
799*/
800static inline QSize basicSize(
801 bool horizontal, const QSize &lc, const QSize &rc, const QSize &s, const QSize &t)
802{
803 return horizontal
804 ? QSize(qMax(s.width(), t.width() + rc.width() + lc.width()),
805 s.height() + (qMax(rc.height(), qMax(lc.height(), t.height()))))
806 : QSize(s.width() + (qMax(rc.width(), qMax(lc.width(), t.width()))),
807 qMax(s.height(), t.height() + rc.height() + lc.height()));
808}
809
810/*!
811 \reimp
812*/
813QSize QTabWidget::sizeHint() const
814{
815 Q_D(const QTabWidget);
816 QSize lc(0, 0), rc(0, 0);
817 QStyleOption opt(0);
818 opt.init(this);
819 opt.state = QStyle::State_None;
820
821 if (d->leftCornerWidget)
822 lc = d->leftCornerWidget->sizeHint();
823 if(d->rightCornerWidget)
824 rc = d->rightCornerWidget->sizeHint();
825 if (!d->dirty) {
826 QTabWidget *that = (QTabWidget*)this;
827 that->setUpLayout(true);
828 }
829 QSize s(d->stack->sizeHint());
830 QSize t(d->tabs->sizeHint());
831 if(usesScrollButtons())
832 t = t.boundedTo(QSize(200,200));
833 else
834 t = t.boundedTo(QApplication::desktop()->size());
835
836 QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
837
838 return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
839 .expandedTo(QApplication::globalStrut());
840}
841
842
843/*!
844 \reimp
845
846 Returns a suitable minimum size for the tab widget.
847*/
848QSize QTabWidget::minimumSizeHint() const
849{
850 Q_D(const QTabWidget);
851 QSize lc(0, 0), rc(0, 0);
852
853 if(d->leftCornerWidget)
854 lc = d->leftCornerWidget->minimumSizeHint();
855 if(d->rightCornerWidget)
856 rc = d->rightCornerWidget->minimumSizeHint();
857 if (!d->dirty) {
858 QTabWidget *that = (QTabWidget*)this;
859 that->setUpLayout(true);
860 }
861 QSize s(d->stack->minimumSizeHint());
862 QSize t(d->tabs->minimumSizeHint());
863
864 QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
865
866 QStyleOption opt(0);
867 opt.rect = rect();
868 opt.palette = palette();
869 opt.state = QStyle::State_None;
870 return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
871 .expandedTo(QApplication::globalStrut());
872}
873
874/*!
875 \reimp
876 */
877void QTabWidget::showEvent(QShowEvent *)
878{
879 setUpLayout();
880}
881
882void QTabWidgetPrivate::updateTabBarPosition()
883{
884 Q_Q(QTabWidget);
885 switch (pos) {
886 case QTabWidget::North:
887 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedNorth
888 : QTabBar::TriangularNorth);
889 break;
890 case QTabWidget::South:
891 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedSouth
892 : QTabBar::TriangularSouth);
893 break;
894 case QTabWidget::West:
895 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedWest
896 : QTabBar::TriangularWest);
897 break;
898 case QTabWidget::East:
899 tabs->setShape(shape == QTabWidget::Rounded ? QTabBar::RoundedEast
900 : QTabBar::TriangularEast);
901 break;
902 }
903 q->setUpLayout();
904}
905
906/*!
907 \property QTabWidget::tabPosition
908 \brief the position of the tabs in this tab widget
909
910 Possible values for this property are described by the TabPosition
911 enum.
912
913 By default, this property is set to \l North.
914
915 \sa TabPosition
916*/
917QTabWidget::TabPosition QTabWidget::tabPosition() const
918{
919 Q_D(const QTabWidget);
920 return d->pos;
921}
922
923void QTabWidget::setTabPosition(TabPosition pos)
924{
925 Q_D(QTabWidget);
926 if (d->pos == pos)
927 return;
928 d->pos = pos;
929 d->updateTabBarPosition();
930}
931
932/*!
933 \property QTabWidget::tabsClosable
934 \brief whether close buttons are automatically added to each tab.
935
936 \since 4.5
937
938 \sa QTabBar::tabsClosable()
939*/
940bool QTabWidget::tabsClosable() const
941{
942 return tabBar()->tabsClosable();
943}
944
945void QTabWidget::setTabsClosable(bool closeable)
946{
947 if (tabsClosable() == closeable)
948 return;
949
950 tabBar()->setTabsClosable(closeable);
951 if (closeable)
952 connect(tabBar(), SIGNAL(tabCloseRequested(int)),
953 this, SIGNAL(tabCloseRequested(int)));
954 else
955 disconnect(tabBar(), SIGNAL(tabCloseRequested(int)),
956 this, SIGNAL(tabCloseRequested(int)));
957 setUpLayout();
958}
959
960/*!
961 \property QTabWidget::movable
962 \brief This property holds whether the user can move the tabs
963 within the tabbar area.
964
965 \since 4.5
966
967 By default, this property is false;
968*/
969
970bool QTabWidget::isMovable() const
971{
972 return tabBar()->isMovable();
973}
974
975void QTabWidget::setMovable(bool movable)
976{
977 tabBar()->setMovable(movable);
978}
979
980/*!
981 \property QTabWidget::tabShape
982 \brief the shape of the tabs in this tab widget
983
984 Possible values for this property are QTabWidget::Rounded
985 (default) or QTabWidget::Triangular.
986
987 \sa TabShape
988*/
989
990QTabWidget::TabShape QTabWidget::tabShape() const
991{
992 Q_D(const QTabWidget);
993 return d->shape;
994}
995
996void QTabWidget::setTabShape(TabShape s)
997{
998 Q_D(QTabWidget);
999 if (d->shape == s)
1000 return;
1001 d->shape = s;
1002 d->updateTabBarPosition();
1003}
1004
1005/*!
1006 \reimp
1007 */
1008bool QTabWidget::event(QEvent *ev)
1009{
1010 if (ev->type() == QEvent::LayoutRequest)
1011 setUpLayout();
1012 return QWidget::event(ev);
1013}
1014
1015/*!
1016 \reimp
1017 */
1018void QTabWidget::changeEvent(QEvent *ev)
1019{
1020 if (ev->type() == QEvent::StyleChange
1021#ifdef Q_WS_MAC
1022 || ev->type() == QEvent::MacSizeChange
1023#endif
1024 )
1025 setUpLayout();
1026 QWidget::changeEvent(ev);
1027}
1028
1029
1030/*!
1031 \reimp
1032 */
1033void QTabWidget::keyPressEvent(QKeyEvent *e)
1034{
1035 Q_D(QTabWidget);
1036 if (((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) &&
1037 count() > 1 && e->modifiers() & Qt::ControlModifier)
1038#ifdef QT_KEYPAD_NAVIGATION
1039 || QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right) && count() > 1
1040#endif
1041 ) {
1042 int pageCount = d->tabs->count();
1043 int page = currentIndex();
1044 int dx = (e->key() == Qt::Key_Backtab || e->modifiers() & Qt::ShiftModifier) ? -1 : 1;
1045#ifdef QT_KEYPAD_NAVIGATION
1046 if (QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))
1047 dx = e->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;
1048#endif
1049 for (int pass = 0; pass < pageCount; ++pass) {
1050 page+=dx;
1051 if (page < 0
1052#ifdef QT_KEYPAD_NAVIGATION
1053 && !e->isAutoRepeat()
1054#endif
1055 ) {
1056 page = count() - 1;
1057 } else if (page >= pageCount
1058#ifdef QT_KEYPAD_NAVIGATION
1059 && !e->isAutoRepeat()
1060#endif
1061 ) {
1062 page = 0;
1063 }
1064 if (d->tabs->isTabEnabled(page)) {
1065 setCurrentIndex(page);
1066 break;
1067 }
1068 }
1069 if (!QApplication::focusWidget())
1070 d->tabs->setFocus();
1071 } else {
1072 e->ignore();
1073 }
1074}
1075
1076/*!
1077 Returns the tab page at index position \a index or 0 if the \a
1078 index is out of range.
1079*/
1080QWidget *QTabWidget::widget(int index) const
1081{
1082 Q_D(const QTabWidget);
1083 return d->stack->widget(index);
1084}
1085
1086/*!
1087 \property QTabWidget::count
1088 \brief the number of tabs in the tab bar
1089
1090 By default, this property contains a value of 0.
1091*/
1092int QTabWidget::count() const
1093{
1094 Q_D(const QTabWidget);
1095 return d->tabs->count();
1096}
1097
1098#ifndef QT_NO_TOOLTIP
1099/*!
1100 Sets the tab tool tip for the page at position \a index to \a tip.
1101
1102 \sa tabToolTip()
1103*/
1104void QTabWidget::setTabToolTip(int index, const QString & tip)
1105{
1106 Q_D(QTabWidget);
1107 d->tabs->setTabToolTip(index, tip);
1108}
1109
1110/*!
1111 Returns the tab tool tip for the page at position \a index or
1112 an empty string if no tool tip has been set.
1113
1114 \sa setTabToolTip()
1115*/
1116QString QTabWidget::tabToolTip(int index) const
1117{
1118 Q_D(const QTabWidget);
1119 return d->tabs->tabToolTip(index);
1120}
1121#endif // QT_NO_TOOLTIP
1122
1123#ifndef QT_NO_WHATSTHIS
1124/*!
1125 \since 4.1
1126
1127 Sets the What's This help text for the page at position \a index
1128 to \a text.
1129*/
1130void QTabWidget::setTabWhatsThis(int index, const QString &text)
1131{
1132 Q_D(QTabWidget);
1133 d->tabs->setTabWhatsThis(index, text);
1134}
1135
1136/*!
1137 \since 4.1
1138
1139 Returns the What's This help text for the page at position \a index,
1140 or an empty string if no help text has been set.
1141*/
1142QString QTabWidget::tabWhatsThis(int index) const
1143{
1144 Q_D(const QTabWidget);
1145 return d->tabs->tabWhatsThis(index);
1146}
1147#endif // QT_NO_WHATSTHIS
1148
1149/*!
1150 This virtual handler is called after a new tab was added or
1151 inserted at position \a index.
1152
1153 \sa tabRemoved()
1154 */
1155void QTabWidget::tabInserted(int index)
1156{
1157 Q_UNUSED(index)
1158}
1159
1160/*!
1161 This virtual handler is called after a tab was removed from
1162 position \a index.
1163
1164 \sa tabInserted()
1165 */
1166void QTabWidget::tabRemoved(int index)
1167{
1168 Q_UNUSED(index)
1169}
1170
1171/*!
1172 \fn void QTabWidget::paintEvent(QPaintEvent *event)
1173
1174 Paints the tab widget's tab bar in response to the paint \a event.
1175*/
1176void QTabWidget::paintEvent(QPaintEvent *)
1177{
1178 Q_D(QTabWidget);
1179 if (documentMode()) {
1180 QStylePainter p(this, tabBar());
1181 if (QWidget *w = cornerWidget(Qt::TopLeftCorner)) {
1182 QStyleOptionTabBarBaseV2 opt;
1183 QTabBarPrivate::initStyleBaseOption(&opt, tabBar(), w->size());
1184 opt.rect.moveLeft(w->x() + opt.rect.x());
1185 opt.rect.moveTop(w->y() + opt.rect.y());
1186 p.drawPrimitive(QStyle::PE_FrameTabBarBase, opt);
1187 }
1188 if (QWidget *w = cornerWidget(Qt::TopRightCorner)) {
1189 QStyleOptionTabBarBaseV2 opt;
1190 QTabBarPrivate::initStyleBaseOption(&opt, tabBar(), w->size());
1191 opt.rect.moveLeft(w->x() + opt.rect.x());
1192 opt.rect.moveTop(w->y() + opt.rect.y());
1193 p.drawPrimitive(QStyle::PE_FrameTabBarBase, opt);
1194 }
1195 return;
1196 }
1197 QStylePainter p(this);
1198
1199 QStyleOptionTabWidgetFrameV2 opt;
1200 initStyleOption(&opt);
1201 opt.rect = d->panelRect;
1202 p.drawPrimitive(QStyle::PE_FrameTabWidget, opt);
1203}
1204
1205/*!
1206 \property QTabWidget::iconSize
1207 \brief The size for icons in the tab bar
1208 \since 4.2
1209
1210 The default value is style-dependent. This is the maximum size
1211 that the icons will have. Icons are not scaled up if they are of
1212 smaller size.
1213
1214 \sa QTabBar::iconSize
1215*/
1216QSize QTabWidget::iconSize() const
1217{
1218 return d_func()->tabs->iconSize();
1219}
1220
1221void QTabWidget::setIconSize(const QSize &size)
1222{
1223 d_func()->tabs->setIconSize(size);
1224}
1225
1226/*!
1227 \property QTabWidget::elideMode
1228 \brief how to elide text in the tab bar
1229 \since 4.2
1230
1231 This property controls how items are elided when there is not
1232 enough space to show them for a given tab bar size.
1233
1234 By default the value is style dependant.
1235
1236 \sa QTabBar::elideMode usesScrollButtons QStyle::SH_TabBar_ElideMode
1237*/
1238Qt::TextElideMode QTabWidget::elideMode() const
1239{
1240 return d_func()->tabs->elideMode();
1241}
1242
1243void QTabWidget::setElideMode(Qt::TextElideMode mode)
1244{
1245 d_func()->tabs->setElideMode(mode);
1246}
1247
1248/*!
1249 \property QTabWidget::usesScrollButtons
1250 \brief Whether or not a tab bar should use buttons to scroll tabs when it
1251 has many tabs.
1252 \since 4.2
1253
1254 When there are too many tabs in a tab bar for its size, the tab bar can either choose
1255 to expand its size or to add buttons that allow you to scroll through the tabs.
1256
1257 By default the value is style dependant.
1258
1259 \sa elideMode QTabBar::usesScrollButtons QStyle::SH_TabBar_PreferNoArrows
1260*/
1261bool QTabWidget::usesScrollButtons() const
1262{
1263 return d_func()->tabs->usesScrollButtons();
1264}
1265
1266void QTabWidget::setUsesScrollButtons(bool useButtons)
1267{
1268 d_func()->tabs->setUsesScrollButtons(useButtons);
1269}
1270
1271/*!
1272 \property QTabWidget::documentMode
1273 \brief Whether or not the tab widget is rendered in a mode suitable for document
1274 pages. This is the same as document mode on Mac OS X.
1275 \since 4.5
1276
1277 When this property is set the tab widget frame is not rendered. This mode is useful
1278 for showing document-type pages where the page covers most of the tab widget
1279 area.
1280
1281 \sa elideMode, QTabBar::documentMode, QTabBar::usesScrollButtons, QStyle::SH_TabBar_PreferNoArrows
1282*/
1283bool QTabWidget::documentMode() const
1284{
1285 Q_D(const QTabWidget);
1286 return d->tabs->documentMode();
1287}
1288
1289void QTabWidget::setDocumentMode(bool enabled)
1290{
1291 Q_D(QTabWidget);
1292 d->tabs->setDocumentMode(enabled);
1293 d->tabs->setExpanding(!enabled);
1294 d->tabs->setDrawBase(enabled);
1295 setUpLayout();
1296}
1297
1298/*!
1299 Removes all the pages, but does not delete them. Calling this function
1300 is equivalent to calling removeTab() until the tab widget is empty.
1301*/
1302void QTabWidget::clear()
1303{
1304 // ### optimize by introduce QStackedLayout::clear()
1305 while (count())
1306 removeTab(0);
1307}
1308
1309/*!
1310 \fn void QTabWidget::insertTab(QWidget *widget, const QString &label, int index)
1311
1312 Use insertTab(index, widget, label) instead.
1313*/
1314
1315/*!
1316 \fn void QTabWidget::insertTab(QWidget *widget, const QIcon& icon, const QString &label, int index)
1317
1318 Use insertTab(index, widget, icon, label) instead.
1319*/
1320
1321/*!
1322 \fn void QTabWidget::changeTab(QWidget *widget, const QString
1323 &label)
1324
1325 Use setTabText() instead.
1326
1327*/
1328
1329/*!
1330 \fn void QTabWidget::changeTab(QWidget *widget, const QIcon& icon, const QString &label)
1331
1332 Use setTabText() and setTabIcon() instead.
1333*/
1334
1335/*!
1336 \fn bool QTabWidget::isTabEnabled( QWidget *widget) const
1337
1338 Use isTabEnabled(tabWidget->indexOf(widget)) instead.
1339*/
1340
1341/*!
1342 \fn void QTabWidget::setTabEnabled(QWidget *widget, bool b)
1343
1344 Use setTabEnabled(tabWidget->indexOf(widget), b) instead.
1345*/
1346
1347/*!
1348 \fn QString QTabWidget::tabLabel(QWidget *widget) const
1349
1350 Use tabText(tabWidget->indexOf(widget)) instead.
1351*/
1352
1353/*!
1354 \fn void QTabWidget::setTabLabel(QWidget *widget, const QString
1355 &label)
1356
1357 Use setTabText(tabWidget->indexOf(widget), label) instead.
1358*/
1359
1360/*!
1361 \fn QIcon QTabWidget::tabIconSet(QWidget * widget) const
1362
1363 Use tabIcon(tabWidget->indexOf(widget)) instead.
1364*/
1365
1366/*!
1367 \fn void QTabWidget::setTabIconSet(QWidget * widget, const QIcon & icon)
1368
1369 Use setTabIcon(tabWidget->indexOf(widget), icon) instead.
1370*/
1371
1372/*!
1373 \fn void QTabWidget::removeTabToolTip(QWidget * widget)
1374
1375 Use setTabToolTip(tabWidget->indexOf(widget), QString()) instead.
1376*/
1377
1378/*!
1379 \fn void QTabWidget::setTabToolTip(QWidget * widget, const QString & tip)
1380
1381 Use setTabToolTip(tabWidget->indexOf(widget), tip) instead.
1382*/
1383
1384/*!
1385 \fn QString QTabWidget::tabToolTip(QWidget * widget) const
1386
1387 Use tabToolTip(tabWidget->indexOf(widget)) instead.
1388*/
1389
1390/*!
1391 \fn QWidget * QTabWidget::currentPage() const
1392
1393 Use currentWidget() instead.
1394*/
1395
1396/*!
1397 \fn QWidget *QTabWidget::page(int index) const
1398
1399 Use widget() instead.
1400*/
1401
1402/*!
1403 \fn QString QTabWidget::label(int index) const
1404
1405 Use tabText() instead.
1406*/
1407
1408/*!
1409 \fn int QTabWidget::currentPageIndex() const
1410
1411 Use currentIndex() instead.
1412*/
1413
1414/*!
1415 \fn int QTabWidget::margin() const
1416
1417 This function is kept only to make old code compile.
1418 This functionality is no longer supported by QTabWidget.
1419
1420 \sa contentsRect(), setContentsMargins()
1421*/
1422
1423/*!
1424 \fn void QTabWidget::setMargin(int margin)
1425
1426 This function is kept only to make old code compile.
1427 This functionality is no longer supported by QTabWidget.
1428
1429 \sa contentsRect(), setContentsMargins()
1430*/
1431
1432/*!
1433 \fn void QTabWidget::setCurrentPage(int index)
1434
1435 Use setCurrentIndex() instead.
1436*/
1437
1438/*!
1439 \fn void QTabWidget::showPage(QWidget *widget)
1440
1441 Use setCurrentIndex(indexOf(widget)) instead.
1442*/
1443
1444/*!
1445 \fn void QTabWidget::removePage(QWidget *widget)
1446
1447 Use removeTab(indexOf(widget)) instead.
1448*/
1449
1450/*!
1451 \fn void QTabWidget::currentChanged(QWidget *widget)
1452
1453 Use currentChanged(int) instead.
1454*/
1455
1456QT_END_NAMESPACE
1457
1458#include "moc_qtabwidget.cpp"
1459
1460#endif //QT_NO_TABWIDGET
Note: See TracBrowser for help on using the repository browser.