diff options
Diffstat (limited to 'src/quick/util/qquickpropertychanges.cpp')
-rw-r--r-- | src/quick/util/qquickpropertychanges.cpp | 352 |
1 files changed, 165 insertions, 187 deletions
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 8e2ac32ace..ab08a725bb 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qquickpropertychanges_p.h" @@ -51,10 +15,15 @@ #include <private/qqmlcontext_p.h> #include <private/qquickstate_p_p.h> #include <private/qqmlboundsignal_p.h> +#include <private/qv4qmlcontext_p.h> +#include <private/qqmlpropertybinding_p.h> +#include <private/qqmlirbuilder_p.h> #include <QtCore/qdebug.h> +#include <QtQml/private/qqmlsignalnames_p.h> #include <private/qobject_p.h> +#include <QtCore/qpointer.h> QT_BEGIN_NAMESPACE @@ -68,9 +37,9 @@ QT_BEGIN_NAMESPACE \l State. This enables an item's property values to be changed when it \l {Qt Quick States}{changes between states}. - To create a PropertyChanges object, specify the \l target item whose - properties are to be modified, and define the new property values or - bindings. For example: + To create a PropertyChanges object, bind to properties of the target + item like you would bind to local properties. This way you can define + the new property values or bindings. For example: \snippet qml/propertychanges.qml import \codeline @@ -91,8 +60,7 @@ QT_BEGIN_NAMESPACE \qml PropertyChanges { - target: myMouseArea - onClicked: doSomethingDifferent() + myMouseArea.onClicked: doSomethingDifferent() } \endqml @@ -128,12 +96,22 @@ QT_BEGIN_NAMESPACE changed implicitly through their parent's state, they should be set explicitly in all PropertyChanges. An item will still not be enabled/visible if one of its parents is not enabled or visible. - \sa {Qt Quick Examples - Animation#States}{States example}, {Qt Quick States}, {Qt QML} + \note For backwards compatibility with Qt 5, you can also specify PropertyChanges using + the \l target property and plain property names without IDs. For example: + \c {PropertyChanges { target: myItem; x: 15 }}. The form with ID instead of \l target + is recommended. You may also need to use the form with \l target if the file is to be + edited with \l{Qt Design Studio}. Mind that \l{Qt Design Studio} also imposes a number + of further restrictions on the files it can work with. + + \sa {Qt Quick Examples - Animation#States}{States example}, {Qt Quick States}, {Qt Qml} */ /*! - \qmlproperty Object QtQuick::PropertyChanges::target + \qmlproperty QtObject QtQuick::PropertyChanges::target This property holds the object which contains the properties to be changed. + + \note You generally don't have to use this property. It only exists for + compatibility with Qt 5 and for compatibility with \l{Qt Design Studio}. */ class QQuickReplaceSignalHandler : public QQuickStateActionEvent @@ -145,17 +123,17 @@ public: EventType type() const override { return SignalHandler; } QQmlProperty property; - QQmlBoundSignalExpressionPointer expression; - QQmlBoundSignalExpressionPointer reverseExpression; - QQmlBoundSignalExpressionPointer rewindExpression; + QQmlRefPointer<QQmlBoundSignalExpression> expression; + QQmlRefPointer<QQmlBoundSignalExpression> reverseExpression; + QQmlRefPointer<QQmlBoundSignalExpression> rewindExpression; void execute() override { - QQmlPropertyPrivate::setSignalExpression(property, expression); + QQmlPropertyPrivate::setSignalExpression(property, expression.data()); } bool isReversable() override { return true; } void reverse() override { - QQmlPropertyPrivate::setSignalExpression(property, reverseExpression); + QQmlPropertyPrivate::setSignalExpression(property, reverseExpression.data()); } void saveOriginals() override { @@ -174,7 +152,7 @@ public: } void rewind() override { - QQmlPropertyPrivate::setSignalExpression(property, rewindExpression); + QQmlPropertyPrivate::setSignalExpression(property, rewindExpression.data()); } void saveCurrentValues() override { rewindExpression = QQmlPropertyPrivate::signalExpression(property); @@ -201,14 +179,14 @@ public: QPointer<QObject> object; QList<const QV4::CompiledData::Binding *> bindings; - QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit; + QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; bool decoded : 1; bool restore : 1; bool isExplicit : 1; void decode(); - void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding); + void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding); class ExpressionChange { public: @@ -236,20 +214,24 @@ public: QQmlProperty property(const QString &); }; -void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) +void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) { - if (binding->type == QV4::CompiledData::Binding::Type_Object) { - error(compilationUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects.")); - return; - } - - if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty - || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_Object: + error(compilationUnit->objectAt(binding->value.objectIndex), + QQuickPropertyChanges::tr( + "PropertyChanges does not support creating state-specific objects.")); + break; + case QV4::CompiledData::Binding::Type_GroupProperty: + case QV4::CompiledData::Binding::Type_AttachedProperty: { const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex); const QV4::CompiledData::Binding *subBinding = subObj->bindingTable(); - for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) { + for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) verifyList(compilationUnit, subBinding); - } + break; + } + default: + break; } } @@ -258,7 +240,7 @@ void QQuickPropertyChangesPrivate::decode() if (decoded) return; - for (const QV4::CompiledData::Binding *binding : qAsConst(bindings)) + for (const QV4::CompiledData::Binding *binding : std::as_const(bindings)) decodeBinding(QString(), compilationUnit, binding); bindings.clear(); @@ -266,14 +248,15 @@ void QQuickPropertyChangesPrivate::decode() decoded = true; } -void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) +void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) { Q_Q(QQuickPropertyChanges); QString propertyName = propertyPrefix + compilationUnit->stringAt(binding->propertyNameIndex); - if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty - || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_GroupProperty: + case QV4::CompiledData::Binding::Type_AttachedProperty: { QString pre = propertyName + QLatin1Char('.'); const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex); const QV4::CompiledData::Binding *subBinding = subObj->bindingTable(); @@ -282,23 +265,27 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, } return; } + default: + break; + } - if (propertyName.count() >= 3 && - propertyName.at(0) == QLatin1Char('o') && - propertyName.at(1) == QLatin1Char('n') && - propertyName.at(2).isUpper()) { + if (binding->isSignalHandler() || QQmlSignalNames::isHandlerName(propertyName)) { QQmlProperty prop = property(propertyName); if (prop.isSignalProperty()) { QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler; handler->property = prop; - handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), - QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex))); + handler->expression.adopt( + new QQmlBoundSignalExpression( + prop.object(), QQmlPropertyPrivate::get(prop)->signalIndex(), + QQmlContextData::get(qmlContext(q)), prop.object(), + compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex))); signalReplacements << handler; return; } } - if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { + if (binding->type() == QV4::CompiledData::Binding::Type_Script + || binding->isTranslationBinding()) { QUrl url = QUrl(); int line = -1; int column = -1; @@ -314,7 +301,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, QQmlBinding::Identifier id = QQmlBinding::Invalid; if (!binding->isTranslationBinding()) { - expression = binding->valueAsString(compilationUnit.data()); + expression = compilationUnit->bindingValueAsString(binding); id = binding->value.compiledScriptIndex; } expressions << ExpressionChange(propertyName, binding, id, expression, url, line, column); @@ -322,20 +309,23 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, } QVariant var; - switch (binding->type) { + switch (binding->type()) { case QV4::CompiledData::Binding::Type_Script: case QV4::CompiledData::Binding::Type_Translation: case QV4::CompiledData::Binding::Type_TranslationById: Q_UNREACHABLE(); case QV4::CompiledData::Binding::Type_String: - var = binding->valueAsString(compilationUnit.data()); + var = compilationUnit->bindingValueAsString(binding); break; case QV4::CompiledData::Binding::Type_Number: - var = binding->valueAsNumber(compilationUnit->constants); + var = compilationUnit->bindingValueAsNumber(binding); break; case QV4::CompiledData::Binding::Type_Boolean: var = binding->valueAsBoolean(); break; + case QV4::CompiledData::Binding::Type_Null: + var = QVariant::fromValue(nullptr); + break; default: break; } @@ -343,19 +333,23 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, properties << qMakePair(propertyName, var); } -void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) +void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) { - for (int ii = 0; ii < props.count(); ++ii) + for (int ii = 0; ii < props.size(); ++ii) verifyList(compilationUnit, props.at(ii)); } -void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) +void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) { QQuickPropertyChangesPrivate *p = static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj)); p->bindings = bindings; p->compilationUnit = compilationUnit; p->decoded = false; + + QQmlData *data = QQmlData::get(obj); + Q_ASSERT(data && !data->wasDeleted(obj)); + data->releaseDeferredData(); } QQuickPropertyChanges::QQuickPropertyChanges() @@ -366,7 +360,7 @@ QQuickPropertyChanges::QQuickPropertyChanges() QQuickPropertyChanges::~QQuickPropertyChanges() { Q_D(QQuickPropertyChanges); - for(int ii = 0; ii < d->signalReplacements.count(); ++ii) + for(int ii = 0; ii < d->signalReplacements.size(); ++ii) delete d->signalReplacements.at(ii); } @@ -379,7 +373,10 @@ QObject *QQuickPropertyChanges::object() const void QQuickPropertyChanges::setObject(QObject *o) { Q_D(QQuickPropertyChanges); - d->object = o; + if (o != d->object) { + d->object = o; + emit objectChanged(); + } } /*! @@ -400,17 +397,20 @@ bool QQuickPropertyChanges::restoreEntryValues() const void QQuickPropertyChanges::setRestoreEntryValues(bool v) { Q_D(QQuickPropertyChanges); - d->restore = v; + if (v != d->restore) { + d->restore = v; + emit restoreEntryValuesChanged(); + } } QQmlProperty QQuickPropertyChangesPrivate::property(const QString &property) { Q_Q(QQuickPropertyChanges); - QQmlContextData *context = nullptr; - if (QQmlData *ddata = QQmlData::get(q)) - context = ddata->outerContext; - QQmlProperty prop = QQmlPropertyPrivate::create(object, property, context); + QQmlData *ddata = QQmlData::get(q); + QQmlProperty prop = QQmlPropertyPrivate::create( + object, property, ddata ? ddata->outerContext : QQmlRefPointer<QQmlContextData>(), + QQmlPropertyPrivate::InitFlag::AllowId | QQmlPropertyPrivate::InitFlag::AllowSignal); if (!prop.isValid()) { qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); return QQmlProperty(); @@ -429,7 +429,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() ActionList list; - for (int ii = 0; ii < d->properties.count(); ++ii) { + for (int ii = 0; ii < d->properties.size(); ++ii) { QQmlProperty prop = d->property(d->properties.at(ii).first); QQuickStateAction a(d->object, prop, d->properties.at(ii).first, @@ -441,7 +441,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() } } - for (int ii = 0; ii < d->signalReplacements.count(); ++ii) { + for (int ii = 0; ii < d->signalReplacements.size(); ++ii) { QQuickReplaceSignalHandler *handler = d->signalReplacements.at(ii); if (handler->property.isValid()) { @@ -451,7 +451,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() } } - for (int ii = 0; ii < d->expressions.count(); ++ii) { + for (int ii = 0; ii < d->expressions.size(); ++ii) { QQuickPropertyChangesPrivate::ExpressionChange e = d->expressions.at(ii); const QString &property = e.name; @@ -465,30 +465,36 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() a.specifiedObject = d->object; a.specifiedProperty = property; - QQmlContextData *context = QQmlContextData::get(qmlContext(this)); - - QQmlBinding *newBinding = nullptr; - if (e.binding && e.binding->isTranslationBinding()) { - newBinding = QQmlBinding::createTranslationBinding(d->compilationUnit, e.binding, object(), context); - } else if (e.id != QQmlBinding::Invalid) { - QV4::Scope scope(qmlEngine(this)->handle()); - QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(scope.engine->rootContext(), context, object())); - newBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, - d->compilationUnit->runtimeFunctions.at(e.id), object(), context, qmlContext); - } - if (!newBinding) - newBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, - e.expression, object(), context, e.url.toString(), e.line); + QQmlRefPointer<QQmlContextData> context = QQmlContextData::get(qmlContext(this)); + QV4::Scope scope(qmlEngine(this)->handle()); + QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, QV4::QmlContext::create(scope.engine->rootContext(), context, object())); if (d->isExplicit) { // in this case, we don't want to assign a binding, per se, // so we evaluate the expression and assign the result. // XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString) // so that we can avoid creating then destroying the binding in this case. + std::unique_ptr<QQmlBinding> newBinding = nullptr; + if (e.binding && e.binding->isTranslationBinding()) { + newBinding.reset(QQmlBinding::createTranslationBinding(d->compilationUnit, e.binding, object(), context)); + } else if (e.id != QQmlBinding::Invalid) { + newBinding.reset(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, d->compilationUnit->runtimeFunctions.at(e.id), object(), context, qmlCtxt)); + } else { + newBinding.reset(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, e.expression, object(), context, e.url.toString(), e.line)); + } a.toValue = newBinding->evaluate(); - delete newBinding; } else { - newBinding->setTarget(prop); + QQmlAnyBinding newBinding = nullptr; + if (e.binding && e.binding->isTranslationBinding()) { + newBinding = QQmlAnyBinding::createTranslationBinding(prop, d->compilationUnit, e.binding, object(), context); + } else if (e.id != QQmlBinding::Invalid) { + newBinding = QQmlAnyBinding::createFromFunction(prop, + d->compilationUnit->runtimeFunctions.at(e.id), + object(), context, qmlCtxt); + } else { + newBinding = QQmlAnyBinding::createFromCodeString(prop, e.expression, object(), context, e.url.toString(), e.line); + } + a.toBinding = newBinding; a.deletableToBinding = true; } @@ -528,7 +534,10 @@ bool QQuickPropertyChanges::isExplicit() const void QQuickPropertyChanges::setIsExplicit(bool e) { Q_D(QQuickPropertyChanges); - d->isExplicit = e; + if (e != d->isExplicit) { + d->isExplicit = e; + emit isExplicitChanged(); + } } bool QQuickPropertyChanges::containsValue(const QString &name) const @@ -536,9 +545,7 @@ bool QQuickPropertyChanges::containsValue(const QString &name) const Q_D(const QQuickPropertyChanges); typedef QPair<QString, QVariant> PropertyEntry; - QListIterator<PropertyEntry> propertyIterator(d->properties); - while (propertyIterator.hasNext()) { - const PropertyEntry &entry = propertyIterator.next(); + for (const PropertyEntry &entry : d->properties) { if (entry.first == name) { return true; } @@ -552,9 +559,7 @@ bool QQuickPropertyChanges::containsExpression(const QString &name) const Q_D(const QQuickPropertyChanges); typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry; - QListIterator<ExpressionEntry> expressionIterator(d->expressions); - while (expressionIterator.hasNext()) { - const ExpressionEntry &entry = expressionIterator.next(); + for (const ExpressionEntry &entry : d->expressions) { if (entry.name == name) { return true; } @@ -572,13 +577,10 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val { Q_D(QQuickPropertyChanges); typedef QPair<QString, QVariant> PropertyEntry; - typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry; - QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); - while (expressionIterator.hasNext()) { - const ExpressionEntry &entry = expressionIterator.next(); - if (entry.name == name) { - expressionIterator.remove(); + for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) { + if (it->name == name) { + d->expressions.erase(it); if (state() && state()->isStateActive()) { QQmlPropertyPrivate::removeBinding(d->property(name)); d->property(name).write(value); @@ -589,11 +591,9 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val } } - QMutableListIterator<PropertyEntry> propertyIterator(d->properties); - while (propertyIterator.hasNext()) { - PropertyEntry &entry = propertyIterator.next(); - if (entry.first == name) { - entry.second = value; + for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) { + if (it->first == name) { + it->second = value; if (state() && state()->isStateActive()) d->property(name).write(value); return; @@ -608,7 +608,7 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val action.specifiedProperty = name; action.toValue = value; - propertyIterator.insert(PropertyEntry(name, value)); + d->properties.append(PropertyEntry(name, value)); if (state() && state()->isStateActive()) { state()->addEntryToRevertList(action); QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(action.property); @@ -621,55 +621,45 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val void QQuickPropertyChanges::changeExpression(const QString &name, const QString &expression) { Q_D(QQuickPropertyChanges); - typedef QPair<QString, QVariant> PropertyEntry; typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry; bool hadValue = false; - QMutableListIterator<PropertyEntry> propertyIterator(d->properties); - while (propertyIterator.hasNext()) { - PropertyEntry &entry = propertyIterator.next(); - if (entry.first == name) { - propertyIterator.remove(); + for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) { + if (it->first == name) { + d->properties.erase(it); hadValue = true; break; } } - QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); - while (expressionIterator.hasNext()) { - ExpressionEntry &entry = expressionIterator.next(); - if (entry.name == name) { - entry.expression = expression; + for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) { + if (it->name == name) { + it->expression = expression; if (state() && state()->isStateActive()) { auto prop = d->property(name); - QQmlBinding *newBinding = QQmlBinding::create( - &QQmlPropertyPrivate::get(prop)->core, expression, object(), - QQmlContextData::get(qmlContext(this))); - newBinding->setTarget(prop); - QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor); + auto context = QQmlContextData::get(qmlContext(this)); + QString url; + int lineNumber = 0; + QQmlAnyBinding::createFromCodeString(prop, expression, object(), context, url, lineNumber).installOn(prop); } return; } } // adding a new expression. - expressionIterator.insert(ExpressionEntry(name, nullptr, QQmlBinding::Invalid, expression, QUrl(), -1, -1)); + d->expressions.append(ExpressionEntry(name, nullptr, QQmlBinding::Invalid, expression, QUrl(), -1, -1)); + const QString url; + const quint16 lineNumber = 0; if (state() && state()->isStateActive()) { if (hadValue) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name)); - if (oldBinding) { - oldBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor); + auto prop = d->property(name); + QQmlAnyBinding oldBinding = QQmlAnyBinding::takeFrom(prop); + if (oldBinding) state()->changeBindingInRevertList(object(), name, oldBinding); - } - auto prop = d->property(name); - QQmlBinding *newBinding = QQmlBinding::create( - &QQmlPropertyPrivate::get(prop)->core, expression, object(), - QQmlContextData::get(qmlContext(this))); - newBinding->setTarget(prop); - QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor); + QQmlAnyBinding::createFromCodeString(prop, expression, object(), QQmlContextData::get(qmlContext(this)), url, lineNumber).installOn(prop); } else { QQuickStateAction action; action.restore = restoreEntryValues(); @@ -678,26 +668,28 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString action.specifiedObject = object(); action.specifiedProperty = name; - QQmlBinding *newBinding = QQmlBinding::create( + QQmlAnyBinding newBinding; + if (d->isExplicit) { + newBinding = QQmlBinding::create( &QQmlPropertyPrivate::get(action.property)->core, expression, object(), QQmlContextData::get(qmlContext(this))); + } else { + const auto prop = action.property; + const auto context = QQmlContextData::get(qmlContext(this)); + newBinding = QQmlAnyBinding::createFromCodeString(prop, expression, object(), context, url, lineNumber); + } if (d->isExplicit) { // don't assign the binding, merely evaluate the expression. // XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString) // so that we can avoid creating then destroying the binding in this case. - action.toValue = newBinding->evaluate(); - delete newBinding; + action.toValue = static_cast<QQmlBinding *>(newBinding.asAbstractBinding())->evaluate(); } else { - newBinding->setTarget(action.property); + // TODO: replace binding would be more efficient for new-style properties + QQmlAnyBinding::removeBindingFrom(action.property); + newBinding.installOn(action.property); action.toBinding = newBinding; action.deletableToBinding = true; - state()->addEntryToRevertList(action); - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(action.property); - if (oldBinding) - oldBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor); - - QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor); } } } @@ -710,17 +702,13 @@ QVariant QQuickPropertyChanges::property(const QString &name) const typedef QPair<QString, QVariant> PropertyEntry; typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry; - QListIterator<PropertyEntry> propertyIterator(d->properties); - while (propertyIterator.hasNext()) { - const PropertyEntry &entry = propertyIterator.next(); + for (const PropertyEntry &entry : d->properties) { if (entry.first == name) { return entry.second; } } - QListIterator<ExpressionEntry> expressionIterator(d->expressions); - while (expressionIterator.hasNext()) { - const ExpressionEntry &entry = expressionIterator.next(); + for (const ExpressionEntry &entry : d->expressions) { if (entry.name == name) { return QVariant(entry.expression); } @@ -732,24 +720,18 @@ QVariant QQuickPropertyChanges::property(const QString &name) const void QQuickPropertyChanges::removeProperty(const QString &name) { Q_D(QQuickPropertyChanges); - typedef QPair<QString, QVariant> PropertyEntry; - typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry; - QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); - while (expressionIterator.hasNext()) { - const ExpressionEntry &entry = expressionIterator.next(); - if (entry.name == name) { - expressionIterator.remove(); + for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) { + if (it->name == name) { + d->expressions.erase(it); state()->removeEntryFromRevertList(object(), name); return; } } - QMutableListIterator<PropertyEntry> propertyIterator(d->properties); - while (propertyIterator.hasNext()) { - const PropertyEntry &entry = propertyIterator.next(); - if (entry.first == name) { - propertyIterator.remove(); + for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) { + if (it->first == name) { + d->properties.erase(it); state()->removeEntryFromRevertList(object(), name); return; } @@ -761,9 +743,7 @@ QVariant QQuickPropertyChanges::value(const QString &name) const Q_D(const QQuickPropertyChanges); typedef QPair<QString, QVariant> PropertyEntry; - QListIterator<PropertyEntry> propertyIterator(d->properties); - while (propertyIterator.hasNext()) { - const PropertyEntry &entry = propertyIterator.next(); + for (const PropertyEntry &entry : d->properties) { if (entry.first == name) { return entry.second; } @@ -777,9 +757,7 @@ QString QQuickPropertyChanges::expression(const QString &name) const Q_D(const QQuickPropertyChanges); typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry; - QListIterator<ExpressionEntry> expressionIterator(d->expressions); - while (expressionIterator.hasNext()) { - const ExpressionEntry &entry = expressionIterator.next(); + for (const ExpressionEntry &entry : d->expressions) { if (entry.name == name) { return entry.expression; } |