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 | |
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')
-rw-r--r-- | src/quicktemplates2/qquickpane.cpp | 156 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpane_p.h | 7 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpane_p_p.h | 18 |
3 files changed, 173 insertions, 8 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(); } diff --git a/src/quicktemplates2/qquickpane_p.h b/src/quicktemplates2/qquickpane_p.h index 759c59d8..53bf7067 100644 --- a/src/quicktemplates2/qquickpane_p.h +++ b/src/quicktemplates2/qquickpane_p.h @@ -58,20 +58,23 @@ class QQuickPanePrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPane : public QQuickControl { Q_OBJECT - Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged FINAL) - Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged FINAL) + Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL) + Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL) Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) Q_CLASSINFO("DefaultProperty", "contentData") public: explicit QQuickPane(QQuickItem *parent = nullptr); + ~QQuickPane(); qreal contentWidth() const; void setContentWidth(qreal width); + void resetContentWidth(); qreal contentHeight() const; void setContentHeight(qreal height); + void resetContentHeight(); QQmlListProperty<QObject> contentData(); QQmlListProperty<QQuickItem> contentChildren(); diff --git a/src/quicktemplates2/qquickpane_p_p.h b/src/quicktemplates2/qquickpane_p_p.h index 16a07f08..4d9a1747 100644 --- a/src/quicktemplates2/qquickpane_p_p.h +++ b/src/quicktemplates2/qquickpane_p_p.h @@ -49,12 +49,13 @@ // #include <QtQuickTemplates2/private/qquickcontrol_p_p.h> +#include <QtQuick/private/qquickitemchangelistener_p.h> QT_BEGIN_NAMESPACE class QQuickPane; -class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPanePrivate : public QQuickControlPrivate +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPanePrivate : public QQuickControlPrivate, public QQuickItemChangeListener { Q_DECLARE_PUBLIC(QQuickPane) @@ -63,6 +64,21 @@ public: QQuickItem *getContentItem() override; + void addImplicitSizeListener(QQuickItem *item); + void removeImplicitSizeListener(QQuickItem *item); + + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + void itemDestroyed(QQuickItem *item) override; + + void contentChildrenChange(); + + bool updateContentWidth(QQuickItem *item); + bool updateContentHeight(QQuickItem *item); + void updateContentSize(QQuickItem *item); + + bool hasContentWidth; + bool hasContentHeight; qreal contentWidth; qreal contentHeight; }; |