diff options
Diffstat (limited to 'src/qml/types/qqmlbind.cpp')
-rw-r--r-- | src/qml/types/qqmlbind.cpp | 83 |
1 files changed, 74 insertions, 9 deletions
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 861243987f..921d60caa1 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -54,11 +54,14 @@ #include <QtCore/qfile.h> #include <QtCore/qdebug.h> #include <QtCore/qtimer.h> +#include <QtCore/qloggingcategory.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval) + class QQmlBindPrivate : public QObjectPrivate { public: @@ -72,13 +75,14 @@ public: , restoreBinding(true) , restoreValue(false) , restoreModeExplicit(false) + , writingProperty(false) {} ~QQmlBindPrivate() { } QQmlNullableValue<bool> when; QPointer<QObject> obj; QString propName; - QQmlNullableValue<QVariant> value; + QQmlNullableValue<QJSValue> value; QQmlProperty prop; QQmlAbstractBinding::Ptr prevBind; QV4::PersistentValue v4Value; @@ -90,6 +94,7 @@ public: bool restoreBinding:1; bool restoreValue:1; bool restoreModeExplicit:1; + bool writingProperty: 1; void validate(QObject *binding) const; void clearPrev(); @@ -193,6 +198,13 @@ QQmlBind::~QQmlBind() When the binding becomes inactive again, any direct bindings that were previously set on the property will be restored. + + \note By default, a previously set literal value is not restored when the Binding becomes + inactive. Rather, the last value set by the now inactive Binding is retained. You can customize + the restoration behavior for literal values as well as bindings using the \l restoreMode + property. The default will change in Qt 6.0. + + \sa restoreMode */ bool QQmlBind::when() const { @@ -235,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(); @@ -281,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(); @@ -293,13 +305,13 @@ void QQmlBind::setProperty(const QString &p) The value to be set on the target object and property. This can be a constant (which isn't very useful), or a bound expression. */ -QVariant QQmlBind::value() const +QJSValue QQmlBind::value() const { Q_D(const QQmlBind); return d->value.value; } -void QQmlBind::setValue(const QVariant &v) +void QQmlBind::setValue(const QJSValue &v) { Q_D(QQmlBind); d->value = v; @@ -359,7 +371,8 @@ void QQmlBind::setDelayed(bool delayed) \li Binding.RestoreBindingOrValue The original value is always restored. \endlist - The default value is Binding.RestoreBinding. + \warning The default value is Binding.RestoreBinding. This will change in + Qt 6.0 to Binding.RestoreBindingOrValue. If you rely on any specific behavior regarding the restoration of plain values when bindings get disabled you should migrate to explicitly set the @@ -382,10 +395,10 @@ QQmlBind::RestorationMode QQmlBind::restoreMode() const void QQmlBind::setRestoreMode(RestorationMode newMode) { Q_D(QQmlBind); + d->restoreModeExplicit = true; if (newMode != restoreMode()) { d->restoreValue = (newMode & RestoreValue); d->restoreBinding = (newMode & RestoreBinding); - d->restoreModeExplicit = true; emit restoreModeChanged(); } } @@ -393,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; } @@ -407,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(); @@ -456,11 +482,23 @@ void QQmlBind::eval() Q_ASSERT(vmemo); vmemo->setVMEProperty(propPriv->core.coreIndex(), *d->v4Value.valueRef()); d->clearPrev(); + } else if (!d->restoreModeExplicit) { + qmlWarning(this) + << "Not restoring previous value because restoreMode has not been set." + << "This behavior is deprecated." + << "In Qt < 6.0 the default is Binding.RestoreBinding." + << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue."; } } else if (d->prevIsVariant) { if (d->restoreValue) { d->prop.write(d->prevValue); d->clearPrev(); + } else if (!d->restoreModeExplicit) { + qmlWarning(this) + << "Not restoring previous value because restoreMode has not been set." + << "This behavior is deprecated." + << "In Qt < 6.0 the default is Binding.RestoreBinding." + << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue."; } } return; @@ -489,7 +527,34 @@ void QQmlBind::eval() QQmlPropertyPrivate::removeBinding(d->prop); } - d->prop.write(d->value.value); + 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 |