diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2018-03-09 11:44:27 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2018-03-09 13:32:21 +0000 |
commit | 87dec648804bfa974a297c37542dd77de9f72e9f (patch) | |
tree | 1a242c80ce83e8a3185a5a7ca0a9d78a76175860 /src/quicktemplates2/qquickpane.cpp | |
parent | b6d847ac5bb0e32f928f616cee03d323aab33e55 (diff) |
QQuickPane: calculate content size in C++ unless explicitly defined
No more need for the clumsy and slow contentWidth and contentHeight
bindings in Pane and its derivatives.
QmlBench on TX1:
Pane: 26.4 -> 32.8 frames (~24%)
Frame: 25.4 -> 31 frames (~22%)
GroupBox: 28.6 -> 32 frames (~12%)
Change-Id: I4ba1d46ba6328de2ee0955c241d4b090127f6b85
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quicktemplates2/qquickpane.cpp')
-rw-r--r-- | src/quicktemplates2/qquickpane.cpp | 156 |
1 files changed, 151 insertions, 5 deletions
diff --git a/src/quicktemplates2/qquickpane.cpp b/src/quicktemplates2/qquickpane.cpp index 4c3e1422..7de0e1c5 100644 --- a/src/quicktemplates2/qquickpane.cpp +++ b/src/quicktemplates2/qquickpane.cpp @@ -104,8 +104,12 @@ QT_BEGIN_NAMESPACE \sa {Customizing Pane}, {Container Controls} */ +static const QQuickItemPrivate::ChangeTypes ImplicitSizeChanges = QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed; + QQuickPanePrivate::QQuickPanePrivate() - : contentWidth(0), + : hasContentWidth(false), + hasContentHeight(false), + contentWidth(0), contentHeight(0) { } @@ -118,6 +122,112 @@ QQuickItem *QQuickPanePrivate::getContentItem() return new QQuickItem(q); } +void QQuickPanePrivate::addImplicitSizeListener(QQuickItem *item) +{ + if (!item) + return; + + QQuickItemPrivate::get(item)->addItemChangeListener(this, ImplicitSizeChanges); +} + +void QQuickPanePrivate::removeImplicitSizeListener(QQuickItem *item) +{ + if (!item) + return; + + QQuickItemPrivate::get(item)->removeItemChangeListener(this, ImplicitSizeChanges); +} + +void QQuickPanePrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickPane); + if (item == contentItem && updateContentWidth(item)) + emit q->contentWidthChanged(); +} + +void QQuickPanePrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickPane); + if (item == contentItem && updateContentHeight(item)) + emit q->contentHeightChanged(); +} + +void QQuickPanePrivate::itemDestroyed(QQuickItem *item) +{ + if (item == contentItem) + updateContentSize(nullptr); +} + +void QQuickPanePrivate::contentChildrenChange() +{ + Q_Q(QQuickPane); + updateContentSize(contentItem); + emit q->contentChildrenChanged(); +} + +static qreal getContentWidth(QQuickItem *item) +{ + if (!item) + return 0; + + const qreal cw = item->implicitWidth(); + if (!qFuzzyIsNull(cw)) + return cw; + + const auto contentChildren = item->childItems(); + if (contentChildren.count() == 1) + return contentChildren.first()->implicitWidth(); + + return 0; +} + +static qreal getContentHeight(QQuickItem *item) +{ + if (!item) + return 0; + + const qreal ch = item->implicitHeight(); + if (!qFuzzyIsNull(ch)) + return ch; + + const auto contentChildren = item->childItems(); + if (contentChildren.count() == 1) + return contentChildren.first()->implicitHeight(); + + return 0; +} + +bool QQuickPanePrivate::updateContentWidth(QQuickItem *item) +{ + if (hasContentWidth) + return false; + + qreal oldContentWidth = contentWidth; + contentWidth = getContentWidth(item); + return !qFuzzyCompare(contentWidth, oldContentWidth); +} + +bool QQuickPanePrivate::updateContentHeight(QQuickItem *item) +{ + if (hasContentHeight) + return false; + + qreal oldContentHeight = contentHeight; + contentHeight = getContentHeight(item); + return !qFuzzyCompare(contentHeight, oldContentHeight); +} + +void QQuickPanePrivate::updateContentSize(QQuickItem *item) +{ + Q_Q(QQuickPane); + bool widthChanged = updateContentWidth(item); + bool heightChanged = updateContentHeight(item); + if (widthChanged) + emit q->contentWidthChanged(); + if (heightChanged) + emit q->contentHeightChanged(); +} + QQuickPane::QQuickPane(QQuickItem *parent) : QQuickControl(*(new QQuickPanePrivate), parent) { @@ -128,6 +238,12 @@ QQuickPane::QQuickPane(QQuickItem *parent) #endif } +QQuickPane::~QQuickPane() +{ + Q_D(QQuickPane); + d->removeImplicitSizeListener(d->contentItem); +} + QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent) : QQuickControl(dd, parent) { @@ -157,6 +273,7 @@ qreal QQuickPane::contentWidth() const void QQuickPane::setContentWidth(qreal width) { Q_D(QQuickPane); + d->hasContentWidth = true; if (qFuzzyCompare(d->contentWidth, width)) return; @@ -164,6 +281,17 @@ void QQuickPane::setContentWidth(qreal width) emit contentWidthChanged(); } +void QQuickPane::resetContentWidth() +{ + Q_D(QQuickPane); + if (!d->hasContentWidth) + return; + + d->hasContentHeight = false; + if (d->updateContentWidth(d->contentItem)) + emit contentWidthChanged(); +} + /*! \qmlproperty real QtQuick.Controls::Pane::contentHeight @@ -183,6 +311,7 @@ qreal QQuickPane::contentHeight() const void QQuickPane::setContentHeight(qreal height) { Q_D(QQuickPane); + d->hasContentHeight = true; if (qFuzzyCompare(d->contentHeight, height)) return; @@ -190,6 +319,17 @@ void QQuickPane::setContentHeight(qreal height) emit contentHeightChanged(); } +void QQuickPane::resetContentHeight() +{ + Q_D(QQuickPane); + if (!d->hasContentHeight) + return; + + d->hasContentHeight = false; + if (d->updateContentHeight(d->contentItem)) + emit contentHeightChanged(); +} + /*! \qmlproperty list<Object> QtQuick.Controls::Pane::contentData \default @@ -237,11 +377,17 @@ QQmlListProperty<QQuickItem> QQuickPane::contentChildren() void QQuickPane::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) { + Q_D(QQuickPane); QQuickControl::contentItemChange(newItem, oldItem); - if (oldItem) - disconnect(oldItem, &QQuickItem::childrenChanged, this, &QQuickPane::contentChildrenChanged); - if (newItem) - connect(newItem, &QQuickItem::childrenChanged, this, &QQuickPane::contentChildrenChanged); + if (oldItem) { + d->removeImplicitSizeListener(oldItem); + QObjectPrivate::disconnect(oldItem, &QQuickItem::childrenChanged, d, &QQuickPanePrivate::contentChildrenChange); + } + if (newItem) { + d->addImplicitSizeListener(newItem); + QObjectPrivate::connect(newItem, &QQuickItem::childrenChanged, d, &QQuickPanePrivate::contentChildrenChange); + } + d->updateContentSize(newItem); emit contentChildrenChanged(); } |