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();
144 void tst_qqmlproperty::qmlmetaproperty()
148 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
149 QVERIFY(binding != 0);
150 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
151 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
152 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
154 QObject *obj = new QObject;
156 QCOMPARE(prop.name(), QString());
157 QCOMPARE(prop.read(), QVariant());
158 QCOMPARE(prop.write(QVariant()), false);
159 QCOMPARE(prop.hasNotifySignal(), false);
160 QCOMPARE(prop.needsNotifySignal(), false);
161 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
162 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
163 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
164 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
165 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
166 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
167 QVERIFY(!prop.method().isValid());
168 QCOMPARE(prop.type(), QQmlProperty::Invalid);
169 QCOMPARE(prop.isProperty(), false);
170 QCOMPARE(prop.isWritable(), false);
171 QCOMPARE(prop.isDesignable(), false);
172 QCOMPARE(prop.isResettable(), false);
173 QCOMPARE(prop.isSignalProperty(), false);
174 QCOMPARE(prop.isValid(), false);
175 QCOMPARE(prop.object(), (QObject *)0);
176 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
177 QCOMPARE(prop.propertyType(), 0);
178 QCOMPARE(prop.propertyTypeName(), (const char *)0);
179 QVERIFY(prop.property().name() == 0);
180 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
181 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
182 QVERIFY(binding == 0);
183 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
184 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
185 QVERIFY(sigExprWatcher.wasDeleted());
186 QCOMPARE(prop.index(), -1);
187 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
192 class PropertyObject : public QObject
195 Q_PROPERTY(int defaultProperty READ defaultProperty)
196 Q_PROPERTY(QRect rectProperty READ rectProperty)
197 Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
198 Q_PROPERTY(QUrl url READ url WRITE setUrl)
199 Q_PROPERTY(QVariantMap variantMap READ variantMap WRITE setVariantMap)
200 Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
201 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
202 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
204 Q_CLASSINFO("DefaultProperty", "defaultProperty")
206 PropertyObject() : m_resetProperty(9) {}
208 int defaultProperty() { return 10; }
209 QRect rectProperty() { return QRect(10, 10, 1, 209); }
211 QRect wrectProperty() { return m_rect; }
212 void setWRectProperty(const QRect &r) { m_rect = r; }
214 QUrl url() { return m_url; }
215 void setUrl(const QUrl &u) { m_url = u; }
217 QVariantMap variantMap() const { return m_variantMap; }
218 void setVariantMap(const QVariantMap &variantMap) { m_variantMap = variantMap; }
220 int resettableProperty() const { return m_resetProperty; }
221 void setResettableProperty(int r) { m_resetProperty = r; }
222 void resetProperty() { m_resetProperty = 9; }
224 int propertyWithNotify() const { return m_propertyWithNotify; }
225 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
227 MyQmlObject *qmlObject() { return &m_qmlObject; }
231 void oddlyNamedNotifySignal();
237 QVariantMap m_variantMap;
238 int m_propertyWithNotify;
239 MyQmlObject m_qmlObject;
242 QML_DECLARE_TYPE(PropertyObject);
244 void tst_qqmlproperty::qmlmetaproperty_object()
246 QObject object; // Has no default property
247 PropertyObject dobject; // Has default property
250 QQmlProperty prop(&object);
252 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
253 QVERIFY(binding != 0);
254 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
255 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
256 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
258 QObject *obj = new QObject;
260 QCOMPARE(prop.name(), QString());
261 QCOMPARE(prop.read(), QVariant());
262 QCOMPARE(prop.write(QVariant()), false);
263 QCOMPARE(prop.hasNotifySignal(), false);
264 QCOMPARE(prop.needsNotifySignal(), false);
265 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
266 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
267 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
268 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
269 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
270 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
271 QVERIFY(!prop.method().isValid());
272 QCOMPARE(prop.type(), QQmlProperty::Invalid);
273 QCOMPARE(prop.isProperty(), false);
274 QCOMPARE(prop.isWritable(), false);
275 QCOMPARE(prop.isDesignable(), false);
276 QCOMPARE(prop.isResettable(), false);
277 QCOMPARE(prop.isSignalProperty(), false);
278 QCOMPARE(prop.isValid(), false);
279 QCOMPARE(prop.object(), (QObject *)0);
280 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
281 QCOMPARE(prop.propertyType(), 0);
282 QCOMPARE(prop.propertyTypeName(), (const char *)0);
283 QVERIFY(prop.property().name() == 0);
284 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
285 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
286 QVERIFY(binding == 0);
287 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
288 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
289 QVERIFY(sigExprWatcher.wasDeleted());
290 QCOMPARE(prop.index(), -1);
291 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
297 QQmlProperty prop(&dobject);
299 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
300 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
301 QVERIFY(binding != 0);
302 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
303 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
304 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
306 QObject *obj = new QObject;
308 QCOMPARE(prop.name(), QString("defaultProperty"));
309 QCOMPARE(prop.read(), QVariant(10));
310 QCOMPARE(prop.write(QVariant()), false);
311 QCOMPARE(prop.hasNotifySignal(), false);
312 QCOMPARE(prop.needsNotifySignal(), true);
313 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
314 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
315 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
316 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
317 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
318 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
319 QVERIFY(!prop.method().isValid());
320 QCOMPARE(prop.type(), QQmlProperty::Property);
321 QCOMPARE(prop.isProperty(), true);
322 QCOMPARE(prop.isWritable(), false);
323 QCOMPARE(prop.isDesignable(), true);
324 QCOMPARE(prop.isResettable(), false);
325 QCOMPARE(prop.isSignalProperty(), false);
326 QCOMPARE(prop.isValid(), true);
327 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
328 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
329 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
330 QCOMPARE(prop.propertyTypeName(), "int");
331 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
332 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
333 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
334 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
335 QVERIFY(binding != 0);
336 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
337 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
338 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
339 QVERIFY(sigExprWatcher.wasDeleted());
340 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
341 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
347 void tst_qqmlproperty::qmlmetaproperty_object_string()
350 PropertyObject dobject;
353 QQmlProperty prop(&object, QString("defaultProperty"));
355 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
356 QVERIFY(binding != 0);
357 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
358 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
359 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
361 QObject *obj = new QObject;
363 QCOMPARE(prop.name(), QString());
364 QCOMPARE(prop.read(), QVariant());
365 QCOMPARE(prop.write(QVariant()), false);
366 QCOMPARE(prop.hasNotifySignal(), false);
367 QCOMPARE(prop.needsNotifySignal(), false);
368 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
369 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
370 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
371 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
372 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
373 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
374 QVERIFY(!prop.method().isValid());
375 QCOMPARE(prop.type(), QQmlProperty::Invalid);
376 QCOMPARE(prop.isProperty(), false);
377 QCOMPARE(prop.isWritable(), false);
378 QCOMPARE(prop.isDesignable(), false);
379 QCOMPARE(prop.isResettable(), false);
380 QCOMPARE(prop.isSignalProperty(), false);
381 QCOMPARE(prop.isValid(), false);
382 QCOMPARE(prop.object(), (QObject *)0);
383 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
384 QCOMPARE(prop.propertyType(), 0);
385 QCOMPARE(prop.propertyTypeName(), (const char *)0);
386 QVERIFY(prop.property().name() == 0);
387 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
388 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
389 QVERIFY(binding == 0);
390 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
391 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
392 QVERIFY(sigExprWatcher.wasDeleted());
393 QCOMPARE(prop.index(), -1);
394 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
400 QQmlProperty prop(&dobject, QString("defaultProperty"));
402 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
403 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
404 QVERIFY(binding != 0);
405 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
406 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
407 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
409 QObject *obj = new QObject;
411 QCOMPARE(prop.name(), QString("defaultProperty"));
412 QCOMPARE(prop.read(), QVariant(10));
413 QCOMPARE(prop.write(QVariant()), false);
414 QCOMPARE(prop.hasNotifySignal(), false);
415 QCOMPARE(prop.needsNotifySignal(), true);
416 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
417 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
418 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
419 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
420 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
421 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
422 QVERIFY(!prop.method().isValid());
423 QCOMPARE(prop.type(), QQmlProperty::Property);
424 QCOMPARE(prop.isProperty(), true);
425 QCOMPARE(prop.isWritable(), false);
426 QCOMPARE(prop.isDesignable(), true);
427 QCOMPARE(prop.isResettable(), false);
428 QCOMPARE(prop.isSignalProperty(), false);
429 QCOMPARE(prop.isValid(), true);
430 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
431 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
432 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
433 QCOMPARE(prop.propertyTypeName(), "int");
434 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
435 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
436 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
437 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
438 QVERIFY(binding != 0);
439 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
440 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
441 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
442 QVERIFY(sigExprWatcher.wasDeleted());
443 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
444 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
450 QQmlProperty prop(&dobject, QString("onClicked"));
452 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
453 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
454 QVERIFY(binding != 0);
455 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
456 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
457 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
459 QObject *obj = new QObject;
461 QCOMPARE(prop.name(), QString("onClicked"));
462 QCOMPARE(prop.read(), QVariant());
463 QCOMPARE(prop.write(QVariant("Hello")), false);
464 QCOMPARE(prop.hasNotifySignal(), false);
465 QCOMPARE(prop.needsNotifySignal(), false);
466 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
467 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
468 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
469 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
470 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
471 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
472 QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()"));
473 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
474 QCOMPARE(prop.isProperty(), false);
475 QCOMPARE(prop.isWritable(), false);
476 QCOMPARE(prop.isDesignable(), false);
477 QCOMPARE(prop.isResettable(), false);
478 QCOMPARE(prop.isSignalProperty(), true);
479 QCOMPARE(prop.isValid(), true);
480 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
481 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
482 QCOMPARE(prop.propertyType(), 0);
483 QCOMPARE(prop.propertyTypeName(), (const char *)0);
484 QCOMPARE(prop.property().name(), (const char *)0);
485 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
486 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
487 QVERIFY(binding == 0);
488 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
489 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
490 QVERIFY(!sigExprWatcher.wasDeleted());
491 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
492 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
493 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
499 QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
501 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
502 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
503 QVERIFY(binding != 0);
504 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
505 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
506 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
508 QObject *obj = new QObject;
510 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
511 QCOMPARE(prop.read(), QVariant());
512 QCOMPARE(prop.write(QVariant("Hello")), false);
513 QCOMPARE(prop.hasNotifySignal(), false);
514 QCOMPARE(prop.needsNotifySignal(), false);
515 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
516 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
517 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
518 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
519 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
520 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
521 QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()"));
522 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
523 QCOMPARE(prop.isProperty(), false);
524 QCOMPARE(prop.isWritable(), false);
525 QCOMPARE(prop.isDesignable(), false);
526 QCOMPARE(prop.isResettable(), false);
527 QCOMPARE(prop.isSignalProperty(), true);
528 QCOMPARE(prop.isValid(), true);
529 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
530 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
531 QCOMPARE(prop.propertyType(), 0);
532 QCOMPARE(prop.propertyTypeName(), (const char *)0);
533 QCOMPARE(prop.property().name(), (const char *)0);
534 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
535 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
536 QVERIFY(binding == 0);
537 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
538 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
539 QVERIFY(!sigExprWatcher.wasDeleted());
540 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
541 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
542 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
548 void tst_qqmlproperty::qmlmetaproperty_object_context()
550 QObject object; // Has no default property
551 PropertyObject dobject; // Has default property
554 QQmlProperty prop(&object, engine.rootContext());
556 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
557 QVERIFY(binding != 0);
558 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
559 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
560 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
562 QObject *obj = new QObject;
564 QCOMPARE(prop.name(), QString());
565 QCOMPARE(prop.read(), QVariant());
566 QCOMPARE(prop.write(QVariant()), false);
567 QCOMPARE(prop.hasNotifySignal(), false);
568 QCOMPARE(prop.needsNotifySignal(), false);
569 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
570 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
571 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
572 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
573 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
574 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
575 QVERIFY(!prop.method().isValid());
576 QCOMPARE(prop.type(), QQmlProperty::Invalid);
577 QCOMPARE(prop.isProperty(), false);
578 QCOMPARE(prop.isWritable(), false);
579 QCOMPARE(prop.isDesignable(), false);
580 QCOMPARE(prop.isResettable(), false);
581 QCOMPARE(prop.isSignalProperty(), false);
582 QCOMPARE(prop.isValid(), false);
583 QCOMPARE(prop.object(), (QObject *)0);
584 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
585 QCOMPARE(prop.propertyType(), 0);
586 QCOMPARE(prop.propertyTypeName(), (const char *)0);
587 QVERIFY(prop.property().name() == 0);
588 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
589 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
590 QVERIFY(binding == 0);
591 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
592 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
593 QVERIFY(sigExprWatcher.wasDeleted());
594 QCOMPARE(prop.index(), -1);
595 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
601 QQmlProperty prop(&dobject, engine.rootContext());
603 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
604 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
605 QVERIFY(binding != 0);
606 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
607 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
608 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
610 QObject *obj = new QObject;
612 QCOMPARE(prop.name(), QString("defaultProperty"));
613 QCOMPARE(prop.read(), QVariant(10));
614 QCOMPARE(prop.write(QVariant()), false);
615 QCOMPARE(prop.hasNotifySignal(), false);
616 QCOMPARE(prop.needsNotifySignal(), true);
617 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
618 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
619 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
620 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
621 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
622 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
623 QVERIFY(!prop.method().isValid());
624 QCOMPARE(prop.type(), QQmlProperty::Property);
625 QCOMPARE(prop.isProperty(), true);
626 QCOMPARE(prop.isWritable(), false);
627 QCOMPARE(prop.isDesignable(), true);
628 QCOMPARE(prop.isResettable(), false);
629 QCOMPARE(prop.isSignalProperty(), false);
630 QCOMPARE(prop.isValid(), true);
631 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
632 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
633 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
634 QCOMPARE(prop.propertyTypeName(), "int");
635 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
636 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
637 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
638 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
639 QVERIFY(binding != 0);
640 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
641 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
642 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
643 QVERIFY(sigExprWatcher.wasDeleted());
644 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
645 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
651 void tst_qqmlproperty::qmlmetaproperty_object_string_context()
654 PropertyObject dobject;
657 QQmlProperty prop(&object, QString("defaultProperty"), engine.rootContext());
659 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
660 QVERIFY(binding != 0);
661 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
662 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
663 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
665 QObject *obj = new QObject;
667 QCOMPARE(prop.name(), QString());
668 QCOMPARE(prop.read(), QVariant());
669 QCOMPARE(prop.write(QVariant()), false);
670 QCOMPARE(prop.hasNotifySignal(), false);
671 QCOMPARE(prop.needsNotifySignal(), false);
672 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
673 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
674 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
675 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
676 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
677 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
678 QVERIFY(!prop.method().isValid());
679 QCOMPARE(prop.type(), QQmlProperty::Invalid);
680 QCOMPARE(prop.isProperty(), false);
681 QCOMPARE(prop.isWritable(), false);
682 QCOMPARE(prop.isDesignable(), false);
683 QCOMPARE(prop.isResettable(), false);
684 QCOMPARE(prop.isSignalProperty(), false);
685 QCOMPARE(prop.isValid(), false);
686 QCOMPARE(prop.object(), (QObject *)0);
687 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
688 QCOMPARE(prop.propertyType(), 0);
689 QCOMPARE(prop.propertyTypeName(), (const char *)0);
690 QVERIFY(prop.property().name() == 0);
691 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
692 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
693 QVERIFY(binding == 0);
694 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
695 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
696 QVERIFY(sigExprWatcher.wasDeleted());
697 QCOMPARE(prop.index(), -1);
698 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
704 QQmlProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
706 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
707 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
708 QVERIFY(binding != 0);
709 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
710 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
711 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
713 QObject *obj = new QObject;
715 QCOMPARE(prop.name(), QString("defaultProperty"));
716 QCOMPARE(prop.read(), QVariant(10));
717 QCOMPARE(prop.write(QVariant()), false);
718 QCOMPARE(prop.hasNotifySignal(), false);
719 QCOMPARE(prop.needsNotifySignal(), true);
720 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
721 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
722 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
723 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
724 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
725 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
726 QVERIFY(!prop.method().isValid());
727 QCOMPARE(prop.type(), QQmlProperty::Property);
728 QCOMPARE(prop.isProperty(), true);
729 QCOMPARE(prop.isWritable(), false);
730 QCOMPARE(prop.isDesignable(), true);
731 QCOMPARE(prop.isResettable(), false);
732 QCOMPARE(prop.isSignalProperty(), false);
733 QCOMPARE(prop.isValid(), true);
734 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
735 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::Normal);
736 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
737 QCOMPARE(prop.propertyTypeName(), "int");
738 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
739 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
740 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
741 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
742 QVERIFY(binding != 0);
743 QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
744 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
745 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
746 QVERIFY(sigExprWatcher.wasDeleted());
747 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
748 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
754 QQmlProperty prop(&dobject, QString("onClicked"), engine.rootContext());
756 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
757 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
758 QVERIFY(binding != 0);
759 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
760 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
761 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
763 QObject *obj = new QObject;
765 QCOMPARE(prop.name(), QString("onClicked"));
766 QCOMPARE(prop.read(), QVariant());
767 QCOMPARE(prop.write(QVariant("Hello")), false);
768 QCOMPARE(prop.hasNotifySignal(), false);
769 QCOMPARE(prop.needsNotifySignal(), false);
770 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
771 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
772 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
773 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
774 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
775 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
776 QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()"));
777 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
778 QCOMPARE(prop.isProperty(), false);
779 QCOMPARE(prop.isWritable(), false);
780 QCOMPARE(prop.isDesignable(), false);
781 QCOMPARE(prop.isResettable(), false);
782 QCOMPARE(prop.isSignalProperty(), true);
783 QCOMPARE(prop.isValid(), true);
784 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
785 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
786 QCOMPARE(prop.propertyType(), 0);
787 QCOMPARE(prop.propertyTypeName(), (const char *)0);
788 QCOMPARE(prop.property().name(), (const char *)0);
789 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
790 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
791 QVERIFY(binding == 0);
792 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
793 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
794 QVERIFY(!sigExprWatcher.wasDeleted());
795 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
796 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
797 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
803 QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
805 QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
806 static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
807 QVERIFY(binding != 0);
808 QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
809 QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
810 QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
812 QObject *obj = new QObject;
814 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
815 QCOMPARE(prop.read(), QVariant());
816 QCOMPARE(prop.write(QVariant("Hello")), false);
817 QCOMPARE(prop.hasNotifySignal(), false);
818 QCOMPARE(prop.needsNotifySignal(), false);
819 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
820 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
821 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
822 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
823 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
824 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
825 QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()"));
826 QCOMPARE(prop.type(), QQmlProperty::SignalProperty);
827 QCOMPARE(prop.isProperty(), false);
828 QCOMPARE(prop.isWritable(), false);
829 QCOMPARE(prop.isDesignable(), false);
830 QCOMPARE(prop.isResettable(), false);
831 QCOMPARE(prop.isSignalProperty(), true);
832 QCOMPARE(prop.isValid(), true);
833 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
834 QCOMPARE(prop.propertyTypeCategory(), QQmlProperty::InvalidCategory);
835 QCOMPARE(prop.propertyType(), 0);
836 QCOMPARE(prop.propertyTypeName(), (const char *)0);
837 QCOMPARE(prop.property().name(), (const char *)0);
838 QVERIFY(QQmlPropertyPrivate::binding(prop) == 0);
839 QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
840 QVERIFY(binding == 0);
841 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
842 QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
843 QVERIFY(!sigExprWatcher.wasDeleted());
844 QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
845 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
846 QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
852 void tst_qqmlproperty::name()
856 QCOMPARE(p.name(), QString());
862 QCOMPARE(p.name(), QString("defaultProperty"));
867 QQmlProperty p(&o, QString("objectName"));
868 QCOMPARE(p.name(), QString("objectName"));
873 QQmlProperty p(&o, "onClicked");
874 QCOMPARE(p.name(), QString("onClicked"));
879 QQmlProperty p(&o, "onClicked");
880 QCOMPARE(p.name(), QString());
885 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
886 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
891 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
892 QCOMPARE(p.name(), QString());
897 QQmlProperty p(&o, "foo");
898 QCOMPARE(p.name(), QString());
902 QQmlProperty p(0, "foo");
903 QCOMPARE(p.name(), QString());
908 QQmlProperty p(&o, "rectProperty");
909 QCOMPARE(p.name(), QString("rectProperty"));
914 QQmlProperty p(&o, "rectProperty.x");
915 QCOMPARE(p.name(), QString("rectProperty.x"));
920 QQmlProperty p(&o, "rectProperty.foo");
921 QCOMPARE(p.name(), QString());
925 void tst_qqmlproperty::read()
930 QCOMPARE(p.read(), QVariant());
937 QCOMPARE(p.read(), QVariant(10));
940 // Invalid default prop
944 QCOMPARE(p.read(), QVariant());
947 // Value prop by name
951 QQmlProperty p(&o, "objectName");
952 QCOMPARE(p.read(), QVariant(QString()));
954 o.setObjectName("myName");
956 QCOMPARE(p.read(), QVariant("myName"));
959 // Value prop by name (static)
963 QCOMPARE(QQmlProperty::read(&o, "objectName"), QVariant(QString()));
965 o.setObjectName("myName");
967 QCOMPARE(QQmlProperty::read(&o, "objectName"), QVariant("myName"));
973 QQmlProperty p(&o, "rectProperty.x");
974 QCOMPARE(p.read(), QVariant(10));
977 // Invalid value-type prop
980 QQmlProperty p(&o, "rectProperty.foo");
981 QCOMPARE(p.read(), QVariant());
987 QQmlProperty p(&o, "onClicked");
988 QCOMPARE(p.read(), QVariant());
990 QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
991 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
993 QCOMPARE(p.read(), QVariant());
996 // Automatic signal property
999 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1000 QCOMPARE(p.read(), QVariant());
1002 QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1003 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1005 QCOMPARE(p.read(), QVariant());
1010 PropertyObject *o = new PropertyObject;
1011 QQmlProperty p(o, "rectProperty.x");
1012 QCOMPARE(p.read(), QVariant(10));
1014 QCOMPARE(p.read(), QVariant());
1020 QQmlProperty p(&o, "qmlObject");
1021 QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
1022 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
1023 QVariant v = p.read();
1024 QVERIFY(v.userType() == QMetaType::QObjectStar);
1025 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1028 QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1029 QObject *object = component.create();
1030 QVERIFY(object != 0);
1032 QQmlProperty p(object, "test", &engine);
1034 QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
1035 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1037 QVariant v = p.read();
1038 QVERIFY(v.userType() == QMetaType::QObjectStar);
1039 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1040 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1043 QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1044 QObject *object = component.create();
1045 QVERIFY(object != 0);
1047 QVariant v = QQmlProperty::read(object, "test", &engine);
1048 QVERIFY(v.userType() == QMetaType::QObjectStar);
1049 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1050 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1053 // Attached property
1055 QQmlComponent component(&engine);
1056 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1057 QObject *object = component.create();
1058 QVERIFY(object != 0);
1060 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1061 QCOMPARE(p.read(), QVariant(13));
1065 QQmlComponent component(&engine);
1066 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1067 QObject *object = component.create();
1068 QVERIFY(object != 0);
1070 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1071 QCOMPARE(p.read(), QVariant(10));
1075 QQmlComponent component(&engine);
1076 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1077 QObject *object = component.create();
1078 QVERIFY(object != 0);
1080 QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1081 QCOMPARE(p.read(), QVariant(10));
1085 QQmlComponent component(&engine);
1086 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1087 QObject *object = component.create();
1088 QVERIFY(object != 0);
1090 QCOMPARE(QQmlProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1095 void tst_qqmlproperty::write()
1100 QCOMPARE(p.write(QVariant(10)), false);
1103 // Read-only default prop
1107 QCOMPARE(p.write(QVariant(10)), false);
1110 // Invalid default prop
1114 QCOMPARE(p.write(QVariant(10)), false);
1117 // Read-only prop by name
1120 QQmlProperty p(&o, QString("defaultProperty"));
1121 QCOMPARE(p.write(QVariant(10)), false);
1124 // Writable prop by name
1127 QQmlProperty p(&o, QString("objectName"));
1128 QCOMPARE(o.objectName(), QString());
1129 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1130 QCOMPARE(o.objectName(), QString("myName"));
1133 // Writable prop by name (static)
1136 QCOMPARE(QQmlProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1137 QCOMPARE(o.objectName(), QString("myName"));
1142 PropertyObject *o = new PropertyObject;
1143 QQmlProperty p(o, QString("objectName"));
1144 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1145 QCOMPARE(o->objectName(), QString("myName"));
1149 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1155 QQmlProperty p(&o, "onClicked");
1156 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1158 QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1159 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1161 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1163 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1166 // Automatic signal property
1169 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1170 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1172 QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
1173 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1175 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1177 QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
1180 // Value-type property
1183 QQmlProperty p(&o, "wrectProperty");
1185 QCOMPARE(o.wrectProperty(), QRect());
1186 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1187 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1189 QQmlProperty p2(&o, "wrectProperty.x");
1190 QCOMPARE(p2.read(), QVariant(1));
1191 QCOMPARE(p2.write(QVariant(6)), true);
1192 QCOMPARE(p2.read(), QVariant(6));
1193 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1199 QQmlProperty p(&o, "url");
1201 QCOMPARE(p.write(QUrl("main.qml")), true);
1202 QCOMPARE(o.url(), QUrl("main.qml"));
1204 QQmlProperty p2(&o, "url", engine.rootContext());
1206 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1207 QVERIFY(result != QUrl("main.qml"));
1209 QCOMPARE(p2.write(QUrl("main.qml")), true);
1210 QCOMPARE(o.url(), result);
1215 QCOMPARE(QQmlProperty::write(&o, "url", QUrl("main.qml")), true);
1216 QCOMPARE(o.url(), QUrl("main.qml"));
1218 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1219 QVERIFY(result != QUrl("main.qml"));
1221 QCOMPARE(QQmlProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1222 QCOMPARE(o.url(), result);
1225 // VariantMap-property
1227 vm.insert("key", "value");
1231 QQmlProperty p(&o, "variantMap");
1233 QCOMPARE(p.write(vm), true);
1234 QCOMPARE(o.variantMap(), vm);
1236 QQmlProperty p2(&o, "variantMap", engine.rootContext());
1238 QCOMPARE(p2.write(vm), true);
1239 QCOMPARE(o.variantMap(), vm);
1244 QCOMPARE(QQmlProperty::write(&o, "variantMap", vm), true);
1245 QCOMPARE(o.variantMap(), vm);
1247 QCOMPARE(QQmlProperty::write(&o, "variantMap", vm, engine.rootContext()), true);
1248 QCOMPARE(o.variantMap(), vm);
1251 // Attached property
1253 QQmlComponent component(&engine);
1254 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1255 QObject *object = component.create();
1256 QVERIFY(object != 0);
1258 QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
1259 p.write(QVariant(99));
1260 QCOMPARE(p.read(), QVariant(99));
1264 QQmlComponent component(&engine);
1265 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1266 QObject *object = component.create();
1267 QVERIFY(object != 0);
1269 QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1270 p.write(QVariant(99));
1271 QCOMPARE(p.read(), QVariant(99));
1276 void tst_qqmlproperty::reset()
1281 QCOMPARE(p.isResettable(), false);
1282 QCOMPARE(p.reset(), false);
1285 // Read-only default prop
1289 QCOMPARE(p.isResettable(), false);
1290 QCOMPARE(p.reset(), false);
1293 // Invalid default prop
1297 QCOMPARE(p.isResettable(), false);
1298 QCOMPARE(p.reset(), false);
1301 // Non-resettable-only prop by name
1304 QQmlProperty p(&o, QString("defaultProperty"));
1305 QCOMPARE(p.isResettable(), false);
1306 QCOMPARE(p.reset(), false);
1309 // Resettable prop by name
1312 QQmlProperty p(&o, QString("resettableProperty"));
1314 QCOMPARE(p.read(), QVariant(9));
1315 QCOMPARE(p.write(QVariant(11)), true);
1316 QCOMPARE(p.read(), QVariant(11));
1318 QCOMPARE(p.isResettable(), true);
1319 QCOMPARE(p.reset(), true);
1321 QCOMPARE(p.read(), QVariant(9));
1326 PropertyObject *o = new PropertyObject;
1328 QQmlProperty p(o, QString("resettableProperty"));
1330 QCOMPARE(p.isResettable(), true);
1331 QCOMPARE(p.reset(), true);
1335 QCOMPARE(p.isResettable(), false);
1336 QCOMPARE(p.reset(), false);
1342 QQmlProperty p(&o, "onClicked");
1344 QCOMPARE(p.isResettable(), false);
1345 QCOMPARE(p.reset(), false);
1348 // Automatic signal property
1351 QQmlProperty p(&o, "onPropertyWithNotifyChanged");
1353 QCOMPARE(p.isResettable(), false);
1354 QCOMPARE(p.reset(), false);
1358 void tst_qqmlproperty::writeObjectToList()
1360 QQmlComponent containerComponent(&engine);
1361 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1362 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1363 QVERIFY(container != 0);
1364 QQmlListReference list(container, "children");
1365 QVERIFY(list.count() == 1);
1367 MyQmlObject *object = new MyQmlObject;
1368 QQmlProperty prop(container, "children");
1369 prop.write(qVariantFromValue(object));
1370 QCOMPARE(list.count(), 1);
1371 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1374 void tst_qqmlproperty::writeListToList()
1376 QQmlComponent containerComponent(&engine);
1377 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1378 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1379 QVERIFY(container != 0);
1380 QQmlListReference list(container, "children");
1381 QVERIFY(list.count() == 1);
1383 QList<QObject*> objList;
1384 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1385 QQmlProperty prop(container, "children");
1386 prop.write(qVariantFromValue(objList));
1387 QCOMPARE(list.count(), 4);
1389 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1390 /*QList<MyQmlObject*> typedObjList;
1391 typedObjList << new MyQmlObject();
1392 prop.write(qVariantFromValue(&typedObjList));
1393 QCOMPARE(container->children()->size(), 1);*/
1396 void tst_qqmlproperty::urlHandling_data()
1398 QTest::addColumn<QByteArray>("input");
1399 QTest::addColumn<QString>("scheme");
1400 QTest::addColumn<QString>("path");
1401 QTest::addColumn<QByteArray>("encoded");
1403 QTest::newRow("unspecifiedFile")
1404 << QByteArray("main.qml")
1406 << QString("main.qml")
1407 << QByteArray("main.qml");
1409 QTest::newRow("specifiedFile")
1410 << QByteArray("file:///main.qml")
1412 << QString("/main.qml")
1413 << QByteArray("file:///main.qml");
1415 QTest::newRow("httpFile")
1416 << QByteArray("http://www.example.com/main.qml")
1418 << QString("/main.qml")
1419 << QByteArray("http://www.example.com/main.qml");
1421 QTest::newRow("pathFile")
1422 << QByteArray("http://www.example.com/resources/main.qml")
1424 << QString("/resources/main.qml")
1425 << QByteArray("http://www.example.com/resources/main.qml");
1427 QTest::newRow("encodableName")
1428 << QByteArray("http://www.example.com/main file.qml")
1430 << QString("/main file.qml")
1431 << QByteArray("http://www.example.com/main%20file.qml");
1433 QTest::newRow("preencodedName")
1434 << QByteArray("http://www.example.com/resources%7Cmain%20file.qml")
1436 << QString("/resources|main file.qml")
1437 << QByteArray("http://www.example.com/resources%7Cmain%20file.qml");
1439 QTest::newRow("encodableQuery")
1440 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now working?")
1442 << QString("/main.qml")
1443 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now%20working?");
1445 QTest::newRow("preencodedQuery")
1446 << QByteArray("http://www.example.com/main.qml?type=text%2Fqml&comment=now working%3F")
1448 << QString("/main.qml")
1449 << QByteArray("http://www.example.com/main.qml?type=text%2Fqml&comment=now%20working%3F");
1451 QTest::newRow("encodableFragment")
1452 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000|volume+50%")
1454 << QString("/main.qml")
1455 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume+50%25");
1457 QTest::newRow("improperlyEncodedFragment")
1458 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume%2B50%")
1460 << QString("/main.qml")
1461 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%257Cvolume%252B50%25");
1464 void tst_qqmlproperty::urlHandling()
1466 QFETCH(QByteArray, input);
1467 QFETCH(QString, scheme);
1468 QFETCH(QString, path);
1469 QFETCH(QByteArray, encoded);
1471 QString inputString(QString::fromUtf8(input));
1475 QQmlProperty p(&o, "url");
1477 // Test url written as QByteArray
1478 QCOMPARE(p.write(input), true);
1479 QUrl byteArrayResult(o.url());
1481 QCOMPARE(byteArrayResult.scheme(), scheme);
1482 QCOMPARE(byteArrayResult.path(), path);
1483 QCOMPARE(byteArrayResult.toString(QUrl::FullyEncoded), QString::fromUtf8(encoded));
1484 QCOMPARE(byteArrayResult.toEncoded(), encoded);
1489 QQmlProperty p(&o, "url");
1491 // Test url written as QString
1492 QCOMPARE(p.write(inputString), true);
1493 QUrl stringResult(o.url());
1495 QCOMPARE(stringResult.scheme(), scheme);
1496 QCOMPARE(stringResult.path(), path);
1497 QCOMPARE(stringResult.toString(QUrl::FullyEncoded), QString::fromUtf8(encoded));
1498 QCOMPARE(stringResult.toEncoded(), encoded);
1502 void tst_qqmlproperty::variantMapHandling_data()
1504 QTest::addColumn<QVariantMap>("vm");
1509 QTest::newRow("{}") << m;
1513 m["a"] = QVariantMap();
1514 QTest::newRow("{ a:{} }") << m;
1521 QTest::newRow("{ a:{b:10, c:20} }") << m;
1526 m["b"] = QVariantList() << 20 << 30;
1527 QTest::newRow("{ a:10, b:[20, 30]}") << m;
1533 m["p"] = QVariantMap();
1534 QTest::newRow("var o={}; o.p=o") << m;
1539 m["q"] = QVariantMap();
1540 QTest::newRow("var o={}; o.p=123; o.q=o") << m;
1544 void tst_qqmlproperty::variantMapHandling()
1546 QFETCH(QVariantMap, vm);
1549 QQmlProperty p(&o, "variantMap");
1551 QCOMPARE(p.write(vm), true);
1552 QCOMPARE(o.variantMap(), vm);
1555 void tst_qqmlproperty::crashOnValueProperty()
1557 QQmlEngine *engine = new QQmlEngine;
1558 QQmlComponent component(engine);
1560 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1561 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1564 QQmlProperty p(obj, "wrectProperty.x", qmlContext(obj));
1565 QCOMPARE(p.name(), QString("wrectProperty.x"));
1567 QCOMPARE(p.read(), QVariant(10));
1569 //don't crash once the engine is deleted
1573 QCOMPARE(p.propertyTypeName(), "int");
1574 QCOMPARE(p.read(), QVariant(10));
1575 p.write(QVariant(20));
1576 QCOMPARE(p.read(), QVariant(20));
1580 void tst_qqmlproperty::aliasPropertyBindings()
1582 QQmlComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
1584 QObject *object = component.create();
1585 QVERIFY(object != 0);
1587 QCOMPARE(object->property("realProperty").toReal(), 90.);
1588 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1590 object->setProperty("test", 10);
1592 QCOMPARE(object->property("realProperty").toReal(), 110.);
1593 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1595 QQmlProperty realProperty(object, QLatin1String("realProperty"));
1596 QQmlProperty aliasProperty(object, QLatin1String("aliasProperty"));
1598 // Check there is a binding on these two properties
1599 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1600 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1602 // Check that its the same binding on these two properties
1603 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1604 QQmlPropertyPrivate::binding(aliasProperty));
1606 // Change the binding
1607 object->setProperty("state", QString("switch"));
1609 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1610 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1611 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1612 QQmlPropertyPrivate::binding(aliasProperty));
1614 QCOMPARE(object->property("realProperty").toReal(), 96.);
1615 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1617 // Check the old binding really has not effect any more
1618 object->setProperty("test", 4);
1620 QCOMPARE(object->property("realProperty").toReal(), 96.);
1621 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1623 object->setProperty("test2", 9);
1625 QCOMPARE(object->property("realProperty").toReal(), 288.);
1626 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1629 object->setProperty("state", QString(""));
1631 QVERIFY(QQmlPropertyPrivate::binding(realProperty) != 0);
1632 QVERIFY(QQmlPropertyPrivate::binding(aliasProperty) != 0);
1633 QCOMPARE(QQmlPropertyPrivate::binding(realProperty),
1634 QQmlPropertyPrivate::binding(aliasProperty));
1636 QCOMPARE(object->property("realProperty").toReal(), 20.);
1637 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1639 object->setProperty("test2", 3);
1641 QCOMPARE(object->property("realProperty").toReal(), 20.);
1642 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1647 void tst_qqmlproperty::copy()
1649 PropertyObject object;
1651 QQmlProperty *property = new QQmlProperty(&object, QLatin1String("defaultProperty"));
1652 QCOMPARE(property->name(), QString("defaultProperty"));
1653 QCOMPARE(property->read(), QVariant(10));
1654 QCOMPARE(property->type(), QQmlProperty::Property);
1655 QCOMPARE(property->propertyTypeCategory(), QQmlProperty::Normal);
1656 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1658 QQmlProperty p1(*property);
1659 QCOMPARE(p1.name(), QString("defaultProperty"));
1660 QCOMPARE(p1.read(), QVariant(10));
1661 QCOMPARE(p1.type(), QQmlProperty::Property);
1662 QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::Normal);
1663 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1665 QQmlProperty p2(&object, QLatin1String("url"));
1666 QCOMPARE(p2.name(), QString("url"));
1668 QCOMPARE(p2.name(), QString("defaultProperty"));
1669 QCOMPARE(p2.read(), QVariant(10));
1670 QCOMPARE(p2.type(), QQmlProperty::Property);
1671 QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::Normal);
1672 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1674 delete property; property = 0;
1676 QCOMPARE(p1.name(), QString("defaultProperty"));
1677 QCOMPARE(p1.read(), QVariant(10));
1678 QCOMPARE(p1.type(), QQmlProperty::Property);
1679 QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::Normal);
1680 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1682 QCOMPARE(p2.name(), QString("defaultProperty"));
1683 QCOMPARE(p2.read(), QVariant(10));
1684 QCOMPARE(p2.type(), QQmlProperty::Property);
1685 QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::Normal);
1686 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1689 void tst_qqmlproperty::noContext()
1691 QQmlComponent compA(&engine, testFileUrl("NoContextTypeA.qml"));
1692 QQmlComponent compB(&engine, testFileUrl("NoContextTypeB.qml"));
1694 QObject *a = compA.create();
1696 QObject *b = compB.create();
1699 QVERIFY(QQmlProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1705 void tst_qqmlproperty::assignEmptyVariantMap()
1710 map.insert("key", "value");
1711 o.setVariantMap(map);
1712 QCOMPARE(o.variantMap().count(), 1);
1713 QCOMPARE(o.variantMap().isEmpty(), false);
1715 QQmlContext context(&engine);
1716 context.setContextProperty("o", &o);
1718 QQmlComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml"));
1719 QObject *obj = component.create(&context);
1722 QCOMPARE(o.variantMap().count(), 0);
1723 QCOMPARE(o.variantMap().isEmpty(), true);
1728 void tst_qqmlproperty::warnOnInvalidBinding()
1730 QUrl testUrl(testFileUrl("invalidBinding.qml"));
1731 QString expectedWarning;
1733 // V4 error message for property-to-property binding
1734 expectedWarning = testUrl.toString() + QString::fromLatin1(":6:36: Unable to assign QQuickText to QQuickRectangle");
1735 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1737 // V8 error message for function-to-property binding
1738 expectedWarning = testUrl.toString() + QString::fromLatin1(":7:36: Unable to assign QQuickText to QQuickRectangle");
1739 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1741 // V8 error message for invalid binding to anchor
1742 expectedWarning = testUrl.toString() + QString::fromLatin1(":14: Unable to assign QQuickItem_QML_7 to QQuickAnchorLine");
1743 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
1745 QQmlComponent component(&engine, testUrl);
1746 QObject *obj = component.create();
1751 void tst_qqmlproperty::initTestCase()
1753 QQmlDataTest::initTestCase();
1754 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1755 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1756 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1759 QTEST_MAIN(tst_qqmlproperty)
1761 #include "tst_qqmlproperty.moc"