summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@qt.io>2017-08-29 11:44:27 +0700
committerGabriel de Dietrich <gabriel.dedietrich@qt.io>2017-09-22 00:01:24 +0000
commitc84b4ff4958bf3be513b3108d5a07d6565f95a98 (patch)
tree1ca6995068fffd699540b9f1b41f7b5a818c78bd /src/widgets/widgets
parentd25346417238b7dc0fb37359a9b56eff2908a5dc (diff)
QTabWidget: Don't build expensive parts of the style option when hidden
We end up calling setUpLayout() quite a few times and, in particular, every time we add a new tab. Even if the tab widget is hidden, we set the layout item margins to ensure that whatever layout will contain the tab widget can get the proper sizing. For all practical purposes, layout item margins don't depend on the contents itself, but are rather a simple constant returned by the style. This means that QStyleOptionTabWidgetFrame ::tabBarSize, among a few other properties, is not needed right away. This property in particular is quite expensive to compute because it requires measuring the text size of each tab. This can lead to a quadratic behavior: the size of each tab's text will be computed for each tab we add. Besides, text size computing has become a relatively expensive function in itself (see QTBUG-53151, for example). The current solution just uses a partially initialized style option object for the sole purpose of getting the tab widget's layout item margins from the style. The performance improvements detailed show the creation time for QTabWidget with the specified amount of tabs (times in ms): Tabs Before After ------------------- 1 6 5 5 6 6 10 8 6 50 57 17 100 178 21 200 673 33 Task-number: QTBUG-55126 Change-Id: I79505dbd0014f6ed185da28047d8b68f9462ba94 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/widgets/widgets')
-rw-r--r--src/widgets/widgets/qtabwidget.cpp83
1 files changed, 49 insertions, 34 deletions
diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp
index c496d267b3..dc866a38cf 100644
--- a/src/widgets/widgets/qtabwidget.cpp
+++ b/src/widgets/widgets/qtabwidget.cpp
@@ -195,6 +195,8 @@ public:
void _q_tabMoved(int from, int to);
void init();
+ void initBasicStyleOption(QStyleOptionTabWidgetFrame *option) const;
+
QTabBar *tabs;
QStackedWidget *stack;
QRect panelRect;
@@ -257,6 +259,43 @@ bool QTabWidget::hasHeightForWidth() const
return has;
}
+/*!
+ \internal
+
+ Initialize only time inexpensive parts of the style option
+ for QTabWidget::setUpLayout()'s non-visible code path.
+*/
+void QTabWidgetPrivate::initBasicStyleOption(QStyleOptionTabWidgetFrame *option) const
+{
+ Q_Q(const QTabWidget);
+ option->initFrom(q);
+
+ if (q->documentMode())
+ option->lineWidth = 0;
+ else
+ option->lineWidth = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, q);
+
+ switch (pos) {
+ case QTabWidget::North:
+ option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedNorth
+ : QTabBar::TriangularNorth;
+ break;
+ case QTabWidget::South:
+ option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedSouth
+ : QTabBar::TriangularSouth;
+ break;
+ case QTabWidget::West:
+ option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedWest
+ : QTabBar::TriangularWest;
+ break;
+ case QTabWidget::East:
+ option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedEast
+ : QTabBar::TriangularEast;
+ break;
+ }
+
+ option->tabBarRect = q->tabBar()->geometry();
+}
/*!
Initialize \a option with the values from this QTabWidget. This method is useful
@@ -271,12 +310,7 @@ void QTabWidget::initStyleOption(QStyleOptionTabWidgetFrame *option) const
return;
Q_D(const QTabWidget);
- option->initFrom(this);
-
- if (documentMode())
- option->lineWidth = 0;
- else
- option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this);
+ d->initBasicStyleOption(option);
int exth = style()->pixelMetric(QStyle::PM_TabBarBaseHeight, 0, this);
QSize t(0, d->stack->frameWidth());
@@ -307,31 +341,10 @@ void QTabWidget::initStyleOption(QStyleOptionTabWidgetFrame *option) const
option->leftCornerWidgetSize = QSize(0, 0);
}
- switch (d->pos) {
- case QTabWidget::North:
- option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedNorth
- : QTabBar::TriangularNorth;
- break;
- case QTabWidget::South:
- option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedSouth
- : QTabBar::TriangularSouth;
- break;
- case QTabWidget::West:
- option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedWest
- : QTabBar::TriangularWest;
- break;
- case QTabWidget::East:
- option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedEast
- : QTabBar::TriangularEast;
- break;
- }
-
option->tabBarSize = t;
- QRect tbRect = tabBar()->geometry();
QRect selectedTabRect = tabBar()->tabRect(tabBar()->currentIndex());
- option->tabBarRect = tbRect;
- selectedTabRect.moveTopLeft(selectedTabRect.topLeft() + tbRect.topLeft());
+ selectedTabRect.moveTopLeft(selectedTabRect.topLeft() + option->tabBarRect.topLeft());
option->selectedTabRect = selectedTabRect;
}
@@ -763,17 +776,19 @@ void QTabWidget::setUpLayout(bool onlyCheck)
if (onlyCheck && !d->dirty)
return; // nothing to do
- QStyleOptionTabWidgetFrame option;
- initStyleOption(&option);
-
- // this must be done immediately, because QWidgetItem relies on it (even if !isVisible())
- d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &option);
-
if (!isVisible()) {
+ // this must be done immediately, because QWidgetItem relies on it (even if !isVisible())
+ QStyleOptionTabWidgetFrame basicOption;
+ d->initBasicStyleOption(&basicOption);
+ d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &basicOption);
d->dirty = true;
return; // we'll do it later
}
+ QStyleOptionTabWidgetFrame option;
+ initStyleOption(&option);
+ d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &option);
+
QRect tabRect = style()->subElementRect(QStyle::SE_TabWidgetTabBar, &option, this);
d->panelRect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option, this);
QRect contentsRect = style()->subElementRect(QStyle::SE_TabWidgetTabContents, &option, this);