#include <QtCore/qvarlengtharray.h>
#include <QtQml/qjsvalue.h>
+#include <utility>
+
QT_BEGIN_NAMESPACE
+template <typename T1, typename T2>
+uint qHash(const std::pair<T1, T2> &p)
+{
+ return qHash(p.first) ^ qHash(p.second);
+}
+
using namespace QQmlVMETypes;
#define VME_EXCEPTION(desc, line) \
{
QQmlTrace trace("VME Binding Enable");
trace.event("begin binding eval");
- while (!bindValues.isEmpty()) {
- QQmlAbstractBinding *b = bindValues.pop();
- if(b) {
- b->m_mePtr = 0;
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
- }
+ size_t bindValuesRemaining = bindValues.count();
+ if (bindValuesRemaining > 0) {
+ typedef std::pair<QObject *, int> TargetProperty;
- if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return 0;
+ QSet<TargetProperty> boundProperties;
+ boundProperties.reserve(bindValuesRemaining - 1);
+
+ while (bindValuesRemaining > 0) {
+ QQmlAbstractBinding *b = bindValues.pop();
+ --bindValuesRemaining;
+
+ if (b) {
+ b->m_mePtr = 0;
+
+ TargetProperty property(std::make_pair(b->object(), b->propertyIndex()));
+ if (!boundProperties.contains(property)) {
+ // We have not assigned a binding to this property yet
+ b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+ QQmlPropertyPrivate::DontRemoveBinding);
+
+ if (bindValuesRemaining > 0) {
+ boundProperties.insert(property);
+ }
+ } else {
+ b->destroy();
+ }
+ }
+
+ if (watcher.hasRecursed() || interrupt.shouldInterrupt())
+ return 0;
+ }
}
+
bindValues.deallocate();
}
--- /dev/null
+import QtQuick 2.0
+
+QtObject {
+ property int foo1: 100
+ property int foo2: 100
+ property int foo3: { return 100; }
+ property int foo4: { return 100; }
+
+ property string bar1: 'Hello'
+ property string bar2: 'Hello'
+ property string bar3: { return 'Hello'; }
+ property string bar4: { return 'Hello'; }
+}
--- /dev/null
+import QtQuick 2.0
+
+OuterObject {
+ property bool success: false
+
+ inner.foo1: 200
+ inner.foo2: { return 200; }
+ inner.foo3: 200
+ inner.foo4: { return 200; }
+
+ inner.bar1: 'Goodbye'
+ inner.bar2: { return 'Goodbye' }
+ inner.bar3: 'Goodbye'
+ inner.bar4: { return 'Goodbye' }
+
+ Component.onCompleted: {
+ success = (inner.foo1 == 200 &&
+ inner.foo2 == 200 &&
+ inner.foo3 == 200 &&
+ inner.foo4 == 200 &&
+ inner.bar1 == 'Goodbye' &&
+ inner.bar2 == 'Goodbye' &&
+ inner.bar3 == 'Goodbye' &&
+ inner.bar4 == 'Goodbye');
+ }
+}
void restoreBinding();
void restoreBindingWithLoop();
void deletedObject();
+ void replaceBinding();
private:
QQmlEngine engine;
delete rect;
}
+void tst_qquickbinding::replaceBinding()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("replaceBinding.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj != 0);
+
+ QVERIFY(obj->property("success").toBool());
+ delete obj;
+}
+
QTEST_MAIN(tst_qquickbinding)
#include "tst_qquickbinding.moc"