1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtQml/qqmlengine.h>
43 #include <QtQml/qqmlcomponent.h>
44 #include <QtQml/qqmlcontext.h>
45 #include <QtQml/qqmlproperty.h>
46 #include <QtQml/private/qqmlproperty_p.h>
47 #include <private/qqmlbinding_p.h>
48 #include <private/qqmlboundsignal_p.h>
49 #include <QtWidgets/QLineEdit>
50 #include <QtCore/qfileinfo.h>
51 #include <QtCore/qdir.h>
52 #include "../../shared/util.h"
55 class MyQmlObject : public QObject
62 QML_DECLARE_TYPE(MyQmlObject);
64 class MyAttached : public QObject
67 Q_PROPERTY(int foo READ foo WRITE setFoo)
69 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
71 int foo() const { return m_foo; }
72 void setFoo(int f) { m_foo = f; }
78 class MyContainer : public QObject
81 Q_PROPERTY(QQmlListProperty<MyQmlObject> children READ children)
85 QQmlListProperty<MyQmlObject> children() { return QQmlListProperty<MyQmlObject>(this, m_children); }
87 static MyAttached *qmlAttachedProperties(QObject *o) {
88 return new MyAttached(o);
92 QList<MyQmlObject*> m_children;
95 QML_DECLARE_TYPE(MyContainer);
96 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
98 class tst_qqmlproperty : public QQmlDataTest
102 tst_qqmlproperty() {}
108 void qmlmetaproperty();
109 void qmlmetaproperty_object();
110 void qmlmetaproperty_object_string();
111 void qmlmetaproperty_object_context();
112 void qmlmetaproperty_object_string_context();
121 void writeObjectToList();
122 void writeListToList();
126 void urlHandling_data();
129 void variantMapHandling_data();
130 void variantMapHandling();
133 void crashOnValueProperty();
134 void aliasPropertyBindings();
136 void assignEmptyVariantMap();
137 void warnOnInvalidBinding();
138 void registeredCompositeTypeProperty();
145 void tst_qqmlproperty::qmlmetaproperty()
149 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
150 QVERIFY(binding != 0);
151 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
152 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
153 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
155 QObject *obj = new QObject;
157 QCOMPARE(prop.name(), QString());
158 QCOMPARE(prop.read(), QVariant());
159 QCOMPARE(prop.write(QVariant()), false);
160 QCOMPARE(prop.hasNotifySignal(), false);
161 QCOMPARE(prop.needsNotifySignal(), false);
162 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
163 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
164 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
165 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
166 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
167 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
168 QVERIFY(!prop.method().isValid());
169 QCOMPARE(prop.type(), QQmlProperty::Invalid);
170 QCOMPARE(prop.isProperty(), false);
171 QCOMPARE(prop.isWritable(), false);
172 QCOMPARE(prop.isDesignable(), false);
173 QCOMPARE(prop.isResettable(), false);
174 QCOMPARE(prop.isSignalProperty(), false);
175 QCOMPARE(prop.isValid(), false);
176 QCOMPARE(prop.object(), (QObject *)0);
177 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
178 QCOMPARE(prop.propertyType(), 0);
179 QCOMPARE(prop.propertyTypeName(), (const char *)0);
180 QVERIFY(prop.property().name() == 0);
181 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
182 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
183 QVERIFY(binding == 0);
184 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
185 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
186 QVERIFY(sigExprWatcher.wasDeleted());
187 QCOMPARE(prop.index(), -1);
188 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
193 // 1 = equal, 0 = unknown, -1 = not equal.
194 static int compareVariantAndListReference(const QVariant &v, QQmlListReference &r)
196 if (QLatin1String(v.typeName()) != QLatin1String("QQmlListReference"))
199 QQmlListReference lhs = v.value<QQmlListReference>();
200 if (lhs.isValid() != r.isValid())
203 if (lhs.canCount() != r.canCount())
206 if (!lhs.canCount()) {
207 if (lhs.canAt() != r.canAt())
208 return -1; // not equal.
209 return 0; // not sure if they're equal or not, and no way to tell.
212 // if we get here, we must be able to count.
213 if (lhs.count() != r.count())
216 if (lhs.canAt() != r.canAt())
220 return 0; // can count, but can't check element equality.
222 for (int i = 0; i < lhs.count(); ++i) {
223 if (lhs.at(i) != r.at(i)) {
224 return -1; // different elements :. not equal.
231 void tst_qqmlproperty::registeredCompositeTypeProperty()
233 // Composite type properties
236 QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml"));
237 QObject *obj = component.create();
240 // create property accessors and check types.
241 QQmlProperty p1(obj, "first");
242 QQmlProperty p2(obj, "second");
243 QQmlProperty p3(obj, "third");
244 QQmlProperty p1e(obj, "first", &engine);
245 QQmlProperty p2e(obj, "second", &engine);
246 QQmlProperty p3e(obj, "third", &engine);
247 QVERIFY(p1.propertyType() == p2.propertyType());
248 QVERIFY(p1.propertyType() != p3.propertyType());
250 // check that the values are retrievable from CPP
251 QVariant first = obj->property("first");
252 QVariant second = obj->property("second");
253 QVariant third = obj->property("third");
254 QVERIFY(first.isValid());
255 QVERIFY(second.isValid());
256 QVERIFY(third.isValid());
257 // ensure that conversion from qobject-derived-ptr to qobject-ptr works.
258 QVERIFY(first.value<QObject*>());
259 QVERIFY(second.value<QObject*>());
260 QVERIFY(third.value<QObject*>());
262 // check that the values retrieved via QQmlProperty match those retrieved via QMetaProperty::read().
263 QCOMPARE(p1.read().value<QObject*>(), first.value<QObject*>());
264 QCOMPARE(p2.read().value<QObject*>(), second.value<QObject*>());
265 QCOMPARE(p3.read().value<QObject*>(), third.value<QObject*>());
266 QCOMPARE(p1e.read().value<QObject*>(), first.value<QObject*>());
267 QCOMPARE(p2e.read().value<QObject*>(), second.value<QObject*>());
268 QCOMPARE(p3e.read().value<QObject*>(), third.value<QObject*>());
273 // List-of-composite-type type properties
276 QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml"));
277 QObject *obj = component.create();
280 // create list property accessors and check types
281 QQmlProperty lp1e(obj, "fclist", &engine);
282 QQmlProperty lp2e(obj, "sclistOne", &engine);
283 QQmlProperty lp3e(obj, "sclistTwo", &engine);
284 QVERIFY(lp1e.propertyType() != lp2e.propertyType());
285 QVERIFY(lp2e.propertyType() == lp3e.propertyType());
287 // check that the list values are retrievable from CPP
288 QVariant firstList = obj->property("fclist");
289 QVariant secondList = obj->property("sclistOne");
290 QVariant thirdList = obj->property("sclistTwo");
291 QVERIFY(firstList.isValid());
292 QVERIFY(secondList.isValid());
293 QVERIFY(thirdList.isValid());
295 // check that the value returned by QQmlProperty::read() is equivalent to the list reference.
296 QQmlListReference r1(obj, "fclist", &engine);
297 QQmlListReference r2(obj, "sclistOne", &engine);
298 QQmlListReference r3(obj, "sclistTwo", &engine);
299 QCOMPARE(compareVariantAndListReference(lp1e.read(), r1), 1);
300 QCOMPARE(compareVariantAndListReference(lp2e.read(), r2), 1);
301 QCOMPARE(compareVariantAndListReference(lp3e.read(), r3), 1);
307 class PropertyObject : public QObject
310 Q_PROPERTY(int defaultProperty READ defaultProperty)
311 Q_PROPERTY(QRect rectProperty READ rectProperty)
312 Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
313 Q_PROPERTY(QUrl url READ url WRITE setUrl)
314 Q_PROPERTY(QVariantMap variantMap READ variantMap WRITE setVariantMap)
315 Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
316 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
317 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
319 Q_CLASSINFO("DefaultProperty", "defaultProperty")
321 PropertyObject() : m_resetProperty(9) {}
323 int defaultProperty() { return 10; }
324 QRect rectProperty() { return QRect(10, 10, 1, 209); }
326 QRect wrectProperty() { return m_rect; }
327 void setWRectProperty(const QRect &r) { m_rect = r; }
329 QUrl url() { return m_url; }
330 void setUrl(const QUrl &u) { m_url = u; }
332 QVariantMap variantMap() const { return m_variantMap; }
333 void setVariantMap(const QVariantMap &variantMap) { m_variantMap = variantMap; }
335 int resettableProperty() const { return m_resetProperty; }
336 void setResettableProperty(int r) { m_resetProperty = r; }
337 void resetProperty() { m_resetProperty = 9; }
339 int propertyWithNotify() const { return m_propertyWithNotify; }
340 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
342 MyQmlObject *qmlObject() { return &m_qmlObject; }
346 void oddlyNamedNotifySignal();
352 QVariantMap m_variantMap;
353 int m_propertyWithNotify;
354 MyQmlObject m_qmlObject;
357 QML_DECLARE_TYPE(PropertyObject);
359 void tst_qqmlproperty::qmlmetaproperty_object()
361 QObject object; // Has no default property
362 PropertyObject dobject; // Has default property
365 QQmlProperty prop(&object);
367 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
368 QVERIFY(binding != 0);
369 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
370 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
371 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
373 QObject *obj = new QObject;
375 QCOMPARE(prop.name(), QString());
376 QCOMPARE(prop.read(), QVariant());
377 QCOMPARE(prop.write(QVariant()), false);
378 QCOMPARE(prop.hasNotifySignal(), false);
379 QCOMPARE(prop.needsNotifySignal(), false);
380 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
381 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
382 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
383 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
384 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
385 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
386 QVERIFY(!prop.method().isValid());
387 QCOMPARE(prop.type(), QQmlProperty::Invalid);
388 QCOMPARE(prop.isProperty(), false);
389 QCOMPARE(prop.isWritable(), false);
390 QCOMPARE(prop.isDesignable(), false);
391 QCOMPARE(prop.isResettable(), false);
392 QCOMPARE(prop.isSignalProperty(), false);
393 QCOMPARE(prop.isValid(), false);
394 QCOMPARE(prop.object(), (QObject *)0);
395 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
396 QCOMPARE(prop.propertyType(), 0);
397 QCOMPARE(prop.propertyTypeName(), (const char *)0);
398 QVERIFY(prop.property().name() == 0);
399 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
400 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
401 QVERIFY(binding == 0);
402 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
403 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
404 QVERIFY(sigExprWatcher.wasDeleted());
405 QCOMPARE(prop.index(), -1);
406 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
412 QQmlProperty prop(&dobject);
414 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
415 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
416 QVERIFY(binding != 0);
417 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
418 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
419 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
421 QObject *obj = new QObject;
423 QCOMPARE(prop.name(), QString("defaultProperty"));
424 QCOMPARE(prop.read(), QVariant(10));
425 QCOMPARE(prop.write(QVariant()), false);
426 QCOMPARE(prop.hasNotifySignal(), false);
427 QCOMPARE(prop.needsNotifySignal(), true);
428 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
429 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
430 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
431 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
432 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
433 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
434 QVERIFY(!prop.method().isValid());
435 QCOMPARE(prop.type(), QQmlProperty::Property);
436 QCOMPARE(prop.isProperty(), true);
437 QCOMPARE(prop.isWritable(), false);
438 QCOMPARE(prop.isDesignable(), true);
439 QCOMPARE(prop.isResettable(), false);
440 QCOMPARE(prop.isSignalProperty(), false);
441 QCOMPARE(prop.isValid(), true);
442 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
443 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
444 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
445 QCOMPARE(prop.propertyTypeName(), "int");
446 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
447 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
448 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
449 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
450 QVERIFY(binding != 0);
451 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
452 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
453 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
454 QVERIFY(sigExprWatcher.wasDeleted());
455 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
456 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
462 void tst_qqmlproperty::qmlmetaproperty_object_string()
465 PropertyObject dobject;
468 QQmlProperty prop(&object, QString("defaultProperty"));
470 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
471 QVERIFY(binding != 0);
472 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
473 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
474 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
476 QObject *obj = new QObject;
478 QCOMPARE(prop.name(), QString());
479 QCOMPARE(prop.read(), QVariant());
480 QCOMPARE(prop.write(QVariant()), false);
481 QCOMPARE(prop.hasNotifySignal(), false);
482 QCOMPARE(prop.needsNotifySignal(), false);
483 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
484 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
485 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
486 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
487 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
488 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
489 QVERIFY(!prop.method().isValid());
490 QCOMPARE(prop.type(), QQmlProperty::Invalid);
491 QCOMPARE(prop.isProperty(), false);
492 QCOMPARE(prop.isWritable(), false);
493 QCOMPARE(prop.isDesignable(), false);
494 QCOMPARE(prop.isResettable(), false);
495 QCOMPARE(prop.isSignalProperty(), false);
496 QCOMPARE(prop.isValid(), false);
497 QCOMPARE(prop.object(), (QObject *)0);
498 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
499 QCOMPARE(prop.propertyType(), 0);
500 QCOMPARE(prop.propertyTypeName(), (const char *)0);
501 QVERIFY(prop.property().name() == 0);
502 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
503 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
504 QVERIFY(binding == 0);
505 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
506 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
507 QVERIFY(sigExprWatcher.wasDeleted());
508 QCOMPARE(prop.index(), -1);
509 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
515 QQmlProperty prop(&dobject, QString("defaultProperty"));
517 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
518 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
519 QVERIFY(binding != 0);
520 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
521 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
522 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
524 QObject *obj = new QObject;
526 QCOMPARE(prop.name(), QString("defaultProperty"));
527 QCOMPARE(prop.read(), QVariant(10));
528 QCOMPARE(prop.write(QVariant()), false);
529 QCOMPARE(prop.hasNotifySignal(), false);
530 QCOMPARE(prop.needsNotifySignal(), true);
531 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
532 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
533 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
534 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
535 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
536 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
537 QVERIFY(!prop.method().isValid());
538 QCOMPARE(prop.type(), QQmlProperty::Property);
539 QCOMPARE(prop.isProperty(), true);
540 QCOMPARE(prop.isWritable(), false);
541 QCOMPARE(prop.isDesignable(), true);
542 QCOMPARE(prop.isResettable(), false);
543 QCOMPARE(prop.isSignalProperty(), false);
544 QCOMPARE(prop.isValid(), true);
545 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
546 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
547 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
548 QCOMPARE(prop.propertyTypeName(), "int");
549 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
550 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
551 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
552 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
553 QVERIFY(binding != 0);
554 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
555 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
556 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
557 QVERIFY(sigExprWatcher.wasDeleted());
558 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
559 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
565 QQmlProperty prop(&dobject, QString("onClicked"));
567 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
568 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
569 QVERIFY(binding != 0);
570 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
571 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
572 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
574 QObject *obj = new QObject;
576 QCOMPARE(prop.name(), QString("onClicked"));
577 QCOMPARE(prop.read(), QVariant());
578 QCOMPARE(prop.write(QVariant("Hello")), false);
579 QCOMPARE(prop.hasNotifySignal(), false);
580 QCOMPARE(prop.needsNotifySignal(), false);
581 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
582 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
583 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
584 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
585 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
586 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
587 QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()"));
588 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
589 QCOMPARE(prop.isProperty(), false);
590 QCOMPARE(prop.isWritable(), false);
591 QCOMPARE(prop.isDesignable(), false);
592 QCOMPARE(prop.isResettable(), false);
593 QCOMPARE(prop.isSignalProperty(), true);
594 QCOMPARE(prop.isValid(), true);
595 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
596 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
597 QCOMPARE(prop.propertyType(), 0);
598 QCOMPARE(prop.propertyTypeName(), (const char *)0);
599 QCOMPARE(prop.property().name(), (const char *)0);
600 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
601 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
602 QVERIFY(binding == 0);
603 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
604 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
605 QVERIFY(!sigExprWatcher.wasDeleted());
606 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
607 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
608 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
614 QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
616 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
617 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
618 QVERIFY(binding != 0);
619 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
620 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
621 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
623 QObject *obj = new QObject;
625 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
626 QCOMPARE(prop.read(), QVariant());
627 QCOMPARE(prop.write(QVariant("Hello")), false);
628 QCOMPARE(prop.hasNotifySignal(), false);
629 QCOMPARE(prop.needsNotifySignal(), false);
630 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
631 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
632 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
633 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
634 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
635 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
636 QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()"));
637 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
638 QCOMPARE(prop.isProperty(), false);
639 QCOMPARE(prop.isWritable(), false);
640 QCOMPARE(prop.isDesignable(), false);
641 QCOMPARE(prop.isResettable(), false);
642 QCOMPARE(prop.isSignalProperty(), true);
643 QCOMPARE(prop.isValid(), true);
644 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
645 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
646 QCOMPARE(prop.propertyType(), 0);
647 QCOMPARE(prop.propertyTypeName(), (const char *)0);
648 QCOMPARE(prop.property().name(), (const char *)0);
649 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
650 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
651 QVERIFY(binding == 0);
652 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
653 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
654 QVERIFY(!sigExprWatcher.wasDeleted());
655 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
656 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
657 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
663 void tst_qqmlproperty::qmlmetaproperty_object_context()
665 QObject object; // Has no default property
666 PropertyObject dobject; // Has default property
669 QQmlProperty prop(&object, engine.rootContext());
671 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
672 QVERIFY(binding != 0);
673 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
674 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
675 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
677 QObject *obj = new QObject;
679 QCOMPARE(prop.name(), QString());
680 QCOMPARE(prop.read(), QVariant());
681 QCOMPARE(prop.write(QVariant()), false);
682 QCOMPARE(prop.hasNotifySignal(), false);
683 QCOMPARE(prop.needsNotifySignal(), false);
684 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
685 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
686 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
687 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
688 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
689 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
690 QVERIFY(!prop.method().isValid());
691 QCOMPARE(prop.type(), QQmlProperty::Invalid);
692 QCOMPARE(prop.isProperty(), false);
693 QCOMPARE(prop.isWritable(), false);
694 QCOMPARE(prop.isDesignable(), false);
695 QCOMPARE(prop.isResettable(), false);
696 QCOMPARE(prop.isSignalProperty(), false);
697 QCOMPARE(prop.isValid(), false);
698 QCOMPARE(prop.object(), (QObject *)0);
699 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
700 QCOMPARE(prop.propertyType(), 0);
701 QCOMPARE(prop.propertyTypeName(), (const char *)0);
702 QVERIFY(prop.property().name() == 0);
703 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
704 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
705 QVERIFY(binding == 0);
706 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
707 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
708 QVERIFY(sigExprWatcher.wasDeleted());
709 QCOMPARE(prop.index(), -1);
710 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
716 QQmlProperty prop(&dobject, engine.rootContext());
718 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
719 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
720 QVERIFY(binding != 0);
721 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
722 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
723 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
725 QObject *obj = new QObject;
727 QCOMPARE(prop.name(), QString("defaultProperty"));
728 QCOMPARE(prop.read(), QVariant(10));
729 QCOMPARE(prop.write(QVariant()), false);
730 QCOMPARE(prop.hasNotifySignal(), false);
731 QCOMPARE(prop.needsNotifySignal(), true);
732 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
733 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
734 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
735 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
736 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
737 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
738 QVERIFY(!prop.method().isValid());
739 QCOMPARE(prop.type(), QQmlProperty::Property);
740 QCOMPARE(prop.isProperty(), true);
741 QCOMPARE(prop.isWritable(), false);
742 QCOMPARE(prop.isDesignable(), true);
743 QCOMPARE(prop.isResettable(), false);
744 QCOMPARE(prop.isSignalProperty(), false);
745 QCOMPARE(prop.isValid(), true);
746 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
747 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
748 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
749 QCOMPARE(prop.propertyTypeName(), "int");
750 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
751 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
752 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
753 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
754 QVERIFY(binding != 0);
755 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
756 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
757 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
758 QVERIFY(sigExprWatcher.wasDeleted());
759 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
760 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
766 void tst_qqmlproperty::qmlmetaproperty_object_string_context()
769 PropertyObject dobject;
772 QQmlProperty prop(&object, QString("defaultProperty"), engine.rootContext());
774 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
775 QVERIFY(binding != 0);
776 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
777 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
778 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
780 QObject *obj = new QObject;
782 QCOMPARE(prop.name(), QString());
783 QCOMPARE(prop.read(), QVariant());
784 QCOMPARE(prop.write(QVariant()), false);
785 QCOMPARE(prop.hasNotifySignal(), false);
786 QCOMPARE(prop.needsNotifySignal(), false);
787 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
788 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
789 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
790 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
791 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
792 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
793 QVERIFY(!prop.method().isValid());
794 QCOMPARE(prop.type(), QQmlProperty::Invalid);
795 QCOMPARE(prop.isProperty(), false);
796 QCOMPARE(prop.isWritable(), false);
797 QCOMPARE(prop.isDesignable(), false);
798 QCOMPARE(prop.isResettable(), false);
799 QCOMPARE(prop.isSignalProperty(), false);
800 QCOMPARE(prop.isValid(), false);
801 QCOMPARE(prop.object(), (QObject *)0);
802 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
803 QCOMPARE(prop.propertyType(), 0);
804 QCOMPARE(prop.propertyTypeName(), (const char *)0);
805 QVERIFY(prop.property().name() == 0);
806 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
807 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
808 QVERIFY(binding == 0);
809 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
810 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
811 QVERIFY(sigExprWatcher.wasDeleted());
812 QCOMPARE(prop.index(), -1);
813 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
819 QQmlProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
821 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
822 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
823 QVERIFY(binding != 0);
824 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
825 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
826 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
828 QObject *obj = new QObject;
830 QCOMPARE(prop.name(), QString("defaultProperty"));
831 QCOMPARE(prop.read(), QVariant(10));
832 QCOMPARE(prop.write(QVariant()), false);
833 QCOMPARE(prop.hasNotifySignal(), false);
834 QCOMPARE(prop.needsNotifySignal(), true);
835 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
836 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
837 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
838 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
839 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
840 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
841 QVERIFY(!prop.method().isValid());
842 QCOMPARE(prop.type(), QQmlProperty::Property);
843 QCOMPARE(prop.isProperty(), true);
844 QCOMPARE(prop.isWritable(), false);
845 QCOMPARE(prop.isDesignable(), true);
846 QCOMPARE(prop.isResettable(), false);
847 QCOMPARE(prop.isSignalProperty(), false);
848 QCOMPARE(prop.isValid(), true);
849 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
850 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
851 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
852 QCOMPARE(prop.propertyTypeName(), "int");
853 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
854 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
855 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
856 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
857 QVERIFY(binding != 0);
858 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
859 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
860 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
861 QVERIFY(sigExprWatcher.wasDeleted());
862 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
863 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
869 QQmlProperty prop(&dobject, QString("onClicked"), engine.rootContext());
871 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
872 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
873 QVERIFY(binding != 0);
874 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
875 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
876 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
878 QObject *obj = new QObject;
880 QCOMPARE(prop.name(), QString("onClicked"));
881 QCOMPARE(prop.read(), QVariant());
882 QCOMPARE(prop.write(QVariant("Hello")), false);
883 QCOMPARE(prop.hasNotifySignal(), false);
884 QCOMPARE(prop.needsNotifySignal(), false);
885 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
886 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
887 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
888 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
889 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
890 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
891 QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()"));
892 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
893 QCOMPARE(prop.isProperty(), false);
894 QCOMPARE(prop.isWritable(), false);
895 QCOMPARE(prop.isDesignable(), false);
896 QCOMPARE(prop.isResettable(), false);
897 QCOMPARE(prop.isSignalProperty(), true);
898 QCOMPARE(prop.isValid(), true);
899 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
900 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
901 QCOMPARE(prop.propertyType(), 0);
902 QCOMPARE(prop.propertyTypeName(), (const char *)0);
903 QCOMPARE(prop.property().name(), (const char *)0);
904 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
905 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
906 QVERIFY(binding == 0);
907 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
908 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
909 QVERIFY(!sigExprWatcher.wasDeleted());
910 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
911 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
912 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
918 QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
920 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
921 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
922 QVERIFY(binding != 0);
923 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
924 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
925 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
927 QObject *obj = new QObject;
929 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
930 QCOMPARE(prop.read(), QVariant());
931 QCOMPARE(prop.write(QVariant("Hello")), false);
932 QCOMPARE(prop.hasNotifySignal(), false);
933 QCOMPARE(prop.needsNotifySignal(), false);
934 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
935 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
936 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
937 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
938 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
939 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
940 QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()"));
941 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
942 QCOMPARE(prop.isProperty(), false);
943 QCOMPARE(prop.isWritable(), false);
944 QCOMPARE(prop.isDesignable(), false);
945 QCOMPARE(prop.isResettable(), false);
946 QCOMPARE(prop.isSignalProperty(), true);
947 QCOMPARE(prop.isValid(), true);
948 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
949 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
950 QCOMPARE(prop.propertyType(), 0);
951 QCOMPARE(prop.propertyTypeName(), (const char *)0);
952 QCOMPARE(prop.property().name(), (const char *)0);
953 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
954 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
955 QVERIFY(binding == 0);
956 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
957 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
958 QVERIFY(!sigExprWatcher.wasDeleted());
959 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
960 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
961 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
967 void tst_qqmlproperty::name()
971 QCOMPARE(p.name(), QString());
977 QCOMPARE(p.name(), QString("defaultProperty"));
982 QQmlProperty p(&o, QString("objectName"));
983 QCOMPARE(p.name(), QString("objectName"));
988 QQmlProperty p(&o, "onClicked");
989 QCOMPARE(p.name(), QString("onClicked"));
994 QQmlProperty p(&o, "onClicked");
995 QCOMPARE(p.name(), QString());
1000 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1001 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
1006 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1007 QCOMPARE(p.name(), QString());
1012 QQmlProperty p(&o, "foo");
1013 QCOMPARE(p.name(), QString());
1017 QQmlProperty p(0, "foo");
1018 QCOMPARE(p.name(), QString());
1023 QQmlProperty p(&o, "rectProperty");
1024 QCOMPARE(p.name(), QString("rectProperty"));
1029 QQmlProperty p(&o, "rectProperty.x");
1030 QCOMPARE(p.name(), QString("rectProperty.x"));
1035 QQmlProperty p(&o, "rectProperty.foo");
1036 QCOMPARE(p.name(), QString());
1040 void tst_qqmlproperty::read()
1045 QCOMPARE(p.read(), QVariant());
1052 QCOMPARE(p.read(), QVariant(10));
1055 // Invalid default prop
1059 QCOMPARE(p.read(), QVariant());
1062 // Value prop by name
1066 QQmlProperty p(&o, "objectName");
1067 QCOMPARE(p.read(), QVariant(QString()));
1069 o.setObjectName("myName");
1071 QCOMPARE(p.read(), QVariant("myName"));
1074 // Value prop by name (static)
1078 QCOMPARE(QQmlProperty::read(&o, "objectName"), QVariant(QString()));
1080 o.setObjectName("myName");
1082 QCOMPARE(QQmlProperty::read(&o, "objectName"), QVariant("myName"));
1088 QQmlProperty p(&o, "rectProperty.x");
1089 QCOMPARE(p.read(), QVariant(10));
1092 // Invalid value-type prop
1095 QQmlProperty p(&o, "rectProperty.foo");
1096 QCOMPARE(p.read(), QVariant());
1102 QQmlProperty p(&o, "onClicked");
1103 QCOMPARE(p.read(), QVariant());
1105 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1106 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1108 QCOMPARE(p.read(), QVariant());
1111 // Automatic signal property
1114 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1115 QCOMPARE(p.read(), QVariant());
1117 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1118 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1120 QCOMPARE(p.read(), QVariant());
1125 PropertyObject *o = new PropertyObject;
1126 QQmlProperty p(o, "rectProperty.x");
1127 QCOMPARE(p.read(), QVariant(10));
1129 QCOMPARE(p.read(), QVariant());
1135 QQmlProperty p(&o, "qmlObject");
1136 QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
1137 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
1138 QVariant v = p.read();
1139 QVERIFY(v.userType() == QMetaType::QObjectStar);
1140 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1143 QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1144 QObject *object = component.create();
1145 QVERIFY(object != 0);
1147 QQmlProperty p(object, "test", &engine);
1149 QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
1150 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1152 QVariant v = p.read();
1153 QVERIFY(v.userType() == QMetaType::QObjectStar);
1154 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1155 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1158 QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1159 QObject *object = component.create();
1160 QVERIFY(object != 0);
1162 QVariant v = QQmlProperty::read(object, "test", &engine);
1163 QVERIFY(v.userType() == QMetaType::QObjectStar);
1164 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1165 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1168 // Attached property
1170 QQmlComponent component(&engine);
1171 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1172 QObject *object = component.create();
1173 QVERIFY(object != 0);
1175 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1176 QCOMPARE(p.read(), QVariant(13));
1180 QQmlComponent component(&engine);
1181 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1182 QObject *object = component.create();
1183 QVERIFY(object != 0);
1185 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1186 QCOMPARE(p.read(), QVariant(10));
1190 QQmlComponent component(&engine);
1191 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1192 QObject *object = component.create();
1193 QVERIFY(object != 0);
1195 QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1196 QCOMPARE(p.read(), QVariant(10));
1200 QQmlComponent component(&engine);
1201 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1202 QObject *object = component.create();
1203 QVERIFY(object != 0);
1205 QCOMPARE(QQmlProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1210 void tst_qqmlproperty::write()
1215 QCOMPARE(p.write(QVariant(10)), false);
1218 // Read-only default prop
1222 QCOMPARE(p.write(QVariant(10)), false);
1225 // Invalid default prop
1229 QCOMPARE(p.write(QVariant(10)), false);
1232 // Read-only prop by name
1235 QQmlProperty p(&o, QString("defaultProperty"));
1236 QCOMPARE(p.write(QVariant(10)), false);
1239 // Writable prop by name
1242 QQmlProperty p(&o, QString("objectName"));
1243 QCOMPARE(o.objectName(), QString());
1244 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1245 QCOMPARE(o.objectName(), QString("myName"));
1248 // Writable prop by name (static)
1251 QCOMPARE(QQmlProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1252 QCOMPARE(o.objectName(), QString("myName"));
1257 PropertyObject *o = new PropertyObject;
1258 QQmlProperty p(o, QString("objectName"));
1259 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1260 QCOMPARE(o->objectName(), QString("myName"));
1264 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1270 QQmlProperty p(&o, "onClicked");
1271 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1273 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1274 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1276 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1278 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1281 // Automatic signal property
1284 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1285 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1287 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1288 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1290 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1292 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1295 // Value-type property
1298 QQmlProperty p(&o, "wrectProperty");
1300 QCOMPARE(o.wrectProperty(), QRect());
1301 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1302 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1304 QQmlProperty p2(&o, "wrectProperty.x");
1305 QCOMPARE(p2.read(), QVariant(1));
1306 QCOMPARE(p2.write(QVariant(6)), true);
1307 QCOMPARE(p2.read(), QVariant(6));
1308 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1314 QQmlProperty p(&o, "url");
1316 QCOMPARE(p.write(QUrl("main.qml")), true);
1317 QCOMPARE(o.url(), QUrl("main.qml"));
1319 QQmlProperty p2(&o, "url", engine.rootContext());
1321 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1322 QVERIFY(result != QUrl("main.qml"));
1324 QCOMPARE(p2.write(QUrl("main.qml")), true);
1325 QCOMPARE(o.url(), result);
1330 QCOMPARE(QQmlProperty::write(&o, "url", QUrl("main.qml")), true);
1331 QCOMPARE(o.url(), QUrl("main.qml"));
1333 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1334 QVERIFY(result != QUrl("main.qml"));
1336 QCOMPARE(QQmlProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1337 QCOMPARE(o.url(), result);
1340 // VariantMap-property
1342 vm.insert("key", "value");
1346 QQmlProperty p(&o, "variantMap");
1348 QCOMPARE(p.write(vm), true);
1349 QCOMPARE(o.variantMap(), vm);
1351 QQmlProperty p2(&o, "variantMap", engine.rootContext());
1353 QCOMPARE(p2.write(vm), true);
1354 QCOMPARE(o.variantMap(), vm);
1359 QCOMPARE(QQmlProperty::write(&o, "variantMap", vm), true);
1360 QCOMPARE(o.variantMap(), vm);
1362 QCOMPARE(QQmlProperty::write(&o, "variantMap", vm, engine.rootContext()), true);
1363 QCOMPARE(o.variantMap(), vm);
1366 // Attached property
1368 QQmlComponent component(&engine);
1369 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1370 QObject *object = component.create();
1371 QVERIFY(object != 0);
1373 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1374 p.write(QVariant(99));
1375 QCOMPARE(p.read(), QVariant(99));
1379 QQmlComponent component(&engine);
1380 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1381 QObject *object = component.create();
1382 QVERIFY(object != 0);
1384 QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1385 p.write(QVariant(99));
1386 QCOMPARE(p.read(), QVariant(99));
1391 void tst_qqmlproperty::reset()
1396 QCOMPARE(p.isResettable(), false);
1397 QCOMPARE(p.reset(), false);
1400 // Read-only default prop
1404 QCOMPARE(p.isResettable(), false);
1405 QCOMPARE(p.reset(), false);
1408 // Invalid default prop
1412 QCOMPARE(p.isResettable(), false);
1413 QCOMPARE(p.reset(), false);
1416 // Non-resettable-only prop by name
1419 QQmlProperty p(&o, QString("defaultProperty"));
1420 QCOMPARE(p.isResettable(), false);
1421 QCOMPARE(p.reset(), false);
1424 // Resettable prop by name
1427 QQmlProperty p(&o, QString("resettableProperty"));
1429 QCOMPARE(p.read(), QVariant(9));
1430 QCOMPARE(p.write(QVariant(11)), true);
1431 QCOMPARE(p.read(), QVariant(11));
1433 QCOMPARE(p.isResettable(), true);
1434 QCOMPARE(p.reset(), true);
1436 QCOMPARE(p.read(), QVariant(9));
1441 PropertyObject *o = new PropertyObject;
1443 QQmlProperty p(o, QString("resettableProperty"));
1445 QCOMPARE(p.isResettable(), true);
1446 QCOMPARE(p.reset(), true);
1450 QCOMPARE(p.isResettable(), false);
1451 QCOMPARE(p.reset(), false);
1457 QQmlProperty p(&o, "onClicked");
1459 QCOMPARE(p.isResettable(), false);
1460 QCOMPARE(p.reset(), false);
1463 // Automatic signal property
1466 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1468 QCOMPARE(p.isResettable(), false);
1469 QCOMPARE(p.reset(), false);
1473 void tst_qqmlproperty::writeObjectToList()
1475 QQmlComponent containerComponent(&engine);
1476 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1477 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1478 QVERIFY(container != 0);
1479 QQmlListReference list(container, "children");
1480 QVERIFY(list.count() == 1);
1482 MyQmlObject *object = new MyQmlObject;
1483 QQmlProperty prop(container, "children");
1484 prop.write(qVariantFromValue(object));
1485 QCOMPARE(list.count(), 1);
1486 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1489 void tst_qqmlproperty::writeListToList()
1491 QQmlComponent containerComponent(&engine);
1492 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1493 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1494 QVERIFY(container != 0);
1495 QQmlListReference list(container, "children");
1496 QVERIFY(list.count() == 1);
1498 QList<QObject*> objList;
1499 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1500 QQmlProperty prop(container, "children");
1501 prop.write(qVariantFromValue(objList));
1502 QCOMPARE(list.count(), 4);
1504 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1505 /*QList<MyQmlObject*> typedObjList;
1506 typedObjList << new MyQmlObject();
1507 prop.write(qVariantFromValue(&typedObjList));
1508 QCOMPARE(container->children()->size(), 1);*/
1511 void tst_qqmlproperty::urlHandling_data()
1513 QTest::addColumn<QByteArray>("input");
1514 QTest::addColumn<QString>("scheme");
1515 QTest::addColumn<QString>("path");
1516 QTest::addColumn<QByteArray>("encoded");
1518 QTest::newRow("unspecifiedFile")
1519 << QByteArray("main.qml")
1521 << QString("main.qml")
1522 << QByteArray("main.qml");
1524 QTest::newRow("specifiedFile")
1525 << QByteArray("file:///main.qml")
1527 << QString("/main.qml")
1528 << QByteArray("file:///main.qml");
1530 QTest::newRow("httpFile")
1531 << QByteArray("http://www.example.com/main.qml")
1533 << QString("/main.qml")
1534 << QByteArray("http://www.example.com/main.qml");
1536 QTest::newRow("pathFile")
1537 << QByteArray("http://www.example.com/resources/main.qml")
1539 << QString("/resources/main.qml")
1540 << QByteArray("http://www.example.com/resources/main.qml");
1542 QTest::newRow("encodableName")
1543 << QByteArray("http://www.example.com/main file.qml")
1545 << QString("/main file.qml")
1546 << QByteArray("http://www.example.com/main%20file.qml");
1548 QTest::newRow("preencodedName")
1549 << QByteArray("http://www.example.com/resources%7Cmain%20file.qml")
1551 << QString("/resources|main file.qml")
1552 << QByteArray("http://www.example.com/resources%7Cmain%20file.qml");
1554 QTest::newRow("encodableQuery")
1555 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now working?")
1557 << QString("/main.qml")
1558 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now%20working?");
1560 QTest::newRow("preencodedQuery")
1561 << QByteArray("http://www.example.com/main.qml?type=text%2Fqml&comment=now working%3F")
1563 << QString("/main.qml")
1564 << QByteArray("http://www.example.com/main.qml?type=text%2Fqml&comment=now%20working%3F");
1566 QTest::newRow("encodableFragment")
1567 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000|volume+50%")
1569 << QString("/main.qml")
1570 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume+50%25");
1572 QTest::newRow("improperlyEncodedFragment")
1573 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume%2B50%")
1575 << QString("/main.qml")
1576 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%257Cvolume%252B50%25");
1579 void tst_qqmlproperty::urlHandling()
1581 QFETCH(QByteArray, input);
1582 QFETCH(QString, scheme);
1583 QFETCH(QString, path);
1584 QFETCH(QByteArray, encoded);
1586 QString inputString(QString::fromUtf8(input));
1590 QQmlProperty p(&o, "url");
1592 // Test url written as QByteArray
1593 QCOMPARE(p.write(input), true);
1594 QUrl byteArrayResult(o.url());
1596 QCOMPARE(byteArrayResult.scheme(), scheme);
1597 QCOMPARE(byteArrayResult.path(), path);
1598 QCOMPARE(byteArrayResult.toString(QUrl::FullyEncoded), QString::fromUtf8(encoded));
1599 QCOMPARE(byteArrayResult.toEncoded(), encoded);
1604 QQmlProperty p(&o, "url");
1606 // Test url written as QString
1607 QCOMPARE(p.write(inputString), true);
1608 QUrl stringResult(o.url());
1610 QCOMPARE(stringResult.scheme(), scheme);
1611 QCOMPARE(stringResult.path(), path);
1612 QCOMPARE(stringResult.toString(QUrl::FullyEncoded), QString::fromUtf8(encoded));
1613 QCOMPARE(stringResult.toEncoded(), encoded);
1617 void tst_qqmlproperty::variantMapHandling_data()
1619 QTest::addColumn<QVariantMap>("vm");
1624 QTest::newRow("{}") << m;
1628 m["a"] = QVariantMap();
1629 QTest::newRow("{ a:{} }") << m;
1636 QTest::newRow("{ a:{b:10, c:20} }") << m;
1641 m["b"] = QVariantList() << 20 << 30;
1642 QTest::newRow("{ a:10, b:[20, 30]}") << m;
1648 m["p"] = QVariantMap();
1649 QTest::newRow("var o={}; o.p=o") << m;
1654 m["q"] = QVariantMap();
1655 QTest::newRow("var o={}; o.p=123; o.q=o") << m;
1659 void tst_qqmlproperty::variantMapHandling()
1661 QFETCH(QVariantMap, vm);
1664 QQmlProperty p(&o, "variantMap");
1666 QCOMPARE(p.write(vm), true);
1667 QCOMPARE(o.variantMap(), vm);
1670 void tst_qqmlproperty::crashOnValueProperty()
1672 QQmlEngine *engine = new QQmlEngine;
1673 QQmlComponent component(engine);
1675 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1676 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1679 QQmlProperty p(obj, "wrectProperty.x", qmlContext(obj));
1680 QCOMPARE(p.name(), QString("wrectProperty.x"));
1682 QCOMPARE(p.read(), QVariant(10));
1684 //don't crash once the engine is deleted
1688 QCOMPARE(p.propertyTypeName(), "int");
1689 QCOMPARE(p.read(), QVariant(10));
1690 p.write(QVariant(20));
1691 QCOMPARE(p.read(), QVariant(20));
1695 void tst_qqmlproperty::aliasPropertyBindings()
1697 QQmlComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
1699 QObject *object = component.create();
1700 QVERIFY(object != 0);
1702 QCOMPARE(object->property("realProperty").toReal(), 90.);
1703 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1705 object->setProperty("test", 10);
1707 QCOMPARE(object->property("realProperty").toReal(), 110.);
1708 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1710 QQmlProperty realProperty(object, QLatin1String("realProperty"));
1711 QQmlProperty aliasProperty(object, QLatin1String("aliasProperty"));
1713 // Check there is a binding on these two properties
1714 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1715 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1717 // Check that its the same binding on these two properties
1718 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1719 QQmlPropertyPrivate::binding(aliasProperty));
1721 // Change the binding
1722 object->setProperty("state", QString("switch"));
1724 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1725 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1726 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1727 QQmlPropertyPrivate::binding(aliasProperty));
1729 QCOMPARE(object->property("realProperty").toReal(), 96.);
1730 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1732 // Check the old binding really has not effect any more
1733 object->setProperty("test", 4);
1735 QCOMPARE(object->property("realProperty").toReal(), 96.);
1736 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1738 object->setProperty("test2", 9);
1740 QCOMPARE(object->property("realProperty").toReal(), 288.);
1741 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1744 object->setProperty("state", QString(""));
1746 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1747 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1748 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1749 QQmlPropertyPrivate::binding(aliasProperty));
1751 QCOMPARE(object->property("realProperty").toReal(), 20.);
1752 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1754 object->setProperty("test2", 3);
1756 QCOMPARE(object->property("realProperty").toReal(), 20.);
1757 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1762 void tst_qqmlproperty::copy()
1764 PropertyObject object;
1766 QQmlProperty *property = new QQmlProperty(&object, QLatin1String("defaultProperty"));
1767 QCOMPARE(property->name(), QString("defaultProperty"));
1768 QCOMPARE(property->read(), QVariant(10));
1769 QCOMPARE(property->type(), QQmlProperty::Property);
1770 QCOMPARE(property->propertyTypeCategory(), QQmlProperty::Normal);
1771 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1773 QQmlProperty p1(*property);
1774 QCOMPARE(p1.name(), QString("defaultProperty"));
1775 QCOMPARE(p1.read(), QVariant(10));
1776 QCOMPARE(p1.type(), QQmlProperty::Property);
1777 QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::Normal);
1778 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1780 QQmlProperty p2(&object, QLatin1String("url"));
1781 QCOMPARE(p2.name(), QString("url"));
1783 QCOMPARE(p2.name(), QString("defaultProperty"));
1784 QCOMPARE(p2.read(), QVariant(10));
1785 QCOMPARE(p2.type(), QQmlProperty::Property);
1786 QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::Normal);
1787 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1789 delete property; property = 0;
1791 QCOMPARE(p1.name(), QString("defaultProperty"));
1792 QCOMPARE(p1.read(), QVariant(10));
1793 QCOMPARE(p1.type(), QQmlProperty::Property);
1794 QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::Normal);
1795 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1797 QCOMPARE(p2.name(), QString("defaultProperty"));
1798 QCOMPARE(p2.read(), QVariant(10));
1799 QCOMPARE(p2.type(), QQmlProperty::Property);
1800 QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::Normal);
1801 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1804 void tst_qqmlproperty::noContext()
1806 QQmlComponent compA(&engine, testFileUrl("NoContextTypeA.qml"));
1807 QQmlComponent compB(&engine, testFileUrl("NoContextTypeB.qml"));
1809 QObject *a = compA.create();
1811 QObject *b = compB.create();
1814 QVERIFY(QQmlProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1820 void tst_qqmlproperty::assignEmptyVariantMap()
1825 map.insert("key", "value");
1826 o.setVariantMap(map);
1827 QCOMPARE(o.variantMap().count(), 1);
1828 QCOMPARE(o.variantMap().isEmpty(), false);
1830 QQmlContext context(&engine);
1831 context.setContextProperty("o", &o);
1833 QQmlComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml"));
1834 QObject *obj = component.create(&context);
1837 QCOMPARE(o.variantMap().count(), 0);
1838 QCOMPARE(o.variantMap().isEmpty(), true);
1843 void tst_qqmlproperty::warnOnInvalidBinding()
1845 QUrl testUrl(testFileUrl("invalidBinding.qml"));
1846 QString expectedWarning;
1848 // V4 error message for property-to-property binding
1849 expectedWarning = testUrl.toString() + QString::fromLatin1(":6:36: Unable to assign QQuickText to QQuickRectangle");
1850 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1852 // V8 error message for function-to-property binding
1853 expectedWarning = testUrl.toString() + QString::fromLatin1(":7:36: Unable to assign QQuickText to QQuickRectangle");
1854 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1856 // V8 error message for invalid binding to anchor
1857 expectedWarning = testUrl.toString() + QString::fromLatin1(":14: Unable to assign QQuickItem_QML_7 to QQuickAnchorLine");
1858 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1860 QQmlComponent component(&engine, testUrl);
1861 QObject *obj = component.create();
1866 void tst_qqmlproperty::initTestCase()
1868 QQmlDataTest::initTestCase();
1869 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1870 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1871 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1874 QTEST_MAIN(tst_qqmlproperty)
1876 #include "tst_qqmlproperty.moc"