diff options
Diffstat (limited to 'src/qml/qml/qqmljavascriptexpression.cpp')
-rw-r--r-- | src/qml/qml/qqmljavascriptexpression.cpp | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 0f83baa893..88a9932f53 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qqmljavascriptexpression_p.h" +#include "qqmljavascriptexpression_p.h" #include <private/qqmlexpression_p.h> #include <private/qv4context_p.h> @@ -51,6 +52,9 @@ #include <private/qv4qobjectwrapper_p.h> #include <private/qqmlbuiltinfunctions_p.h> #include <private/qqmlsourcecoordinate_p.h> +#include <private/qqmlabstractbinding_p.h> +#include <private/qqmlpropertybinding_p.h> +#include <private/qproperty_p.h> QT_BEGIN_NAMESPACE @@ -109,6 +113,12 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression() m_nextExpression->m_prevExpression = m_prevExpression; } + while (qpropertyChangeTriggers) { + auto current = qpropertyChangeTriggers; + qpropertyChangeTriggers = current->next; + QRecyclePool<TriggerList>::Delete(current); + } + clearActiveGuards(); clearError(); if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion. @@ -289,7 +299,33 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, bool doNotif return; Q_ASSERT(expression); + const QQmlData *ddata = QQmlData::get(o, /*create=*/false); + bool isBindable = false; + if (auto const propCache = ddata ? ddata->propertyCache : nullptr; propCache) { + Q_ASSERT(propCache->property(c)); + isBindable = propCache->property(c)->isBindable(); + } else { + auto metaProp = o->staticMetaObject.property(c); + isBindable = metaProp.isBindable(); + } + if (isBindable) { + // if the property is a QPropery, and we're binding to a QProperty + // the automatic capturing process already takes care of everything + if (typeid(QQmlPropertyBinding) == typeid(*expression)) + return; + for (auto trigger = expression->qpropertyChangeTriggers; trigger; trigger = trigger->next) { + if (trigger->target == o && trigger->propertyIndex == c) + return; // already installed + } + auto trigger = expression->allocatePropertyChangeTrigger(o, c); + QUntypedBindable bindable; + void *argv[] = { &bindable }; + o->qt_metacall(QMetaObject::BindableProperty, c, argv); + bindable.observe(trigger); + return; + } if (n == -1) { + if (!errorString) { errorString = new QStringList; QString preamble = QLatin1String("QQmlExpression: Expression ") + @@ -298,11 +334,9 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, bool doNotif errorString->append(preamble); } - const QMetaObject *metaObj = o->metaObject(); - QMetaProperty metaProp = metaObj->property(c); - + const QMetaProperty metaProp = o->metaObject()->property(c); QString error = QLatin1String(" ") + - QString::fromUtf8(metaObj->className()) + + QString::fromUtf8(o->metaObject()->className()) + QLatin1String("::") + QString::fromUtf8(metaProp.name()); errorString->append(error); @@ -413,6 +447,21 @@ void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer<QV4::Exec m_compilationUnit = compilationUnit; } +void QPropertyChangeTrigger::operator()() { + m_expression->expressionChanged(); +} + +QPropertyChangeHandler<QPropertyChangeTrigger> *QQmlJavaScriptExpression::allocatePropertyChangeTrigger(QObject *target, int propertyIndex) +{ + auto trigger = QQmlEnginePrivate::get(engine())->qPropertyTriggerPool.New(QPropertyChangeTrigger { this }); + trigger->target = target; + trigger->propertyIndex = propertyIndex; + auto oldHead = qpropertyChangeTriggers; + trigger->next = oldHead; + qpropertyChangeTriggers = trigger; + return trigger; +} + void QQmlJavaScriptExpression::clearActiveGuards() { while (QQmlJavaScriptExpressionGuard *g = activeGuards.takeFirst()) |