aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2018-03-09 11:44:27 +0100
committerJ-P Nurmi <jpnurmi@qt.io>2018-03-09 13:32:21 +0000
commit87dec648804bfa974a297c37542dd77de9f72e9f (patch)
tree1a242c80ce83e8a3185a5a7ca0a9d78a76175860 /src/quicktemplates2
parentb6d847ac5bb0e32f928f616cee03d323aab33e55 (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.cpp156
-rw-r--r--src/quicktemplates2/qquickpane_p.h7
-rw-r--r--src/quicktemplates2/qquickpane_p_p.h18
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;
};