aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/types/qqmlbind.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/types/qqmlbind.cpp')
-rw-r--r--src/qml/types/qqmlbind.cpp83
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