From d522746afa394960bef225ba08080d8364b69a7e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 9 Oct 2019 13:51:33 +0200 Subject: Output a message when changing the target of a Binding from elsewhere Explicitly created Binding elements should not be silently disabled when writing their target property. That would be rather confusing. Instead, the binding stays active and updates the target property again on the next change. This behavior is still somewhat confusing. Therefore, if the qt.qml.binding.removal logging category is enabled, output a helpful message. Fixes: QTBUG-78566 Change-Id: Idcd8e51e1cd7eaf78d70b15f065fd9159521ff20 Reviewed-by: Simon Hausmann --- src/qml/types/qqmlbind.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++--- src/qml/types/qqmlbind_p.h | 3 +++ 2 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src/qml') diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 7ab854dad0..921d60caa1 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -54,11 +54,14 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval) + class QQmlBindPrivate : public QObjectPrivate { public: @@ -72,6 +75,7 @@ public: , restoreBinding(true) , restoreValue(false) , restoreModeExplicit(false) + , writingProperty(false) {} ~QQmlBindPrivate() { } @@ -90,6 +94,7 @@ public: bool restoreBinding:1; bool restoreValue:1; bool restoreModeExplicit:1; + bool writingProperty: 1; void validate(QObject *binding) const; void clearPrev(); @@ -242,7 +247,7 @@ void QQmlBind::setObject(QObject *obj) } d->obj = obj; if (d->componentComplete) { - d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this)); + setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this))); d->validate(this); } eval(); @@ -288,7 +293,7 @@ void QQmlBind::setProperty(const QString &p) } d->propName = p; if (d->componentComplete) { - d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this)); + setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this))); d->validate(this); } eval(); @@ -401,6 +406,19 @@ void QQmlBind::setRestoreMode(RestorationMode newMode) void QQmlBind::setTarget(const QQmlProperty &p) { Q_D(QQmlBind); + + if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) { + if (QObject *oldObject = d->prop.object()) { + QMetaProperty prop = oldObject->metaObject()->property(d->prop.index()); + if (prop.hasNotifySignal()) { + QByteArray signal('2' + prop.notifySignal().methodSignature()); + QObject::disconnect(oldObject, signal.constData(), + this, SLOT(targetValueChanged())); + } + } + p.connectNotifySignal(this, SLOT(targetValueChanged())); + } + d->prop = p; } @@ -415,7 +433,7 @@ void QQmlBind::componentComplete() Q_D(QQmlBind); d->componentComplete = true; if (!d->prop.isValid()) { - d->prop = QQmlProperty(d->obj, d->propName, qmlContext(this)); + setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this))); d->validate(this); } eval(); @@ -509,7 +527,34 @@ void QQmlBind::eval() QQmlPropertyPrivate::removeBinding(d->prop); } + d->writingProperty = true; d->prop.write(d->value.value.toVariant()); + d->writingProperty = false; +} + +void QQmlBind::targetValueChanged() +{ + Q_D(QQmlBind); + if (d->writingProperty) + return; + + if (d->when.isValid() && !d->when) + return; + + QUrl url; + quint16 line = 0; + + const QQmlData *ddata = QQmlData::get(this, false); + if (ddata && ddata->outerContext) { + url = ddata->outerContext->url(); + line = ddata->lineNumber; + } + + qCInfo(lcBindingRemoval, + "The target property of the Binding element created at %s:%d was changed from " + "elsewhere. This does not overwrite the binding. The target property will still be " + "updated when the value of the Binding element changes.", + qPrintable(url.toString()), line); } QT_END_NAMESPACE diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h index ba040d2a0b..7bf4fc4dfd 100644 --- a/src/qml/types/qqmlbind_p.h +++ b/src/qml/types/qqmlbind_p.h @@ -115,6 +115,9 @@ protected: private: void prepareEval(); void eval(); + +private Q_SLOTS: + void targetValueChanged(); }; QT_END_NAMESPACE -- cgit v1.2.3