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 void tst_qqmlproperty::registeredCompositeTypeProperty()
195 // Composite type properties
198 QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml"));
199 QObject *obj = component.create();
202 // create property accessors and check types.
203 QQmlProperty p1(obj, "first");
204 QQmlProperty p2(obj, "second");
205 QQmlProperty p3(obj, "third");
206 QVERIFY(p1.propertyType() == p2.propertyType());
207 QVERIFY(p1.propertyType() != p3.propertyType());
209 // check that the values are retrievable from CPP
210 QVariant first = obj->property("first");
211 QVariant second = obj->property("second");
212 QVariant third = obj->property("third");
213 QVERIFY(first.isValid());
214 QVERIFY(second.isValid());
215 QVERIFY(third.isValid());
216 // ensure that conversion from qobject-derived-ptr to qobject-ptr works.
217 QVERIFY(first.value<QObject*>());
218 QVERIFY(second.value<QObject*>());
219 QVERIFY(third.value<QObject*>());
221 // check that the values retrieved via QQmlProperty match.
222 QCOMPARE(p1.read(), first);
223 QCOMPARE(p2.read(), second);
224 QCOMPARE(p3.read(), third);
229 // List-of-composite-type type properties
232 QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml"));
233 QObject *obj = component.create();
236 // create list property accessors and check types
237 QQmlProperty lp1(obj, "fclist");
238 QQmlProperty lp2(obj, "sclistOne");
239 QQmlProperty lp3(obj, "sclistTwo");
240 QVERIFY(lp1.propertyType() != lp2.propertyType());
241 QVERIFY(lp2.propertyType() == lp3.propertyType());
243 // check that the list values are retrievable from CPP
244 QVariant firstList = obj->property("fclist");
245 QVariant secondList = obj->property("sclistOne");
246 QVariant thirdList = obj->property("sclistTwo");
247 QVERIFY(firstList.isValid());
248 QVERIFY(secondList.isValid());
249 QVERIFY(thirdList.isValid());
251 // check that the values retrieved via QQmlProperty match.
252 QCOMPARE(lp1.read(), firstList);
253 QCOMPARE(lp2.read(), secondList);
254 QCOMPARE(lp3.read(), thirdList);
260 class PropertyObject : public QObject
263 Q_PROPERTY(int defaultProperty READ defaultProperty)
264 Q_PROPERTY(QRect rectProperty READ rectProperty)
265 Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
266 Q_PROPERTY(QUrl url READ url WRITE setUrl)
267 Q_PROPERTY(QVariantMap variantMap READ variantMap WRITE setVariantMap)
268 Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
269 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
270 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
272 Q_CLASSINFO("DefaultProperty", "defaultProperty")
274 PropertyObject() : m_resetProperty(9) {}
276 int defaultProperty() { return 10; }
277 QRect rectProperty() { return QRect(10, 10, 1, 209); }
279 QRect wrectProperty() { return m_rect; }
280 void setWRectProperty(const QRect &r) { m_rect = r; }
282 QUrl url() { return m_url; }
283 void setUrl(const QUrl &u) { m_url = u; }
285 QVariantMap variantMap() const { return m_variantMap; }
286 void setVariantMap(const QVariantMap &variantMap) { m_variantMap = variantMap; }
288 int resettableProperty() const { return m_resetProperty; }
289 void setResettableProperty(int r) { m_resetProperty = r; }
290 void resetProperty() { m_resetProperty = 9; }
292 int propertyWithNotify() const { return m_propertyWithNotify; }
293 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
295 MyQmlObject *qmlObject() { return &m_qmlObject; }
299 void oddlyNamedNotifySignal();
305 QVariantMap m_variantMap;
306 int m_propertyWithNotify;
307 MyQmlObject m_qmlObject;
310 QML_DECLARE_TYPE(PropertyObject);
312 void tst_qqmlproperty::qmlmetaproperty_object()
314 QObject object; // Has no default property
315 PropertyObject dobject; // Has default property
318 QQmlProperty prop(&object);
320 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
321 QVERIFY(binding != 0);
322 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
323 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
324 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
326 QObject *obj = new QObject;
328 QCOMPARE(prop.name(), QString());
329 QCOMPARE(prop.read(), QVariant());
330 QCOMPARE(prop.write(QVariant()), false);
331 QCOMPARE(prop.hasNotifySignal(), false);
332 QCOMPARE(prop.needsNotifySignal(), false);
333 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
334 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
335 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
336 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
337 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
338 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
339 QVERIFY(!prop.method().isValid());
340 QCOMPARE(prop.type(), QQmlProperty::Invalid);
341 QCOMPARE(prop.isProperty(), false);
342 QCOMPARE(prop.isWritable(), false);
343 QCOMPARE(prop.isDesignable(), false);
344 QCOMPARE(prop.isResettable(), false);
345 QCOMPARE(prop.isSignalProperty(), false);
346 QCOMPARE(prop.isValid(), false);
347 QCOMPARE(prop.object(), (QObject *)0);
348 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
349 QCOMPARE(prop.propertyType(), 0);
350 QCOMPARE(prop.propertyTypeName(), (const char *)0);
351 QVERIFY(prop.property().name() == 0);
352 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
353 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
354 QVERIFY(binding == 0);
355 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
356 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
357 QVERIFY(sigExprWatcher.wasDeleted());
358 QCOMPARE(prop.index(), -1);
359 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
365 QQmlProperty prop(&dobject);
367 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
368 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
369 QVERIFY(binding != 0);
370 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
371 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
372 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
374 QObject *obj = new QObject;
376 QCOMPARE(prop.name(), QString("defaultProperty"));
377 QCOMPARE(prop.read(), QVariant(10));
378 QCOMPARE(prop.write(QVariant()), false);
379 QCOMPARE(prop.hasNotifySignal(), false);
380 QCOMPARE(prop.needsNotifySignal(), true);
381 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
382 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
383 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
384 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
385 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
386 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
387 QVERIFY(!prop.method().isValid());
388 QCOMPARE(prop.type(), QQmlProperty::Property);
389 QCOMPARE(prop.isProperty(), true);
390 QCOMPARE(prop.isWritable(), false);
391 QCOMPARE(prop.isDesignable(), true);
392 QCOMPARE(prop.isResettable(), false);
393 QCOMPARE(prop.isSignalProperty(), false);
394 QCOMPARE(prop.isValid(), true);
395 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
396 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
397 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
398 QCOMPARE(prop.propertyTypeName(), "int");
399 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
400 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
401 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
402 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
403 QVERIFY(binding != 0);
404 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
405 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
406 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
407 QVERIFY(sigExprWatcher.wasDeleted());
408 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
409 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
415 void tst_qqmlproperty::qmlmetaproperty_object_string()
418 PropertyObject dobject;
421 QQmlProperty prop(&object, QString("defaultProperty"));
423 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
424 QVERIFY(binding != 0);
425 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
426 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
427 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
429 QObject *obj = new QObject;
431 QCOMPARE(prop.name(), QString());
432 QCOMPARE(prop.read(), QVariant());
433 QCOMPARE(prop.write(QVariant()), false);
434 QCOMPARE(prop.hasNotifySignal(), false);
435 QCOMPARE(prop.needsNotifySignal(), false);
436 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
437 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
438 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
439 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
440 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
441 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
442 QVERIFY(!prop.method().isValid());
443 QCOMPARE(prop.type(), QQmlProperty::Invalid);
444 QCOMPARE(prop.isProperty(), false);
445 QCOMPARE(prop.isWritable(), false);
446 QCOMPARE(prop.isDesignable(), false);
447 QCOMPARE(prop.isResettable(), false);
448 QCOMPARE(prop.isSignalProperty(), false);
449 QCOMPARE(prop.isValid(), false);
450 QCOMPARE(prop.object(), (QObject *)0);
451 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
452 QCOMPARE(prop.propertyType(), 0);
453 QCOMPARE(prop.propertyTypeName(), (const char *)0);
454 QVERIFY(prop.property().name() == 0);
455 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
456 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
457 QVERIFY(binding == 0);
458 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
459 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
460 QVERIFY(sigExprWatcher.wasDeleted());
461 QCOMPARE(prop.index(), -1);
462 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
468 QQmlProperty prop(&dobject, QString("defaultProperty"));
470 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
471 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
472 QVERIFY(binding != 0);
473 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
474 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
475 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
477 QObject *obj = new QObject;
479 QCOMPARE(prop.name(), QString("defaultProperty"));
480 QCOMPARE(prop.read(), QVariant(10));
481 QCOMPARE(prop.write(QVariant()), false);
482 QCOMPARE(prop.hasNotifySignal(), false);
483 QCOMPARE(prop.needsNotifySignal(), true);
484 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
485 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
486 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
487 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
488 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
489 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
490 QVERIFY(!prop.method().isValid());
491 QCOMPARE(prop.type(), QQmlProperty::Property);
492 QCOMPARE(prop.isProperty(), true);
493 QCOMPARE(prop.isWritable(), false);
494 QCOMPARE(prop.isDesignable(), true);
495 QCOMPARE(prop.isResettable(), false);
496 QCOMPARE(prop.isSignalProperty(), false);
497 QCOMPARE(prop.isValid(), true);
498 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
499 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
500 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
501 QCOMPARE(prop.propertyTypeName(), "int");
502 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
503 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
504 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
505 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
506 QVERIFY(binding != 0);
507 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
508 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
509 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
510 QVERIFY(sigExprWatcher.wasDeleted());
511 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
512 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
518 QQmlProperty prop(&dobject, QString("onClicked"));
520 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
521 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
522 QVERIFY(binding != 0);
523 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
524 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
525 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
527 QObject *obj = new QObject;
529 QCOMPARE(prop.name(), QString("onClicked"));
530 QCOMPARE(prop.read(), QVariant());
531 QCOMPARE(prop.write(QVariant("Hello")), false);
532 QCOMPARE(prop.hasNotifySignal(), false);
533 QCOMPARE(prop.needsNotifySignal(), false);
534 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
535 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
536 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
537 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
538 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
539 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
540 QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()"));
541 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
542 QCOMPARE(prop.isProperty(), false);
543 QCOMPARE(prop.isWritable(), false);
544 QCOMPARE(prop.isDesignable(), false);
545 QCOMPARE(prop.isResettable(), false);
546 QCOMPARE(prop.isSignalProperty(), true);
547 QCOMPARE(prop.isValid(), true);
548 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
549 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
550 QCOMPARE(prop.propertyType(), 0);
551 QCOMPARE(prop.propertyTypeName(), (const char *)0);
552 QCOMPARE(prop.property().name(), (const char *)0);
553 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
554 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
555 QVERIFY(binding == 0);
556 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
557 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
558 QVERIFY(!sigExprWatcher.wasDeleted());
559 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
560 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
561 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
567 QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
569 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
570 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
571 QVERIFY(binding != 0);
572 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
573 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
574 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
576 QObject *obj = new QObject;
578 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
579 QCOMPARE(prop.read(), QVariant());
580 QCOMPARE(prop.write(QVariant("Hello")), false);
581 QCOMPARE(prop.hasNotifySignal(), false);
582 QCOMPARE(prop.needsNotifySignal(), false);
583 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
584 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
585 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
586 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
587 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
588 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
589 QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()"));
590 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
591 QCOMPARE(prop.isProperty(), false);
592 QCOMPARE(prop.isWritable(), false);
593 QCOMPARE(prop.isDesignable(), false);
594 QCOMPARE(prop.isResettable(), false);
595 QCOMPARE(prop.isSignalProperty(), true);
596 QCOMPARE(prop.isValid(), true);
597 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
598 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
599 QCOMPARE(prop.propertyType(), 0);
600 QCOMPARE(prop.propertyTypeName(), (const char *)0);
601 QCOMPARE(prop.property().name(), (const char *)0);
602 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
603 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
604 QVERIFY(binding == 0);
605 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
606 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
607 QVERIFY(!sigExprWatcher.wasDeleted());
608 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
609 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
610 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
616 void tst_qqmlproperty::qmlmetaproperty_object_context()
618 QObject object; // Has no default property
619 PropertyObject dobject; // Has default property
622 QQmlProperty prop(&object, engine.rootContext());
624 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
625 QVERIFY(binding != 0);
626 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
627 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
628 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
630 QObject *obj = new QObject;
632 QCOMPARE(prop.name(), QString());
633 QCOMPARE(prop.read(), QVariant());
634 QCOMPARE(prop.write(QVariant()), false);
635 QCOMPARE(prop.hasNotifySignal(), false);
636 QCOMPARE(prop.needsNotifySignal(), false);
637 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
638 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
639 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
640 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
641 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
642 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
643 QVERIFY(!prop.method().isValid());
644 QCOMPARE(prop.type(), QQmlProperty::Invalid);
645 QCOMPARE(prop.isProperty(), false);
646 QCOMPARE(prop.isWritable(), false);
647 QCOMPARE(prop.isDesignable(), false);
648 QCOMPARE(prop.isResettable(), false);
649 QCOMPARE(prop.isSignalProperty(), false);
650 QCOMPARE(prop.isValid(), false);
651 QCOMPARE(prop.object(), (QObject *)0);
652 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
653 QCOMPARE(prop.propertyType(), 0);
654 QCOMPARE(prop.propertyTypeName(), (const char *)0);
655 QVERIFY(prop.property().name() == 0);
656 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
657 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
658 QVERIFY(binding == 0);
659 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
660 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
661 QVERIFY(sigExprWatcher.wasDeleted());
662 QCOMPARE(prop.index(), -1);
663 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
669 QQmlProperty prop(&dobject, engine.rootContext());
671 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
672 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
673 QVERIFY(binding != 0);
674 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
675 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
676 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
678 QObject *obj = new QObject;
680 QCOMPARE(prop.name(), QString("defaultProperty"));
681 QCOMPARE(prop.read(), QVariant(10));
682 QCOMPARE(prop.write(QVariant()), false);
683 QCOMPARE(prop.hasNotifySignal(), false);
684 QCOMPARE(prop.needsNotifySignal(), true);
685 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
686 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
687 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
688 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
689 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
690 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
691 QVERIFY(!prop.method().isValid());
692 QCOMPARE(prop.type(), QQmlProperty::Property);
693 QCOMPARE(prop.isProperty(), true);
694 QCOMPARE(prop.isWritable(), false);
695 QCOMPARE(prop.isDesignable(), true);
696 QCOMPARE(prop.isResettable(), false);
697 QCOMPARE(prop.isSignalProperty(), false);
698 QCOMPARE(prop.isValid(), true);
699 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
700 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
701 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
702 QCOMPARE(prop.propertyTypeName(), "int");
703 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
704 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
705 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
706 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
707 QVERIFY(binding != 0);
708 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
709 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
710 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
711 QVERIFY(sigExprWatcher.wasDeleted());
712 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
713 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
719 void tst_qqmlproperty::qmlmetaproperty_object_string_context()
722 PropertyObject dobject;
725 QQmlProperty prop(&object, QString("defaultProperty"), engine.rootContext());
727 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
728 QVERIFY(binding != 0);
729 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
730 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
731 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
733 QObject *obj = new QObject;
735 QCOMPARE(prop.name(), QString());
736 QCOMPARE(prop.read(), QVariant());
737 QCOMPARE(prop.write(QVariant()), false);
738 QCOMPARE(prop.hasNotifySignal(), false);
739 QCOMPARE(prop.needsNotifySignal(), false);
740 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
741 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
742 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
743 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
744 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
745 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
746 QVERIFY(!prop.method().isValid());
747 QCOMPARE(prop.type(), QQmlProperty::Invalid);
748 QCOMPARE(prop.isProperty(), false);
749 QCOMPARE(prop.isWritable(), false);
750 QCOMPARE(prop.isDesignable(), false);
751 QCOMPARE(prop.isResettable(), false);
752 QCOMPARE(prop.isSignalProperty(), false);
753 QCOMPARE(prop.isValid(), false);
754 QCOMPARE(prop.object(), (QObject *)0);
755 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
756 QCOMPARE(prop.propertyType(), 0);
757 QCOMPARE(prop.propertyTypeName(), (const char *)0);
758 QVERIFY(prop.property().name() == 0);
759 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
760 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
761 QVERIFY(binding == 0);
762 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
763 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
764 QVERIFY(sigExprWatcher.wasDeleted());
765 QCOMPARE(prop.index(), -1);
766 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
772 QQmlProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
774 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
775 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
776 QVERIFY(binding != 0);
777 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
778 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
779 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
781 QObject *obj = new QObject;
783 QCOMPARE(prop.name(), QString("defaultProperty"));
784 QCOMPARE(prop.read(), QVariant(10));
785 QCOMPARE(prop.write(QVariant()), false);
786 QCOMPARE(prop.hasNotifySignal(), false);
787 QCOMPARE(prop.needsNotifySignal(), true);
788 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
789 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
790 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
791 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
792 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
793 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
794 QVERIFY(!prop.method().isValid());
795 QCOMPARE(prop.type(), QQmlProperty::Property);
796 QCOMPARE(prop.isProperty(), true);
797 QCOMPARE(prop.isWritable(), false);
798 QCOMPARE(prop.isDesignable(), true);
799 QCOMPARE(prop.isResettable(), false);
800 QCOMPARE(prop.isSignalProperty(), false);
801 QCOMPARE(prop.isValid(), true);
802 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
803 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
804 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
805 QCOMPARE(prop.propertyTypeName(), "int");
806 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
807 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
808 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
809 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
810 QVERIFY(binding != 0);
811 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
812 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
813 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
814 QVERIFY(sigExprWatcher.wasDeleted());
815 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
816 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
822 QQmlProperty prop(&dobject, QString("onClicked"), engine.rootContext());
824 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
825 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
826 QVERIFY(binding != 0);
827 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
828 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
829 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
831 QObject *obj = new QObject;
833 QCOMPARE(prop.name(), QString("onClicked"));
834 QCOMPARE(prop.read(), QVariant());
835 QCOMPARE(prop.write(QVariant("Hello")), false);
836 QCOMPARE(prop.hasNotifySignal(), false);
837 QCOMPARE(prop.needsNotifySignal(), false);
838 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
839 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
840 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
841 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
842 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
843 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
844 QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()"));
845 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
846 QCOMPARE(prop.isProperty(), false);
847 QCOMPARE(prop.isWritable(), false);
848 QCOMPARE(prop.isDesignable(), false);
849 QCOMPARE(prop.isResettable(), false);
850 QCOMPARE(prop.isSignalProperty(), true);
851 QCOMPARE(prop.isValid(), true);
852 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
853 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
854 QCOMPARE(prop.propertyType(), 0);
855 QCOMPARE(prop.propertyTypeName(), (const char *)0);
856 QCOMPARE(prop.property().name(), (const char *)0);
857 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
858 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
859 QVERIFY(binding == 0);
860 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
861 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
862 QVERIFY(!sigExprWatcher.wasDeleted());
863 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
864 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
865 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
871 QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
873 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
874 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
875 QVERIFY(binding != 0);
876 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
877 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
878 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
880 QObject *obj = new QObject;
882 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
883 QCOMPARE(prop.read(), QVariant());
884 QCOMPARE(prop.write(QVariant("Hello")), false);
885 QCOMPARE(prop.hasNotifySignal(), false);
886 QCOMPARE(prop.needsNotifySignal(), false);
887 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
888 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
889 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
890 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
891 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
892 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
893 QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()"));
894 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
895 QCOMPARE(prop.isProperty(), false);
896 QCOMPARE(prop.isWritable(), false);
897 QCOMPARE(prop.isDesignable(), false);
898 QCOMPARE(prop.isResettable(), false);
899 QCOMPARE(prop.isSignalProperty(), true);
900 QCOMPARE(prop.isValid(), true);
901 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
902 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
903 QCOMPARE(prop.propertyType(), 0);
904 QCOMPARE(prop.propertyTypeName(), (const char *)0);
905 QCOMPARE(prop.property().name(), (const char *)0);
906 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
907 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
908 QVERIFY(binding == 0);
909 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
910 QVERIFY(QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr) == 0);
911 QVERIFY(!sigExprWatcher.wasDeleted());
912 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
913 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
914 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
920 void tst_qqmlproperty::name()
924 QCOMPARE(p.name(), QString());
930 QCOMPARE(p.name(), QString("defaultProperty"));
935 QQmlProperty p(&o, QString("objectName"));
936 QCOMPARE(p.name(), QString("objectName"));
941 QQmlProperty p(&o, "onClicked");
942 QCOMPARE(p.name(), QString("onClicked"));
947 QQmlProperty p(&o, "onClicked");
948 QCOMPARE(p.name(), QString());
953 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
954 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
959 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
960 QCOMPARE(p.name(), QString());
965 QQmlProperty p(&o, "foo");
966 QCOMPARE(p.name(), QString());
970 QQmlProperty p(0, "foo");
971 QCOMPARE(p.name(), QString());
976 QQmlProperty p(&o, "rectProperty");
977 QCOMPARE(p.name(), QString("rectProperty"));
982 QQmlProperty p(&o, "rectProperty.x");
983 QCOMPARE(p.name(), QString("rectProperty.x"));
988 QQmlProperty p(&o, "rectProperty.foo");
989 QCOMPARE(p.name(), QString());
993 void tst_qqmlproperty::read()
998 QCOMPARE(p.read(), QVariant());
1005 QCOMPARE(p.read(), QVariant(10));
1008 // Invalid default prop
1012 QCOMPARE(p.read(), QVariant());
1015 // Value prop by name
1019 QQmlProperty p(&o, "objectName");
1020 QCOMPARE(p.read(), QVariant(QString()));
1022 o.setObjectName("myName");
1024 QCOMPARE(p.read(), QVariant("myName"));
1027 // Value prop by name (static)
1031 QCOMPARE(QQmlProperty::read(&o, "objectName"), QVariant(QString()));
1033 o.setObjectName("myName");
1035 QCOMPARE(QQmlProperty::read(&o, "objectName"), QVariant("myName"));
1041 QQmlProperty p(&o, "rectProperty.x");
1042 QCOMPARE(p.read(), QVariant(10));
1045 // Invalid value-type prop
1048 QQmlProperty p(&o, "rectProperty.foo");
1049 QCOMPARE(p.read(), QVariant());
1055 QQmlProperty p(&o, "onClicked");
1056 QCOMPARE(p.read(), QVariant());
1058 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1059 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1061 QCOMPARE(p.read(), QVariant());
1064 // Automatic signal property
1067 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1068 QCOMPARE(p.read(), QVariant());
1070 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1071 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1073 QCOMPARE(p.read(), QVariant());
1078 PropertyObject *o = new PropertyObject;
1079 QQmlProperty p(o, "rectProperty.x");
1080 QCOMPARE(p.read(), QVariant(10));
1082 QCOMPARE(p.read(), QVariant());
1088 QQmlProperty p(&o, "qmlObject");
1089 QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
1090 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
1091 QVariant v = p.read();
1092 QVERIFY(v.userType() == QMetaType::QObjectStar);
1093 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1096 QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1097 QObject *object = component.create();
1098 QVERIFY(object != 0);
1100 QQmlProperty p(object, "test", &engine);
1102 QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
1103 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1105 QVariant v = p.read();
1106 QVERIFY(v.userType() == QMetaType::QObjectStar);
1107 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1108 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1111 QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1112 QObject *object = component.create();
1113 QVERIFY(object != 0);
1115 QVariant v = QQmlProperty::read(object, "test", &engine);
1116 QVERIFY(v.userType() == QMetaType::QObjectStar);
1117 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1118 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1121 // Attached property
1123 QQmlComponent component(&engine);
1124 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1125 QObject *object = component.create();
1126 QVERIFY(object != 0);
1128 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1129 QCOMPARE(p.read(), QVariant(13));
1133 QQmlComponent component(&engine);
1134 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1135 QObject *object = component.create();
1136 QVERIFY(object != 0);
1138 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1139 QCOMPARE(p.read(), QVariant(10));
1143 QQmlComponent component(&engine);
1144 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1145 QObject *object = component.create();
1146 QVERIFY(object != 0);
1148 QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1149 QCOMPARE(p.read(), QVariant(10));
1153 QQmlComponent component(&engine);
1154 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1155 QObject *object = component.create();
1156 QVERIFY(object != 0);
1158 QCOMPARE(QQmlProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1163 void tst_qqmlproperty::write()
1168 QCOMPARE(p.write(QVariant(10)), false);
1171 // Read-only default prop
1175 QCOMPARE(p.write(QVariant(10)), false);
1178 // Invalid default prop
1182 QCOMPARE(p.write(QVariant(10)), false);
1185 // Read-only prop by name
1188 QQmlProperty p(&o, QString("defaultProperty"));
1189 QCOMPARE(p.write(QVariant(10)), false);
1192 // Writable prop by name
1195 QQmlProperty p(&o, QString("objectName"));
1196 QCOMPARE(o.objectName(), QString());
1197 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1198 QCOMPARE(o.objectName(), QString("myName"));
1201 // Writable prop by name (static)
1204 QCOMPARE(QQmlProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1205 QCOMPARE(o.objectName(), QString("myName"));
1210 PropertyObject *o = new PropertyObject;
1211 QQmlProperty p(o, QString("objectName"));
1212 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1213 QCOMPARE(o->objectName(), QString("myName"));
1217 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1223 QQmlProperty p(&o, "onClicked");
1224 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1226 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1227 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1229 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1231 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1234 // Automatic signal property
1237 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1238 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1240 QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1241 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1243 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1245 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1248 // Value-type property
1251 QQmlProperty p(&o, "wrectProperty");
1253 QCOMPARE(o.wrectProperty(), QRect());
1254 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1255 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1257 QQmlProperty p2(&o, "wrectProperty.x");
1258 QCOMPARE(p2.read(), QVariant(1));
1259 QCOMPARE(p2.write(QVariant(6)), true);
1260 QCOMPARE(p2.read(), QVariant(6));
1261 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1267 QQmlProperty p(&o, "url");
1269 QCOMPARE(p.write(QUrl("main.qml")), true);
1270 QCOMPARE(o.url(), QUrl("main.qml"));
1272 QQmlProperty p2(&o, "url", engine.rootContext());
1274 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1275 QVERIFY(result != QUrl("main.qml"));
1277 QCOMPARE(p2.write(QUrl("main.qml")), true);
1278 QCOMPARE(o.url(), result);
1283 QCOMPARE(QQmlProperty::write(&o, "url", QUrl("main.qml")), true);
1284 QCOMPARE(o.url(), QUrl("main.qml"));
1286 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1287 QVERIFY(result != QUrl("main.qml"));
1289 QCOMPARE(QQmlProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1290 QCOMPARE(o.url(), result);
1293 // VariantMap-property
1295 vm.insert("key", "value");
1299 QQmlProperty p(&o, "variantMap");
1301 QCOMPARE(p.write(vm), true);
1302 QCOMPARE(o.variantMap(), vm);
1304 QQmlProperty p2(&o, "variantMap", engine.rootContext());
1306 QCOMPARE(p2.write(vm), true);
1307 QCOMPARE(o.variantMap(), vm);
1312 QCOMPARE(QQmlProperty::write(&o, "variantMap", vm), true);
1313 QCOMPARE(o.variantMap(), vm);
1315 QCOMPARE(QQmlProperty::write(&o, "variantMap", vm, engine.rootContext()), true);
1316 QCOMPARE(o.variantMap(), vm);
1319 // Attached property
1321 QQmlComponent component(&engine);
1322 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1323 QObject *object = component.create();
1324 QVERIFY(object != 0);
1326 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1327 p.write(QVariant(99));
1328 QCOMPARE(p.read(), QVariant(99));
1332 QQmlComponent component(&engine);
1333 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1334 QObject *object = component.create();
1335 QVERIFY(object != 0);
1337 QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1338 p.write(QVariant(99));
1339 QCOMPARE(p.read(), QVariant(99));
1344 void tst_qqmlproperty::reset()
1349 QCOMPARE(p.isResettable(), false);
1350 QCOMPARE(p.reset(), false);
1353 // Read-only default prop
1357 QCOMPARE(p.isResettable(), false);
1358 QCOMPARE(p.reset(), false);
1361 // Invalid default prop
1365 QCOMPARE(p.isResettable(), false);
1366 QCOMPARE(p.reset(), false);
1369 // Non-resettable-only prop by name
1372 QQmlProperty p(&o, QString("defaultProperty"));
1373 QCOMPARE(p.isResettable(), false);
1374 QCOMPARE(p.reset(), false);
1377 // Resettable prop by name
1380 QQmlProperty p(&o, QString("resettableProperty"));
1382 QCOMPARE(p.read(), QVariant(9));
1383 QCOMPARE(p.write(QVariant(11)), true);
1384 QCOMPARE(p.read(), QVariant(11));
1386 QCOMPARE(p.isResettable(), true);
1387 QCOMPARE(p.reset(), true);
1389 QCOMPARE(p.read(), QVariant(9));
1394 PropertyObject *o = new PropertyObject;
1396 QQmlProperty p(o, QString("resettableProperty"));
1398 QCOMPARE(p.isResettable(), true);
1399 QCOMPARE(p.reset(), true);
1403 QCOMPARE(p.isResettable(), false);
1404 QCOMPARE(p.reset(), false);
1410 QQmlProperty p(&o, "onClicked");
1412 QCOMPARE(p.isResettable(), false);
1413 QCOMPARE(p.reset(), false);
1416 // Automatic signal property
1419 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1421 QCOMPARE(p.isResettable(), false);
1422 QCOMPARE(p.reset(), false);
1426 void tst_qqmlproperty::writeObjectToList()
1428 QQmlComponent containerComponent(&engine);
1429 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1430 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1431 QVERIFY(container != 0);
1432 QQmlListReference list(container, "children");
1433 QVERIFY(list.count() == 1);
1435 MyQmlObject *object = new MyQmlObject;
1436 QQmlProperty prop(container, "children");
1437 prop.write(qVariantFromValue(object));
1438 QCOMPARE(list.count(), 1);
1439 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1442 void tst_qqmlproperty::writeListToList()
1444 QQmlComponent containerComponent(&engine);
1445 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1446 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1447 QVERIFY(container != 0);
1448 QQmlListReference list(container, "children");
1449 QVERIFY(list.count() == 1);
1451 QList<QObject*> objList;
1452 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1453 QQmlProperty prop(container, "children");
1454 prop.write(qVariantFromValue(objList));
1455 QCOMPARE(list.count(), 4);
1457 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1458 /*QList<MyQmlObject*> typedObjList;
1459 typedObjList << new MyQmlObject();
1460 prop.write(qVariantFromValue(&typedObjList));
1461 QCOMPARE(container->children()->size(), 1);*/
1464 void tst_qqmlproperty::urlHandling_data()
1466 QTest::addColumn<QByteArray>("input");
1467 QTest::addColumn<QString>("scheme");
1468 QTest::addColumn<QString>("path");
1469 QTest::addColumn<QByteArray>("encoded");
1471 QTest::newRow("unspecifiedFile")
1472 << QByteArray("main.qml")
1474 << QString("main.qml")
1475 << QByteArray("main.qml");
1477 QTest::newRow("specifiedFile")
1478 << QByteArray("file:///main.qml")
1480 << QString("/main.qml")
1481 << QByteArray("file:///main.qml");
1483 QTest::newRow("httpFile")
1484 << QByteArray("http://www.example.com/main.qml")
1486 << QString("/main.qml")
1487 << QByteArray("http://www.example.com/main.qml");
1489 QTest::newRow("pathFile")
1490 << QByteArray("http://www.example.com/resources/main.qml")
1492 << QString("/resources/main.qml")
1493 << QByteArray("http://www.example.com/resources/main.qml");
1495 QTest::newRow("encodableName")
1496 << QByteArray("http://www.example.com/main file.qml")
1498 << QString("/main file.qml")
1499 << QByteArray("http://www.example.com/main%20file.qml");
1501 QTest::newRow("preencodedName")
1502 << QByteArray("http://www.example.com/resources%7Cmain%20file.qml")
1504 << QString("/resources|main file.qml")
1505 << QByteArray("http://www.example.com/resources%7Cmain%20file.qml");
1507 QTest::newRow("encodableQuery")
1508 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now working?")
1510 << QString("/main.qml")
1511 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now%20working?");
1513 QTest::newRow("preencodedQuery")
1514 << QByteArray("http://www.example.com/main.qml?type=text%2Fqml&comment=now working%3F")
1516 << QString("/main.qml")
1517 << QByteArray("http://www.example.com/main.qml?type=text%2Fqml&comment=now%20working%3F");
1519 QTest::newRow("encodableFragment")
1520 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000|volume+50%")
1522 << QString("/main.qml")
1523 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume+50%25");
1525 QTest::newRow("improperlyEncodedFragment")
1526 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume%2B50%")
1528 << QString("/main.qml")
1529 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%257Cvolume%252B50%25");
1532 void tst_qqmlproperty::urlHandling()
1534 QFETCH(QByteArray, input);
1535 QFETCH(QString, scheme);
1536 QFETCH(QString, path);
1537 QFETCH(QByteArray, encoded);
1539 QString inputString(QString::fromUtf8(input));
1543 QQmlProperty p(&o, "url");
1545 // Test url written as QByteArray
1546 QCOMPARE(p.write(input), true);
1547 QUrl byteArrayResult(o.url());
1549 QCOMPARE(byteArrayResult.scheme(), scheme);
1550 QCOMPARE(byteArrayResult.path(), path);
1551 QCOMPARE(byteArrayResult.toString(QUrl::FullyEncoded), QString::fromUtf8(encoded));
1552 QCOMPARE(byteArrayResult.toEncoded(), encoded);
1557 QQmlProperty p(&o, "url");
1559 // Test url written as QString
1560 QCOMPARE(p.write(inputString), true);
1561 QUrl stringResult(o.url());
1563 QCOMPARE(stringResult.scheme(), scheme);
1564 QCOMPARE(stringResult.path(), path);
1565 QCOMPARE(stringResult.toString(QUrl::FullyEncoded), QString::fromUtf8(encoded));
1566 QCOMPARE(stringResult.toEncoded(), encoded);
1570 void tst_qqmlproperty::variantMapHandling_data()
1572 QTest::addColumn<QVariantMap>("vm");
1577 QTest::newRow("{}") << m;
1581 m["a"] = QVariantMap();
1582 QTest::newRow("{ a:{} }") << m;
1589 QTest::newRow("{ a:{b:10, c:20} }") << m;
1594 m["b"] = QVariantList() << 20 << 30;
1595 QTest::newRow("{ a:10, b:[20, 30]}") << m;
1601 m["p"] = QVariantMap();
1602 QTest::newRow("var o={}; o.p=o") << m;
1607 m["q"] = QVariantMap();
1608 QTest::newRow("var o={}; o.p=123; o.q=o") << m;
1612 void tst_qqmlproperty::variantMapHandling()
1614 QFETCH(QVariantMap, vm);
1617 QQmlProperty p(&o, "variantMap");
1619 QCOMPARE(p.write(vm), true);
1620 QCOMPARE(o.variantMap(), vm);
1623 void tst_qqmlproperty::crashOnValueProperty()
1625 QQmlEngine *engine = new QQmlEngine;
1626 QQmlComponent component(engine);
1628 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1629 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1632 QQmlProperty p(obj, "wrectProperty.x", qmlContext(obj));
1633 QCOMPARE(p.name(), QString("wrectProperty.x"));
1635 QCOMPARE(p.read(), QVariant(10));
1637 //don't crash once the engine is deleted
1641 QCOMPARE(p.propertyTypeName(), "int");
1642 QCOMPARE(p.read(), QVariant(10));
1643 p.write(QVariant(20));
1644 QCOMPARE(p.read(), QVariant(20));
1648 void tst_qqmlproperty::aliasPropertyBindings()
1650 QQmlComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
1652 QObject *object = component.create();
1653 QVERIFY(object != 0);
1655 QCOMPARE(object->property("realProperty").toReal(), 90.);
1656 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1658 object->setProperty("test", 10);
1660 QCOMPARE(object->property("realProperty").toReal(), 110.);
1661 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1663 QQmlProperty realProperty(object, QLatin1String("realProperty"));
1664 QQmlProperty aliasProperty(object, QLatin1String("aliasProperty"));
1666 // Check there is a binding on these two properties
1667 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1668 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1670 // Check that its the same binding on these two properties
1671 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1672 QQmlPropertyPrivate::binding(aliasProperty));
1674 // Change the binding
1675 object->setProperty("state", QString("switch"));
1677 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1678 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1679 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1680 QQmlPropertyPrivate::binding(aliasProperty));
1682 QCOMPARE(object->property("realProperty").toReal(), 96.);
1683 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1685 // Check the old binding really has not effect any more
1686 object->setProperty("test", 4);
1688 QCOMPARE(object->property("realProperty").toReal(), 96.);
1689 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1691 object->setProperty("test2", 9);
1693 QCOMPARE(object->property("realProperty").toReal(), 288.);
1694 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1697 object->setProperty("state", QString(""));
1699 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1700 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1701 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1702 QQmlPropertyPrivate::binding(aliasProperty));
1704 QCOMPARE(object->property("realProperty").toReal(), 20.);
1705 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1707 object->setProperty("test2", 3);
1709 QCOMPARE(object->property("realProperty").toReal(), 20.);
1710 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1715 void tst_qqmlproperty::copy()
1717 PropertyObject object;
1719 QQmlProperty *property = new QQmlProperty(&object, QLatin1String("defaultProperty"));
1720 QCOMPARE(property->name(), QString("defaultProperty"));
1721 QCOMPARE(property->read(), QVariant(10));
1722 QCOMPARE(property->type(), QQmlProperty::Property);
1723 QCOMPARE(property->propertyTypeCategory(), QQmlProperty::Normal);
1724 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1726 QQmlProperty p1(*property);
1727 QCOMPARE(p1.name(), QString("defaultProperty"));
1728 QCOMPARE(p1.read(), QVariant(10));
1729 QCOMPARE(p1.type(), QQmlProperty::Property);
1730 QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::Normal);
1731 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1733 QQmlProperty p2(&object, QLatin1String("url"));
1734 QCOMPARE(p2.name(), QString("url"));
1736 QCOMPARE(p2.name(), QString("defaultProperty"));
1737 QCOMPARE(p2.read(), QVariant(10));
1738 QCOMPARE(p2.type(), QQmlProperty::Property);
1739 QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::Normal);
1740 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1742 delete property; property = 0;
1744 QCOMPARE(p1.name(), QString("defaultProperty"));
1745 QCOMPARE(p1.read(), QVariant(10));
1746 QCOMPARE(p1.type(), QQmlProperty::Property);
1747 QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::Normal);
1748 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1750 QCOMPARE(p2.name(), QString("defaultProperty"));
1751 QCOMPARE(p2.read(), QVariant(10));
1752 QCOMPARE(p2.type(), QQmlProperty::Property);
1753 QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::Normal);
1754 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1757 void tst_qqmlproperty::noContext()
1759 QQmlComponent compA(&engine, testFileUrl("NoContextTypeA.qml"));
1760 QQmlComponent compB(&engine, testFileUrl("NoContextTypeB.qml"));
1762 QObject *a = compA.create();
1764 QObject *b = compB.create();
1767 QVERIFY(QQmlProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1773 void tst_qqmlproperty::assignEmptyVariantMap()
1778 map.insert("key", "value");
1779 o.setVariantMap(map);
1780 QCOMPARE(o.variantMap().count(), 1);
1781 QCOMPARE(o.variantMap().isEmpty(), false);
1783 QQmlContext context(&engine);
1784 context.setContextProperty("o", &o);
1786 QQmlComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml"));
1787 QObject *obj = component.create(&context);
1790 QCOMPARE(o.variantMap().count(), 0);
1791 QCOMPARE(o.variantMap().isEmpty(), true);
1796 void tst_qqmlproperty::warnOnInvalidBinding()
1798 QUrl testUrl(testFileUrl("invalidBinding.qml"));
1799 QString expectedWarning;
1801 // V4 error message for property-to-property binding
1802 expectedWarning = testUrl.toString() + QString::fromLatin1(":6:36: Unable to assign QQuickText to QQuickRectangle");
1803 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1805 // V8 error message for function-to-property binding
1806 expectedWarning = testUrl.toString() + QString::fromLatin1(":7:36: Unable to assign QQuickText to QQuickRectangle");
1807 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1809 // V8 error message for invalid binding to anchor
1810 expectedWarning = testUrl.toString() + QString::fromLatin1(":14: Unable to assign QQuickItem_QML_7 to QQuickAnchorLine");
1811 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1813 QQmlComponent component(&engine, testUrl);
1814 QObject *obj = component.create();
1819 void tst_qqmlproperty::initTestCase()
1821 QQmlDataTest::initTestCase();
1822 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1823 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1824 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1827 QTEST_MAIN(tst_qqmlproperty)
1829 #include "tst_qqmlproperty.moc"