aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2011-08-03 11:01:52 +1000
committerQt by Nokia <qt-info@nokia.com>2011-08-03 03:42:01 +0200
commit5084c274aac111db3f5f0c38258aa06aa9448bda (patch)
tree735d55289177451d08a8ff375b0f2f9cebf1883b
parent73aa113181fa2295729d24317c187661f740b898 (diff)
Prevent Binding from crashing when its target object is deleted.
Task-number: QTBUG-20692 Change-Id: Ia9a3d532c45baf01b8c20c7aac9ef373942a75d8 Reviewed-on: http://codereview.qt.nokia.com/2531 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Martin Jones <martin.jones@nokia.com>
-rw-r--r--src/declarative/util/qdeclarativebind.cpp21
-rw-r--r--src/qtquick1/util/qdeclarativebind.cpp3
-rw-r--r--tests/auto/declarative/qdeclarativebinding/data/deletedObject.qml24
-rw-r--r--tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp17
-rw-r--r--tests/auto/qtquick1/qdeclarativebinding/data/deletedObject.qml24
-rw-r--r--tests/auto/qtquick1/qdeclarativebinding/tst_qdeclarativebinding.cpp17
6 files changed, 98 insertions, 8 deletions
diff --git a/src/declarative/util/qdeclarativebind.cpp b/src/declarative/util/qdeclarativebind.cpp
index fa463ebef8..320bca853a 100644
--- a/src/declarative/util/qdeclarativebind.cpp
+++ b/src/declarative/util/qdeclarativebind.cpp
@@ -44,6 +44,7 @@
#include "private/qdeclarativenullablevalue_p_p.h"
#include "private/qdeclarativeproperty_p.h"
#include "private/qdeclarativebinding_p.h"
+#include "private/qdeclarativeguard_p.h"
#include <qdeclarativeengine.h>
#include <qdeclarativecontext.h>
@@ -67,7 +68,7 @@ public:
QDeclarativeNullableValue<bool> when;
bool componentComplete;
- QObject *obj;
+ QDeclarativeGuard<QObject> obj;
QString propName;
QDeclarativeNullableValue<QVariant> value;
QDeclarativeProperty prop;
@@ -196,9 +197,12 @@ QObject *QDeclarativeBind::object()
void QDeclarativeBind::setObject(QObject *obj)
{
Q_D(QDeclarativeBind);
- if (d->obj && d->obj != obj) {
- qmlInfo(this) << tr("Cannot change the object assigned to a Binding.");
- return;
+ if (d->obj && d->when.isValid() && d->when) {
+ /* if we switch the object at runtime, we need to restore the
+ previous binding on the old object before continuing */
+ d->when = false;
+ eval();
+ d->when = true;
}
d->obj = obj;
if (d->componentComplete)
@@ -220,9 +224,12 @@ QString QDeclarativeBind::property() const
void QDeclarativeBind::setProperty(const QString &p)
{
Q_D(QDeclarativeBind);
- if (!d->propName.isEmpty() && d->propName != p) {
- qmlInfo(this) << tr("Cannot change the property assigned to a Binding.");
- return;
+ if (!d->propName.isEmpty() && d->when.isValid() && d->when) {
+ /* if we switch the property name at runtime, we need to restore the
+ previous binding on the old object before continuing */
+ d->when = false;
+ eval();
+ d->when = true;
}
d->propName = p;
if (d->componentComplete)
diff --git a/src/qtquick1/util/qdeclarativebind.cpp b/src/qtquick1/util/qdeclarativebind.cpp
index 50514234a3..7afe848448 100644
--- a/src/qtquick1/util/qdeclarativebind.cpp
+++ b/src/qtquick1/util/qdeclarativebind.cpp
@@ -42,6 +42,7 @@
#include "QtQuick1/private/qdeclarativebind_p.h"
#include "QtDeclarative/private/qdeclarativenullablevalue_p_p.h"
+#include "QtDeclarative/private/qdeclarativeguard_p.h"
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecontext.h>
@@ -65,7 +66,7 @@ public:
bool when : 1;
bool componentComplete : 1;
- QObject *obj;
+ QDeclarativeGuard<QObject> obj;
QString prop;
QDeclarativeNullableValue<QVariant> value;
};
diff --git a/tests/auto/declarative/qdeclarativebinding/data/deletedObject.qml b/tests/auto/declarative/qdeclarativebinding/data/deletedObject.qml
new file mode 100644
index 0000000000..f9cf869ba3
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativebinding/data/deletedObject.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: wrapper
+ width: 400
+ height: 400
+
+ property bool activateBinding: false
+
+ Binding {
+ id: binding
+ target: Qt.createQmlObject('import QtQuick 2.0; Item { property real value: 10 }', wrapper)
+ property: "value"
+ when: activateBinding
+ value: x + y
+ }
+
+ Component.onCompleted: binding.target.destroy();
+
+// MouseArea {
+// anchors.fill: parent
+// onClicked: activateBinding = true;
+// }
+}
diff --git a/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp b/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp
index 2e64fed0ed..3effd68b39 100644
--- a/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp
+++ b/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp
@@ -62,6 +62,7 @@ private slots:
void whenAfterValue();
void restoreBinding();
void restoreBindingWithLoop();
+ void deletedObject();
private:
QDeclarativeEngine engine;
@@ -179,6 +180,22 @@ void tst_qdeclarativebinding::restoreBindingWithLoop()
delete rect;
}
+//QTBUG-20692
+void tst_qdeclarativebinding::deletedObject()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/deletedObject.qml"));
+ QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+
+ //don't crash
+ rect->setProperty("activateBinding", true);
+
+ delete rect;
+}
+
QTEST_MAIN(tst_qdeclarativebinding)
#include "tst_qdeclarativebinding.moc"
diff --git a/tests/auto/qtquick1/qdeclarativebinding/data/deletedObject.qml b/tests/auto/qtquick1/qdeclarativebinding/data/deletedObject.qml
new file mode 100644
index 0000000000..ba4c9f6f7c
--- /dev/null
+++ b/tests/auto/qtquick1/qdeclarativebinding/data/deletedObject.qml
@@ -0,0 +1,24 @@
+import QtQuick 1.0
+
+Rectangle {
+ id: wrapper
+ width: 400
+ height: 400
+
+ property bool activateBinding: false
+
+ Binding {
+ id: binding
+ target: Qt.createQmlObject('import QtQuick 1.0; Item { property real value: 10 }', wrapper)
+ property: "value"
+ when: activateBinding
+ value: x + y
+ }
+
+ Component.onCompleted: binding.target.destroy();
+
+// MouseArea {
+// anchors.fill: parent
+// onClicked: activateBinding = true;
+// }
+}
diff --git a/tests/auto/qtquick1/qdeclarativebinding/tst_qdeclarativebinding.cpp b/tests/auto/qtquick1/qdeclarativebinding/tst_qdeclarativebinding.cpp
index 776fa528cf..54ff801375 100644
--- a/tests/auto/qtquick1/qdeclarativebinding/tst_qdeclarativebinding.cpp
+++ b/tests/auto/qtquick1/qdeclarativebinding/tst_qdeclarativebinding.cpp
@@ -60,6 +60,7 @@ public:
private slots:
void binding();
void whenAfterValue();
+ void deletedObject();
private:
QDeclarativeEngine engine;
@@ -113,6 +114,22 @@ void tst_qdeclarativebinding::whenAfterValue()
delete rect;
}
+//QTBUG-20692
+void tst_qdeclarativebinding::deletedObject()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/deletedObject.qml"));
+ QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+
+ //don't crash
+ rect->setProperty("activateBinding", true);
+
+ delete rect;
+}
+
QTEST_MAIN(tst_qdeclarativebinding)
#include "tst_qdeclarativebinding.moc"