diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2019-02-19 14:22:27 +0100 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2019-02-20 14:33:05 +0000 |
commit | 16836da1ae44c11317b9861764ea55cce39eac02 (patch) | |
tree | 9b7426680516b54e409ab94a437f9e14fdd15db9 | |
parent | 0dfc617e4d089f7513573673d12f9678a88d3081 (diff) |
Page: fix binding loop
When Dialog (which derives from Page) has only its title set,
there'd be a binding loop. A simplified version of the call stack:
- QQuickPopup::componentComplete
- QQuickPopupPrivate::prepareEnterTransition
- QQuickItem::setVisible
- QQuickPagePrivate::itemVisibilityChanged
- QQuickDialog::implicitHeaderWidthChanged
- QQmlBinding::expressionChanged <== Dialog.qml's implicitWidth binding
- QQmlPropertyData::readProperty
- QQuickDialog::implicitHeaderWidth
- QQuickPage::implicitHeaderWidth
- QQuickItem::implicitWidth <== QQuickPagePrivate::header, aka Label
- QQuickTextPrivate::getImplicitWidth
- QQuickTextPrivate::updateSize
- QQuickTextPrivate::setupTextLayout
- QQuickItem::setImplicitSize
- QQuickItemPrivate::implicitWidthChanged
- QQuickPagePrivate::itemImplicitWidthChanged
- QQuickDialog::implicitHeaderWidthChanged
- QQmlBinding::expressionChanged
- QQmlAbstractBinding::printBindingLoopError
Fix the issue by not emitting change signals if we're already in the
process of doing so.
Change-Id: I37d6fa35b1e70420e436c0e001f55035d7630542
Fixes: QTBUG-66494
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
-rw-r--r-- | src/quicktemplates2/qquickpage.cpp | 12 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpage_p_p.h | 1 |
2 files changed, 13 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquickpage.cpp b/src/quicktemplates2/qquickpage.cpp index 56034297..cb90ac48 100644 --- a/src/quicktemplates2/qquickpage.cpp +++ b/src/quicktemplates2/qquickpage.cpp @@ -149,10 +149,12 @@ void QQuickPagePrivate::itemVisibilityChanged(QQuickItem *item) Q_Q(QQuickPage); QQuickPanePrivate::itemVisibilityChanged(item); if (item == header) { + QBoolBlocker signalGuard(emittingImplicitSizeChangedSignals); emit q->implicitHeaderWidthChanged(); emit q->implicitHeaderHeightChanged(); relayout(); } else if (item == footer) { + QBoolBlocker signalGuard(emittingImplicitSizeChangedSignals); emit q->implicitFooterWidthChanged(); emit q->implicitFooterHeightChanged(); relayout(); @@ -163,6 +165,11 @@ void QQuickPagePrivate::itemImplicitWidthChanged(QQuickItem *item) { Q_Q(QQuickPage); QQuickPanePrivate::itemImplicitWidthChanged(item); + + // Avoid binding loops by skipping signal emission if we're already doing it. + if (emittingImplicitSizeChangedSignals) + return; + if (item == header) emit q->implicitHeaderWidthChanged(); else if (item == footer) @@ -173,6 +180,11 @@ void QQuickPagePrivate::itemImplicitHeightChanged(QQuickItem *item) { Q_Q(QQuickPage); QQuickPanePrivate::itemImplicitHeightChanged(item); + + // Avoid binding loops by skipping signal emission if we're already doing it. + if (emittingImplicitSizeChangedSignals) + return; + if (item == header) emit q->implicitHeaderHeightChanged(); else if (item == footer) diff --git a/src/quicktemplates2/qquickpage_p_p.h b/src/quicktemplates2/qquickpage_p_p.h index b7d89ac4..6c8b0371 100644 --- a/src/quicktemplates2/qquickpage_p_p.h +++ b/src/quicktemplates2/qquickpage_p_p.h @@ -71,6 +71,7 @@ public: QString title; QQuickItem *header = nullptr; QQuickItem *footer = nullptr; + bool emittingImplicitSizeChangedSignals = false; }; QT_END_NAMESPACE |