1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtDeclarative/qdeclarativecontext.h>
45 #include <QtDeclarative/qdeclarativeproperty.h>
46 #include <QtDeclarative/private/qdeclarativeproperty_p.h>
47 #include <private/qdeclarativebinding_p.h>
48 #include <QtWidgets/QLineEdit>
49 #include <QtCore/qfileinfo.h>
50 #include <QtCore/qdir.h>
51 #include "../../shared/util.h"
54 class MyQmlObject : public QObject
61 QML_DECLARE_TYPE(MyQmlObject);
63 class MyAttached : public QObject
66 Q_PROPERTY(int foo READ foo WRITE setFoo)
68 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
70 int foo() const { return m_foo; }
71 void setFoo(int f) { m_foo = f; }
77 class MyContainer : public QObject
80 Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children)
84 QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); }
86 static MyAttached *qmlAttachedProperties(QObject *o) {
87 return new MyAttached(o);
91 QList<MyQmlObject*> m_children;
94 QML_DECLARE_TYPE(MyContainer);
95 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
97 class tst_qdeclarativeproperty : public QDeclarativeDataTest
101 tst_qdeclarativeproperty() {}
107 void qmlmetaproperty();
108 void qmlmetaproperty_object();
109 void qmlmetaproperty_object_string();
110 void qmlmetaproperty_object_context();
111 void qmlmetaproperty_object_string_context();
120 void writeObjectToList();
121 void writeListToList();
125 void urlHandling_data();
128 void variantMapHandling_data();
129 void variantMapHandling();
132 void crashOnValueProperty();
133 void aliasPropertyBindings();
135 void assignEmptyVariantMap();
139 QDeclarativeEngine engine;
142 void tst_qdeclarativeproperty::qmlmetaproperty()
144 QDeclarativeProperty prop;
146 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
147 QVERIFY(binding != 0);
148 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
149 QVERIFY(expression != 0);
151 QObject *obj = new QObject;
153 QCOMPARE(prop.name(), QString());
154 QCOMPARE(prop.read(), QVariant());
155 QCOMPARE(prop.write(QVariant()), false);
156 QCOMPARE(prop.hasNotifySignal(), false);
157 QCOMPARE(prop.needsNotifySignal(), false);
158 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
159 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
160 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
161 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
162 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
163 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
164 QVERIFY(prop.method().signature() == 0);
165 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
166 QCOMPARE(prop.isProperty(), false);
167 QCOMPARE(prop.isWritable(), false);
168 QCOMPARE(prop.isDesignable(), false);
169 QCOMPARE(prop.isResettable(), false);
170 QCOMPARE(prop.isSignalProperty(), false);
171 QCOMPARE(prop.isValid(), false);
172 QCOMPARE(prop.object(), (QObject *)0);
173 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
174 QCOMPARE(prop.propertyType(), 0);
175 QCOMPARE(prop.propertyTypeName(), (const char *)0);
176 QVERIFY(prop.property().name() == 0);
177 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
178 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
179 QVERIFY(binding == 0);
180 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
181 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
182 QVERIFY(expression == 0);
183 QCOMPARE(prop.index(), -1);
184 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
189 class PropertyObject : public QObject
192 Q_PROPERTY(int defaultProperty READ defaultProperty)
193 Q_PROPERTY(QRect rectProperty READ rectProperty)
194 Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
195 Q_PROPERTY(QUrl url READ url WRITE setUrl)
196 Q_PROPERTY(QVariantMap variantMap READ variantMap WRITE setVariantMap)
197 Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
198 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
199 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
201 Q_CLASSINFO("DefaultProperty", "defaultProperty")
203 PropertyObject() : m_resetProperty(9) {}
205 int defaultProperty() { return 10; }
206 QRect rectProperty() { return QRect(10, 10, 1, 209); }
208 QRect wrectProperty() { return m_rect; }
209 void setWRectProperty(const QRect &r) { m_rect = r; }
211 QUrl url() { return m_url; }
212 void setUrl(const QUrl &u) { m_url = u; }
214 QVariantMap variantMap() const { return m_variantMap; }
215 void setVariantMap(const QVariantMap &variantMap) { m_variantMap = variantMap; }
217 int resettableProperty() const { return m_resetProperty; }
218 void setResettableProperty(int r) { m_resetProperty = r; }
219 void resetProperty() { m_resetProperty = 9; }
221 int propertyWithNotify() const { return m_propertyWithNotify; }
222 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
224 MyQmlObject *qmlObject() { return &m_qmlObject; }
228 void oddlyNamedNotifySignal();
234 QVariantMap m_variantMap;
235 int m_propertyWithNotify;
236 MyQmlObject m_qmlObject;
239 QML_DECLARE_TYPE(PropertyObject);
241 void tst_qdeclarativeproperty::qmlmetaproperty_object()
243 QObject object; // Has no default property
244 PropertyObject dobject; // Has default property
247 QDeclarativeProperty prop(&object);
249 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
250 QVERIFY(binding != 0);
251 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
252 QVERIFY(expression != 0);
254 QObject *obj = new QObject;
256 QCOMPARE(prop.name(), QString());
257 QCOMPARE(prop.read(), QVariant());
258 QCOMPARE(prop.write(QVariant()), false);
259 QCOMPARE(prop.hasNotifySignal(), false);
260 QCOMPARE(prop.needsNotifySignal(), false);
261 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
262 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
263 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
264 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
265 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
266 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
267 QVERIFY(prop.method().signature() == 0);
268 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
269 QCOMPARE(prop.isProperty(), false);
270 QCOMPARE(prop.isWritable(), false);
271 QCOMPARE(prop.isDesignable(), false);
272 QCOMPARE(prop.isResettable(), false);
273 QCOMPARE(prop.isSignalProperty(), false);
274 QCOMPARE(prop.isValid(), false);
275 QCOMPARE(prop.object(), (QObject *)0);
276 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
277 QCOMPARE(prop.propertyType(), 0);
278 QCOMPARE(prop.propertyTypeName(), (const char *)0);
279 QVERIFY(prop.property().name() == 0);
280 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
281 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
282 QVERIFY(binding == 0);
283 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
284 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
285 QVERIFY(expression == 0);
286 QCOMPARE(prop.index(), -1);
287 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
293 QDeclarativeProperty prop(&dobject);
295 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
296 binding.data()->setTarget(prop);
297 QVERIFY(binding != 0);
298 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
299 QVERIFY(expression != 0);
301 QObject *obj = new QObject;
303 QCOMPARE(prop.name(), QString("defaultProperty"));
304 QCOMPARE(prop.read(), QVariant(10));
305 QCOMPARE(prop.write(QVariant()), false);
306 QCOMPARE(prop.hasNotifySignal(), false);
307 QCOMPARE(prop.needsNotifySignal(), true);
308 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
309 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
310 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
311 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
312 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
313 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
314 QVERIFY(prop.method().signature() == 0);
315 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
316 QCOMPARE(prop.isProperty(), true);
317 QCOMPARE(prop.isWritable(), false);
318 QCOMPARE(prop.isDesignable(), true);
319 QCOMPARE(prop.isResettable(), false);
320 QCOMPARE(prop.isSignalProperty(), false);
321 QCOMPARE(prop.isValid(), true);
322 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
323 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
324 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
325 QCOMPARE(prop.propertyTypeName(), "int");
326 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
327 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
328 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
329 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
330 QVERIFY(binding != 0);
331 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
332 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
333 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
334 QVERIFY(expression == 0);
335 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
336 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
342 void tst_qdeclarativeproperty::qmlmetaproperty_object_string()
345 PropertyObject dobject;
348 QDeclarativeProperty prop(&object, QString("defaultProperty"));
350 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
351 QVERIFY(binding != 0);
352 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
353 QVERIFY(expression != 0);
355 QObject *obj = new QObject;
357 QCOMPARE(prop.name(), QString());
358 QCOMPARE(prop.read(), QVariant());
359 QCOMPARE(prop.write(QVariant()), false);
360 QCOMPARE(prop.hasNotifySignal(), false);
361 QCOMPARE(prop.needsNotifySignal(), false);
362 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
363 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
364 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
365 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
366 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
367 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
368 QVERIFY(prop.method().signature() == 0);
369 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
370 QCOMPARE(prop.isProperty(), false);
371 QCOMPARE(prop.isWritable(), false);
372 QCOMPARE(prop.isDesignable(), false);
373 QCOMPARE(prop.isResettable(), false);
374 QCOMPARE(prop.isSignalProperty(), false);
375 QCOMPARE(prop.isValid(), false);
376 QCOMPARE(prop.object(), (QObject *)0);
377 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
378 QCOMPARE(prop.propertyType(), 0);
379 QCOMPARE(prop.propertyTypeName(), (const char *)0);
380 QVERIFY(prop.property().name() == 0);
381 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
382 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
383 QVERIFY(binding == 0);
384 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
385 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
386 QVERIFY(expression == 0);
387 QCOMPARE(prop.index(), -1);
388 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
394 QDeclarativeProperty prop(&dobject, QString("defaultProperty"));
396 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
397 binding.data()->setTarget(prop);
398 QVERIFY(binding != 0);
399 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
400 QVERIFY(expression != 0);
402 QObject *obj = new QObject;
404 QCOMPARE(prop.name(), QString("defaultProperty"));
405 QCOMPARE(prop.read(), QVariant(10));
406 QCOMPARE(prop.write(QVariant()), false);
407 QCOMPARE(prop.hasNotifySignal(), false);
408 QCOMPARE(prop.needsNotifySignal(), true);
409 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
410 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
411 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
412 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
413 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
414 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
415 QVERIFY(prop.method().signature() == 0);
416 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
417 QCOMPARE(prop.isProperty(), true);
418 QCOMPARE(prop.isWritable(), false);
419 QCOMPARE(prop.isDesignable(), true);
420 QCOMPARE(prop.isResettable(), false);
421 QCOMPARE(prop.isSignalProperty(), false);
422 QCOMPARE(prop.isValid(), true);
423 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
424 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
425 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
426 QCOMPARE(prop.propertyTypeName(), "int");
427 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
428 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
429 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
430 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
431 QVERIFY(binding != 0);
432 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
433 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
434 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
435 QVERIFY(expression == 0);
436 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
437 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
443 QDeclarativeProperty prop(&dobject, QString("onClicked"));
445 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
446 binding.data()->setTarget(prop);
447 QVERIFY(binding != 0);
448 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
449 QVERIFY(expression != 0);
451 QObject *obj = new QObject;
453 QCOMPARE(prop.name(), QString("onClicked"));
454 QCOMPARE(prop.read(), QVariant());
455 QCOMPARE(prop.write(QVariant("Hello")), false);
456 QCOMPARE(prop.hasNotifySignal(), false);
457 QCOMPARE(prop.needsNotifySignal(), false);
458 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
459 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
460 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
461 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
462 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
463 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
464 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
465 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
466 QCOMPARE(prop.isProperty(), false);
467 QCOMPARE(prop.isWritable(), false);
468 QCOMPARE(prop.isDesignable(), false);
469 QCOMPARE(prop.isResettable(), false);
470 QCOMPARE(prop.isSignalProperty(), true);
471 QCOMPARE(prop.isValid(), true);
472 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
473 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
474 QCOMPARE(prop.propertyType(), 0);
475 QCOMPARE(prop.propertyTypeName(), (const char *)0);
476 QCOMPARE(prop.property().name(), (const char *)0);
477 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
478 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
479 QVERIFY(binding == 0);
480 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
481 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
482 QVERIFY(expression != 0);
483 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
484 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
485 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
491 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
493 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
494 binding.data()->setTarget(prop);
495 QVERIFY(binding != 0);
496 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
497 QVERIFY(expression != 0);
499 QObject *obj = new QObject;
501 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
502 QCOMPARE(prop.read(), QVariant());
503 QCOMPARE(prop.write(QVariant("Hello")), false);
504 QCOMPARE(prop.hasNotifySignal(), false);
505 QCOMPARE(prop.needsNotifySignal(), false);
506 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
507 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
508 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
509 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
510 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
511 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
512 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
513 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
514 QCOMPARE(prop.isProperty(), false);
515 QCOMPARE(prop.isWritable(), false);
516 QCOMPARE(prop.isDesignable(), false);
517 QCOMPARE(prop.isResettable(), false);
518 QCOMPARE(prop.isSignalProperty(), true);
519 QCOMPARE(prop.isValid(), true);
520 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
521 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
522 QCOMPARE(prop.propertyType(), 0);
523 QCOMPARE(prop.propertyTypeName(), (const char *)0);
524 QCOMPARE(prop.property().name(), (const char *)0);
525 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
526 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
527 QVERIFY(binding == 0);
528 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
529 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
530 QVERIFY(expression != 0);
531 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
532 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
533 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
539 void tst_qdeclarativeproperty::qmlmetaproperty_object_context()
541 QObject object; // Has no default property
542 PropertyObject dobject; // Has default property
545 QDeclarativeProperty prop(&object, engine.rootContext());
547 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
548 QVERIFY(binding != 0);
549 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
550 QVERIFY(expression != 0);
552 QObject *obj = new QObject;
554 QCOMPARE(prop.name(), QString());
555 QCOMPARE(prop.read(), QVariant());
556 QCOMPARE(prop.write(QVariant()), false);
557 QCOMPARE(prop.hasNotifySignal(), false);
558 QCOMPARE(prop.needsNotifySignal(), false);
559 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
560 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
561 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
562 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
563 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
564 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
565 QVERIFY(prop.method().signature() == 0);
566 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
567 QCOMPARE(prop.isProperty(), false);
568 QCOMPARE(prop.isWritable(), false);
569 QCOMPARE(prop.isDesignable(), false);
570 QCOMPARE(prop.isResettable(), false);
571 QCOMPARE(prop.isSignalProperty(), false);
572 QCOMPARE(prop.isValid(), false);
573 QCOMPARE(prop.object(), (QObject *)0);
574 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
575 QCOMPARE(prop.propertyType(), 0);
576 QCOMPARE(prop.propertyTypeName(), (const char *)0);
577 QVERIFY(prop.property().name() == 0);
578 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
579 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
580 QVERIFY(binding == 0);
581 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
582 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
583 QVERIFY(expression == 0);
584 QCOMPARE(prop.index(), -1);
585 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
591 QDeclarativeProperty prop(&dobject, engine.rootContext());
593 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
594 binding.data()->setTarget(prop);
595 QVERIFY(binding != 0);
596 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
597 QVERIFY(expression != 0);
599 QObject *obj = new QObject;
601 QCOMPARE(prop.name(), QString("defaultProperty"));
602 QCOMPARE(prop.read(), QVariant(10));
603 QCOMPARE(prop.write(QVariant()), false);
604 QCOMPARE(prop.hasNotifySignal(), false);
605 QCOMPARE(prop.needsNotifySignal(), true);
606 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
607 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
608 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
609 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
610 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
611 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
612 QVERIFY(prop.method().signature() == 0);
613 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
614 QCOMPARE(prop.isProperty(), true);
615 QCOMPARE(prop.isWritable(), false);
616 QCOMPARE(prop.isDesignable(), true);
617 QCOMPARE(prop.isResettable(), false);
618 QCOMPARE(prop.isSignalProperty(), false);
619 QCOMPARE(prop.isValid(), true);
620 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
621 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
622 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
623 QCOMPARE(prop.propertyTypeName(), "int");
624 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
625 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
626 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
627 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
628 QVERIFY(binding != 0);
629 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
630 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
631 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
632 QVERIFY(expression == 0);
633 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
634 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
640 void tst_qdeclarativeproperty::qmlmetaproperty_object_string_context()
643 PropertyObject dobject;
646 QDeclarativeProperty prop(&object, QString("defaultProperty"), engine.rootContext());
648 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
649 QVERIFY(binding != 0);
650 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
651 QVERIFY(expression != 0);
653 QObject *obj = new QObject;
655 QCOMPARE(prop.name(), QString());
656 QCOMPARE(prop.read(), QVariant());
657 QCOMPARE(prop.write(QVariant()), false);
658 QCOMPARE(prop.hasNotifySignal(), false);
659 QCOMPARE(prop.needsNotifySignal(), false);
660 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
661 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
662 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
663 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
664 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
665 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
666 QVERIFY(prop.method().signature() == 0);
667 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
668 QCOMPARE(prop.isProperty(), false);
669 QCOMPARE(prop.isWritable(), false);
670 QCOMPARE(prop.isDesignable(), false);
671 QCOMPARE(prop.isResettable(), false);
672 QCOMPARE(prop.isSignalProperty(), false);
673 QCOMPARE(prop.isValid(), false);
674 QCOMPARE(prop.object(), (QObject *)0);
675 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
676 QCOMPARE(prop.propertyType(), 0);
677 QCOMPARE(prop.propertyTypeName(), (const char *)0);
678 QVERIFY(prop.property().name() == 0);
679 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
680 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
681 QVERIFY(binding == 0);
682 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
683 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
684 QVERIFY(expression == 0);
685 QCOMPARE(prop.index(), -1);
686 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
692 QDeclarativeProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
694 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
695 binding.data()->setTarget(prop);
696 QVERIFY(binding != 0);
697 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
698 QVERIFY(expression != 0);
700 QObject *obj = new QObject;
702 QCOMPARE(prop.name(), QString("defaultProperty"));
703 QCOMPARE(prop.read(), QVariant(10));
704 QCOMPARE(prop.write(QVariant()), false);
705 QCOMPARE(prop.hasNotifySignal(), false);
706 QCOMPARE(prop.needsNotifySignal(), true);
707 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
708 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
709 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
710 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
711 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
712 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
713 QVERIFY(prop.method().signature() == 0);
714 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
715 QCOMPARE(prop.isProperty(), true);
716 QCOMPARE(prop.isWritable(), false);
717 QCOMPARE(prop.isDesignable(), true);
718 QCOMPARE(prop.isResettable(), false);
719 QCOMPARE(prop.isSignalProperty(), false);
720 QCOMPARE(prop.isValid(), true);
721 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
722 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
723 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
724 QCOMPARE(prop.propertyTypeName(), "int");
725 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
726 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
727 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
728 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
729 QVERIFY(binding != 0);
730 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
731 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
732 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
733 QVERIFY(expression == 0);
734 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
735 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
741 QDeclarativeProperty prop(&dobject, QString("onClicked"), engine.rootContext());
743 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
744 binding.data()->setTarget(prop);
745 QVERIFY(binding != 0);
746 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
747 QVERIFY(expression != 0);
749 QObject *obj = new QObject;
751 QCOMPARE(prop.name(), QString("onClicked"));
752 QCOMPARE(prop.read(), QVariant());
753 QCOMPARE(prop.write(QVariant("Hello")), false);
754 QCOMPARE(prop.hasNotifySignal(), false);
755 QCOMPARE(prop.needsNotifySignal(), false);
756 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
757 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
758 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
759 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
760 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
761 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
762 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
763 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
764 QCOMPARE(prop.isProperty(), false);
765 QCOMPARE(prop.isWritable(), false);
766 QCOMPARE(prop.isDesignable(), false);
767 QCOMPARE(prop.isResettable(), false);
768 QCOMPARE(prop.isSignalProperty(), true);
769 QCOMPARE(prop.isValid(), true);
770 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
771 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
772 QCOMPARE(prop.propertyType(), 0);
773 QCOMPARE(prop.propertyTypeName(), (const char *)0);
774 QCOMPARE(prop.property().name(), (const char *)0);
775 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
776 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
777 QVERIFY(binding == 0);
778 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
779 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
780 QVERIFY(expression != 0);
781 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
782 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
783 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
789 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
791 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
792 binding.data()->setTarget(prop);
793 QVERIFY(binding != 0);
794 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
795 QVERIFY(expression != 0);
797 QObject *obj = new QObject;
799 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
800 QCOMPARE(prop.read(), QVariant());
801 QCOMPARE(prop.write(QVariant("Hello")), false);
802 QCOMPARE(prop.hasNotifySignal(), false);
803 QCOMPARE(prop.needsNotifySignal(), false);
804 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
805 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
806 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
807 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
808 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
809 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
810 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
811 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
812 QCOMPARE(prop.isProperty(), false);
813 QCOMPARE(prop.isWritable(), false);
814 QCOMPARE(prop.isDesignable(), false);
815 QCOMPARE(prop.isResettable(), false);
816 QCOMPARE(prop.isSignalProperty(), true);
817 QCOMPARE(prop.isValid(), true);
818 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
819 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
820 QCOMPARE(prop.propertyType(), 0);
821 QCOMPARE(prop.propertyTypeName(), (const char *)0);
822 QCOMPARE(prop.property().name(), (const char *)0);
823 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
824 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
825 QVERIFY(binding == 0);
826 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
827 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
828 QVERIFY(expression != 0);
829 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
830 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
831 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
837 void tst_qdeclarativeproperty::name()
840 QDeclarativeProperty p;
841 QCOMPARE(p.name(), QString());
846 QDeclarativeProperty p(&o);
847 QCOMPARE(p.name(), QString("defaultProperty"));
852 QDeclarativeProperty p(&o, QString("objectName"));
853 QCOMPARE(p.name(), QString("objectName"));
858 QDeclarativeProperty p(&o, "onClicked");
859 QCOMPARE(p.name(), QString("onClicked"));
864 QDeclarativeProperty p(&o, "onClicked");
865 QCOMPARE(p.name(), QString());
870 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
871 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
876 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
877 QCOMPARE(p.name(), QString());
882 QDeclarativeProperty p(&o, "foo");
883 QCOMPARE(p.name(), QString());
887 QDeclarativeProperty p(0, "foo");
888 QCOMPARE(p.name(), QString());
893 QDeclarativeProperty p(&o, "rectProperty");
894 QCOMPARE(p.name(), QString("rectProperty"));
899 QDeclarativeProperty p(&o, "rectProperty.x");
900 QCOMPARE(p.name(), QString("rectProperty.x"));
905 QDeclarativeProperty p(&o, "rectProperty.foo");
906 QCOMPARE(p.name(), QString());
910 void tst_qdeclarativeproperty::read()
914 QDeclarativeProperty p;
915 QCOMPARE(p.read(), QVariant());
921 QDeclarativeProperty p(&o);
922 QCOMPARE(p.read(), QVariant(10));
925 // Invalid default prop
928 QDeclarativeProperty p(&o);
929 QCOMPARE(p.read(), QVariant());
932 // Value prop by name
936 QDeclarativeProperty p(&o, "objectName");
937 QCOMPARE(p.read(), QVariant(QString()));
939 o.setObjectName("myName");
941 QCOMPARE(p.read(), QVariant("myName"));
944 // Value prop by name (static)
948 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant(QString()));
950 o.setObjectName("myName");
952 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant("myName"));
958 QDeclarativeProperty p(&o, "rectProperty.x");
959 QCOMPARE(p.read(), QVariant(10));
962 // Invalid value-type prop
965 QDeclarativeProperty p(&o, "rectProperty.foo");
966 QCOMPARE(p.read(), QVariant());
972 QDeclarativeProperty p(&o, "onClicked");
973 QCOMPARE(p.read(), QVariant());
975 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
976 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
978 QCOMPARE(p.read(), QVariant());
981 // Automatic signal property
984 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
985 QCOMPARE(p.read(), QVariant());
987 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
988 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
990 QCOMPARE(p.read(), QVariant());
995 PropertyObject *o = new PropertyObject;
996 QDeclarativeProperty p(o, "rectProperty.x");
997 QCOMPARE(p.read(), QVariant(10));
999 QCOMPARE(p.read(), QVariant());
1005 QDeclarativeProperty p(&o, "qmlObject");
1006 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1007 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
1008 QVariant v = p.read();
1009 QVERIFY(v.userType() == QMetaType::QObjectStar);
1010 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1013 QDeclarativeComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1014 QObject *object = component.create();
1015 QVERIFY(object != 0);
1017 QDeclarativeProperty p(object, "test", &engine);
1019 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1020 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1022 QVariant v = p.read();
1023 QVERIFY(v.userType() == QMetaType::QObjectStar);
1024 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1025 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1028 QDeclarativeComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1029 QObject *object = component.create();
1030 QVERIFY(object != 0);
1032 QVariant v = QDeclarativeProperty::read(object, "test", &engine);
1033 QVERIFY(v.userType() == QMetaType::QObjectStar);
1034 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1035 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1038 // Attached property
1040 QDeclarativeComponent component(&engine);
1041 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1042 QObject *object = component.create();
1043 QVERIFY(object != 0);
1045 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1046 QCOMPARE(p.read(), QVariant(13));
1050 QDeclarativeComponent component(&engine);
1051 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1052 QObject *object = component.create();
1053 QVERIFY(object != 0);
1055 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1056 QCOMPARE(p.read(), QVariant(10));
1060 QDeclarativeComponent component(&engine);
1061 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1062 QObject *object = component.create();
1063 QVERIFY(object != 0);
1065 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1066 QCOMPARE(p.read(), QVariant(10));
1070 QDeclarativeComponent component(&engine);
1071 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1072 QObject *object = component.create();
1073 QVERIFY(object != 0);
1075 QCOMPARE(QDeclarativeProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1080 void tst_qdeclarativeproperty::write()
1084 QDeclarativeProperty p;
1085 QCOMPARE(p.write(QVariant(10)), false);
1088 // Read-only default prop
1091 QDeclarativeProperty p(&o);
1092 QCOMPARE(p.write(QVariant(10)), false);
1095 // Invalid default prop
1098 QDeclarativeProperty p(&o);
1099 QCOMPARE(p.write(QVariant(10)), false);
1102 // Read-only prop by name
1105 QDeclarativeProperty p(&o, QString("defaultProperty"));
1106 QCOMPARE(p.write(QVariant(10)), false);
1109 // Writable prop by name
1112 QDeclarativeProperty p(&o, QString("objectName"));
1113 QCOMPARE(o.objectName(), QString());
1114 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1115 QCOMPARE(o.objectName(), QString("myName"));
1118 // Writable prop by name (static)
1121 QCOMPARE(QDeclarativeProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1122 QCOMPARE(o.objectName(), QString("myName"));
1127 PropertyObject *o = new PropertyObject;
1128 QDeclarativeProperty p(o, QString("objectName"));
1129 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1130 QCOMPARE(o->objectName(), QString("myName"));
1134 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1140 QDeclarativeProperty p(&o, "onClicked");
1141 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1143 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1144 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1146 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1148 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1151 // Automatic signal property
1154 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1155 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1157 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1158 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1160 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1162 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1165 // Value-type property
1168 QDeclarativeProperty p(&o, "wrectProperty");
1170 QCOMPARE(o.wrectProperty(), QRect());
1171 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1172 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1174 QDeclarativeProperty p2(&o, "wrectProperty.x");
1175 QCOMPARE(p2.read(), QVariant(1));
1176 QCOMPARE(p2.write(QVariant(6)), true);
1177 QCOMPARE(p2.read(), QVariant(6));
1178 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1184 QDeclarativeProperty p(&o, "url");
1186 QCOMPARE(p.write(QUrl("main.qml")), true);
1187 QCOMPARE(o.url(), QUrl("main.qml"));
1189 QDeclarativeProperty p2(&o, "url", engine.rootContext());
1191 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1192 QVERIFY(result != QUrl("main.qml"));
1194 QCOMPARE(p2.write(QUrl("main.qml")), true);
1195 QCOMPARE(o.url(), result);
1200 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml")), true);
1201 QCOMPARE(o.url(), QUrl("main.qml"));
1203 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1204 QVERIFY(result != QUrl("main.qml"));
1206 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1207 QCOMPARE(o.url(), result);
1210 // VariantMap-property
1212 vm.insert("key", "value");
1216 QDeclarativeProperty p(&o, "variantMap");
1218 QCOMPARE(p.write(vm), true);
1219 QCOMPARE(o.variantMap(), vm);
1221 QDeclarativeProperty p2(&o, "variantMap", engine.rootContext());
1223 QCOMPARE(p2.write(vm), true);
1224 QCOMPARE(o.variantMap(), vm);
1229 QCOMPARE(QDeclarativeProperty::write(&o, "variantMap", vm), true);
1230 QCOMPARE(o.variantMap(), vm);
1232 QCOMPARE(QDeclarativeProperty::write(&o, "variantMap", vm, engine.rootContext()), true);
1233 QCOMPARE(o.variantMap(), vm);
1236 // Attached property
1238 QDeclarativeComponent component(&engine);
1239 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1240 QObject *object = component.create();
1241 QVERIFY(object != 0);
1243 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1244 p.write(QVariant(99));
1245 QCOMPARE(p.read(), QVariant(99));
1249 QDeclarativeComponent component(&engine);
1250 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1251 QObject *object = component.create();
1252 QVERIFY(object != 0);
1254 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1255 p.write(QVariant(99));
1256 QCOMPARE(p.read(), QVariant(99));
1261 void tst_qdeclarativeproperty::reset()
1265 QDeclarativeProperty p;
1266 QCOMPARE(p.isResettable(), false);
1267 QCOMPARE(p.reset(), false);
1270 // Read-only default prop
1273 QDeclarativeProperty p(&o);
1274 QCOMPARE(p.isResettable(), false);
1275 QCOMPARE(p.reset(), false);
1278 // Invalid default prop
1281 QDeclarativeProperty p(&o);
1282 QCOMPARE(p.isResettable(), false);
1283 QCOMPARE(p.reset(), false);
1286 // Non-resettable-only prop by name
1289 QDeclarativeProperty p(&o, QString("defaultProperty"));
1290 QCOMPARE(p.isResettable(), false);
1291 QCOMPARE(p.reset(), false);
1294 // Resettable prop by name
1297 QDeclarativeProperty p(&o, QString("resettableProperty"));
1299 QCOMPARE(p.read(), QVariant(9));
1300 QCOMPARE(p.write(QVariant(11)), true);
1301 QCOMPARE(p.read(), QVariant(11));
1303 QCOMPARE(p.isResettable(), true);
1304 QCOMPARE(p.reset(), true);
1306 QCOMPARE(p.read(), QVariant(9));
1311 PropertyObject *o = new PropertyObject;
1313 QDeclarativeProperty p(o, QString("resettableProperty"));
1315 QCOMPARE(p.isResettable(), true);
1316 QCOMPARE(p.reset(), true);
1320 QCOMPARE(p.isResettable(), false);
1321 QCOMPARE(p.reset(), false);
1327 QDeclarativeProperty p(&o, "onClicked");
1329 QCOMPARE(p.isResettable(), false);
1330 QCOMPARE(p.reset(), false);
1333 // Automatic signal property
1336 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1338 QCOMPARE(p.isResettable(), false);
1339 QCOMPARE(p.reset(), false);
1343 void tst_qdeclarativeproperty::writeObjectToList()
1345 QDeclarativeComponent containerComponent(&engine);
1346 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1347 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1348 QVERIFY(container != 0);
1349 QDeclarativeListReference list(container, "children");
1350 QVERIFY(list.count() == 1);
1352 MyQmlObject *object = new MyQmlObject;
1353 QDeclarativeProperty prop(container, "children");
1354 prop.write(qVariantFromValue(object));
1355 QCOMPARE(list.count(), 1);
1356 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1359 void tst_qdeclarativeproperty::writeListToList()
1361 QDeclarativeComponent containerComponent(&engine);
1362 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1363 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1364 QVERIFY(container != 0);
1365 QDeclarativeListReference list(container, "children");
1366 QVERIFY(list.count() == 1);
1368 QList<QObject*> objList;
1369 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1370 QDeclarativeProperty prop(container, "children");
1371 prop.write(qVariantFromValue(objList));
1372 QCOMPARE(list.count(), 4);
1374 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1375 /*QList<MyQmlObject*> typedObjList;
1376 typedObjList << new MyQmlObject();
1377 prop.write(qVariantFromValue(&typedObjList));
1378 QCOMPARE(container->children()->size(), 1);*/
1381 void tst_qdeclarativeproperty::urlHandling_data()
1383 QTest::addColumn<QByteArray>("input");
1384 QTest::addColumn<QString>("scheme");
1385 QTest::addColumn<QString>("path");
1386 QTest::addColumn<QByteArray>("encoded");
1388 QTest::newRow("unspecifiedFile")
1389 << QByteArray("main.qml")
1391 << QString("main.qml")
1392 << QByteArray("main.qml");
1394 QTest::newRow("specifiedFile")
1395 << QByteArray("file:///main.qml")
1397 << QString("/main.qml")
1398 << QByteArray("file:///main.qml");
1400 QTest::newRow("httpFile")
1401 << QByteArray("http://www.example.com/main.qml")
1403 << QString("/main.qml")
1404 << QByteArray("http://www.example.com/main.qml");
1406 QTest::newRow("pathFile")
1407 << QByteArray("http://www.example.com/resources/main.qml")
1409 << QString("/resources/main.qml")
1410 << QByteArray("http://www.example.com/resources/main.qml");
1412 QTest::newRow("encodableName")
1413 << QByteArray("http://www.example.com/main file.qml")
1415 << QString("/main file.qml")
1416 << QByteArray("http://www.example.com/main%20file.qml");
1418 QTest::newRow("preencodedName")
1419 << QByteArray("http://www.example.com/resources%7cmain%20file.qml")
1421 << QString("/resources|main file.qml")
1422 << QByteArray("http://www.example.com/resources%7cmain%20file.qml");
1424 QTest::newRow("encodableQuery")
1425 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now working?")
1427 << QString("/main.qml")
1428 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now%20working?");
1430 QTest::newRow("preencodedQuery")
1431 << QByteArray("http://www.example.com/main.qml?type=text%2fqml&comment=now working%3f")
1433 << QString("/main.qml")
1434 << QByteArray("http://www.example.com/main.qml?type=text%2fqml&comment=now%20working%3f");
1436 QTest::newRow("encodableFragment")
1437 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000|volume+50%")
1439 << QString("/main.qml")
1440 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume+50%25");
1442 QTest::newRow("preencodedFragment")
1443 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7cvolume%2b50%")
1445 << QString("/main.qml")
1446 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7cvolume%2b50%25");
1449 void tst_qdeclarativeproperty::urlHandling()
1451 QFETCH(QByteArray, input);
1452 QFETCH(QString, scheme);
1453 QFETCH(QString, path);
1454 QFETCH(QByteArray, encoded);
1456 QString inputString(QString::fromUtf8(input));
1460 QDeclarativeProperty p(&o, "url");
1462 // Test url written as QByteArray
1463 QCOMPARE(p.write(input), true);
1464 QUrl byteArrayResult(o.url());
1466 QCOMPARE(byteArrayResult.scheme(), scheme);
1467 QCOMPARE(byteArrayResult.path(), path);
1468 QCOMPARE(byteArrayResult.toEncoded(), encoded);
1473 QDeclarativeProperty p(&o, "url");
1475 // Test url written as QString
1476 QCOMPARE(p.write(inputString), true);
1477 QUrl stringResult(o.url());
1479 QCOMPARE(stringResult.scheme(), scheme);
1480 QCOMPARE(stringResult.path(), path);
1481 QCOMPARE(stringResult.toEncoded(), encoded);
1485 void tst_qdeclarativeproperty::variantMapHandling_data()
1487 QTest::addColumn<QVariantMap>("vm");
1492 QTest::newRow("{}") << m;
1496 m["a"] = QVariantMap();
1497 QTest::newRow("{ a:{} }") << m;
1504 QTest::newRow("{ a:{b:10, c:20} }") << m;
1509 m["b"] = QVariantList() << 20 << 30;
1510 QTest::newRow("{ a:10, b:[20, 30]}") << m;
1516 m["p"] = QVariantMap();
1517 QTest::newRow("var o={}; o.p=o") << m;
1522 m["q"] = QVariantMap();
1523 QTest::newRow("var o={}; o.p=123; o.q=o") << m;
1527 void tst_qdeclarativeproperty::variantMapHandling()
1529 QFETCH(QVariantMap, vm);
1532 QDeclarativeProperty p(&o, "variantMap");
1534 QCOMPARE(p.write(vm), true);
1535 QCOMPARE(o.variantMap(), vm);
1538 void tst_qdeclarativeproperty::crashOnValueProperty()
1540 QDeclarativeEngine *engine = new QDeclarativeEngine;
1541 QDeclarativeComponent component(engine);
1543 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1544 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1547 QDeclarativeProperty p(obj, "wrectProperty.x", qmlContext(obj));
1548 QCOMPARE(p.name(), QString("wrectProperty.x"));
1550 QCOMPARE(p.read(), QVariant(10));
1552 //don't crash once the engine is deleted
1556 QCOMPARE(p.propertyTypeName(), "int");
1557 QCOMPARE(p.read(), QVariant(10));
1558 p.write(QVariant(20));
1559 QCOMPARE(p.read(), QVariant(20));
1563 void tst_qdeclarativeproperty::aliasPropertyBindings()
1565 QDeclarativeComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
1567 QObject *object = component.create();
1568 QVERIFY(object != 0);
1570 QCOMPARE(object->property("realProperty").toReal(), 90.);
1571 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1573 object->setProperty("test", 10);
1575 QCOMPARE(object->property("realProperty").toReal(), 110.);
1576 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1578 QDeclarativeProperty realProperty(object, QLatin1String("realProperty"));
1579 QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty"));
1581 // Check there is a binding on these two properties
1582 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1583 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1585 // Check that its the same binding on these two properties
1586 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1587 QDeclarativePropertyPrivate::binding(aliasProperty));
1589 // Change the binding
1590 object->setProperty("state", QString("switch"));
1592 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1593 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1594 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1595 QDeclarativePropertyPrivate::binding(aliasProperty));
1597 QCOMPARE(object->property("realProperty").toReal(), 96.);
1598 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1600 // Check the old binding really has not effect any more
1601 object->setProperty("test", 4);
1603 QCOMPARE(object->property("realProperty").toReal(), 96.);
1604 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1606 object->setProperty("test2", 9);
1608 QCOMPARE(object->property("realProperty").toReal(), 288.);
1609 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1612 object->setProperty("state", QString(""));
1614 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1615 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1616 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1617 QDeclarativePropertyPrivate::binding(aliasProperty));
1619 QCOMPARE(object->property("realProperty").toReal(), 20.);
1620 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1622 object->setProperty("test2", 3);
1624 QCOMPARE(object->property("realProperty").toReal(), 20.);
1625 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1630 void tst_qdeclarativeproperty::copy()
1632 PropertyObject object;
1634 QDeclarativeProperty *property = new QDeclarativeProperty(&object, QLatin1String("defaultProperty"));
1635 QCOMPARE(property->name(), QString("defaultProperty"));
1636 QCOMPARE(property->read(), QVariant(10));
1637 QCOMPARE(property->type(), QDeclarativeProperty::Property);
1638 QCOMPARE(property->propertyTypeCategory(), QDeclarativeProperty::Normal);
1639 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1641 QDeclarativeProperty p1(*property);
1642 QCOMPARE(p1.name(), QString("defaultProperty"));
1643 QCOMPARE(p1.read(), QVariant(10));
1644 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1645 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1646 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1648 QDeclarativeProperty p2(&object, QLatin1String("url"));
1649 QCOMPARE(p2.name(), QString("url"));
1651 QCOMPARE(p2.name(), QString("defaultProperty"));
1652 QCOMPARE(p2.read(), QVariant(10));
1653 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1654 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1655 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1657 delete property; property = 0;
1659 QCOMPARE(p1.name(), QString("defaultProperty"));
1660 QCOMPARE(p1.read(), QVariant(10));
1661 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1662 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1663 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1665 QCOMPARE(p2.name(), QString("defaultProperty"));
1666 QCOMPARE(p2.read(), QVariant(10));
1667 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1668 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1669 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1672 void tst_qdeclarativeproperty::noContext()
1674 QDeclarativeComponent compA(&engine, testFileUrl("NoContextTypeA.qml"));
1675 QDeclarativeComponent compB(&engine, testFileUrl("NoContextTypeB.qml"));
1677 QObject *a = compA.create();
1679 QObject *b = compB.create();
1682 QVERIFY(QDeclarativeProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1688 void tst_qdeclarativeproperty::assignEmptyVariantMap()
1693 map.insert("key", "value");
1694 o.setVariantMap(map);
1695 QCOMPARE(o.variantMap().count(), 1);
1696 QCOMPARE(o.variantMap().isEmpty(), false);
1698 QDeclarativeContext context(&engine);
1699 context.setContextProperty("o", &o);
1701 QDeclarativeComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml"));
1702 QObject *obj = component.create(&context);
1705 QCOMPARE(o.variantMap().count(), 0);
1706 QCOMPARE(o.variantMap().isEmpty(), true);
1711 void tst_qdeclarativeproperty::initTestCase()
1713 QDeclarativeDataTest::initTestCase();
1714 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1715 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1716 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1719 QTEST_MAIN(tst_qdeclarativeproperty)
1721 #include "tst_qdeclarativeproperty.moc"