1 /****************************************************************************
3 ** Copyright (C) 2011 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/qdeclarativeproperty.h>
45 #include <QtDeclarative/private/qdeclarativeproperty_p.h>
46 #include <private/qdeclarativebinding_p.h>
47 #include <QtWidgets/QLineEdit>
48 #include <QtCore/qfileinfo.h>
49 #include <QtCore/qdir.h>
51 inline QUrl TEST_FILE(const QString &filename)
53 QFileInfo fileInfo(__FILE__);
54 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(QLatin1String("data/") + filename));
57 class MyQmlObject : public QObject
64 QML_DECLARE_TYPE(MyQmlObject);
66 class MyAttached : public QObject
69 Q_PROPERTY(int foo READ foo WRITE setFoo)
71 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
73 int foo() const { return m_foo; }
74 void setFoo(int f) { m_foo = f; }
80 class MyContainer : public QObject
83 Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children)
87 QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); }
89 static MyAttached *qmlAttachedProperties(QObject *o) {
90 return new MyAttached(o);
94 QList<MyQmlObject*> m_children;
97 QML_DECLARE_TYPE(MyContainer);
98 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
100 class tst_qdeclarativeproperty : public QObject
104 tst_qdeclarativeproperty() {}
110 void qmlmetaproperty();
111 void qmlmetaproperty_object();
112 void qmlmetaproperty_object_string();
113 void qmlmetaproperty_object_context();
114 void qmlmetaproperty_object_string_context();
123 void writeObjectToList();
124 void writeListToList();
129 void crashOnValueProperty();
130 void aliasPropertyBindings();
135 QDeclarativeEngine engine;
138 void tst_qdeclarativeproperty::qmlmetaproperty()
140 QDeclarativeProperty prop;
142 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
143 QVERIFY(binding != 0);
144 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
145 QVERIFY(expression != 0);
147 QObject *obj = new QObject;
149 QCOMPARE(prop.name(), QString());
150 QCOMPARE(prop.read(), QVariant());
151 QCOMPARE(prop.write(QVariant()), false);
152 QCOMPARE(prop.hasNotifySignal(), false);
153 QCOMPARE(prop.needsNotifySignal(), false);
154 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
155 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
156 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
157 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
158 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
159 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
160 QVERIFY(prop.method().signature() == 0);
161 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
162 QCOMPARE(prop.isProperty(), false);
163 QCOMPARE(prop.isWritable(), false);
164 QCOMPARE(prop.isDesignable(), false);
165 QCOMPARE(prop.isResettable(), false);
166 QCOMPARE(prop.isSignalProperty(), false);
167 QCOMPARE(prop.isValid(), false);
168 QCOMPARE(prop.object(), (QObject *)0);
169 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
170 QCOMPARE(prop.propertyType(), 0);
171 QCOMPARE(prop.propertyTypeName(), (const char *)0);
172 QVERIFY(prop.property().name() == 0);
173 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
174 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
175 QVERIFY(binding == 0);
176 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
177 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
178 QVERIFY(expression == 0);
179 QCOMPARE(prop.index(), -1);
180 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
185 class PropertyObject : public QObject
188 Q_PROPERTY(int defaultProperty READ defaultProperty)
189 Q_PROPERTY(QRect rectProperty READ rectProperty)
190 Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
191 Q_PROPERTY(QUrl url READ url WRITE setUrl)
192 Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
193 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
194 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
196 Q_CLASSINFO("DefaultProperty", "defaultProperty")
198 PropertyObject() : m_resetProperty(9) {}
200 int defaultProperty() { return 10; }
201 QRect rectProperty() { return QRect(10, 10, 1, 209); }
203 QRect wrectProperty() { return m_rect; }
204 void setWRectProperty(const QRect &r) { m_rect = r; }
206 QUrl url() { return m_url; }
207 void setUrl(const QUrl &u) { m_url = u; }
209 int resettableProperty() const { return m_resetProperty; }
210 void setResettableProperty(int r) { m_resetProperty = r; }
211 void resetProperty() { m_resetProperty = 9; }
213 int propertyWithNotify() const { return m_propertyWithNotify; }
214 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
216 MyQmlObject *qmlObject() { return &m_qmlObject; }
219 void oddlyNamedNotifySignal();
225 int m_propertyWithNotify;
226 MyQmlObject m_qmlObject;
229 QML_DECLARE_TYPE(PropertyObject);
231 void tst_qdeclarativeproperty::qmlmetaproperty_object()
233 QObject object; // Has no default property
234 PropertyObject dobject; // Has default property
237 QDeclarativeProperty prop(&object);
239 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
240 QVERIFY(binding != 0);
241 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
242 QVERIFY(expression != 0);
244 QObject *obj = new QObject;
246 QCOMPARE(prop.name(), QString());
247 QCOMPARE(prop.read(), QVariant());
248 QCOMPARE(prop.write(QVariant()), false);
249 QCOMPARE(prop.hasNotifySignal(), false);
250 QCOMPARE(prop.needsNotifySignal(), false);
251 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
252 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
253 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
254 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
255 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
256 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
257 QVERIFY(prop.method().signature() == 0);
258 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
259 QCOMPARE(prop.isProperty(), false);
260 QCOMPARE(prop.isWritable(), false);
261 QCOMPARE(prop.isDesignable(), false);
262 QCOMPARE(prop.isResettable(), false);
263 QCOMPARE(prop.isSignalProperty(), false);
264 QCOMPARE(prop.isValid(), false);
265 QCOMPARE(prop.object(), (QObject *)0);
266 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
267 QCOMPARE(prop.propertyType(), 0);
268 QCOMPARE(prop.propertyTypeName(), (const char *)0);
269 QVERIFY(prop.property().name() == 0);
270 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
271 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
272 QVERIFY(binding == 0);
273 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
274 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
275 QVERIFY(expression == 0);
276 QCOMPARE(prop.index(), -1);
277 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
283 QDeclarativeProperty prop(&dobject);
285 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
286 binding.data()->setTarget(prop);
287 QVERIFY(binding != 0);
288 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
289 QVERIFY(expression != 0);
291 QObject *obj = new QObject;
293 QCOMPARE(prop.name(), QString("defaultProperty"));
294 QCOMPARE(prop.read(), QVariant(10));
295 QCOMPARE(prop.write(QVariant()), false);
296 QCOMPARE(prop.hasNotifySignal(), false);
297 QCOMPARE(prop.needsNotifySignal(), true);
298 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
299 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
300 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
301 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
302 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
303 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
304 QVERIFY(prop.method().signature() == 0);
305 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
306 QCOMPARE(prop.isProperty(), true);
307 QCOMPARE(prop.isWritable(), false);
308 QCOMPARE(prop.isDesignable(), true);
309 QCOMPARE(prop.isResettable(), false);
310 QCOMPARE(prop.isSignalProperty(), false);
311 QCOMPARE(prop.isValid(), true);
312 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
313 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
314 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
315 QCOMPARE(prop.propertyTypeName(), "int");
316 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
317 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
318 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
319 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
320 QVERIFY(binding != 0);
321 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
322 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
323 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
324 QVERIFY(expression == 0);
325 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
326 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
332 void tst_qdeclarativeproperty::qmlmetaproperty_object_string()
335 PropertyObject dobject;
338 QDeclarativeProperty prop(&object, QString("defaultProperty"));
340 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
341 QVERIFY(binding != 0);
342 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
343 QVERIFY(expression != 0);
345 QObject *obj = new QObject;
347 QCOMPARE(prop.name(), QString());
348 QCOMPARE(prop.read(), QVariant());
349 QCOMPARE(prop.write(QVariant()), false);
350 QCOMPARE(prop.hasNotifySignal(), false);
351 QCOMPARE(prop.needsNotifySignal(), false);
352 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
353 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
354 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
355 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
356 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
357 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
358 QVERIFY(prop.method().signature() == 0);
359 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
360 QCOMPARE(prop.isProperty(), false);
361 QCOMPARE(prop.isWritable(), false);
362 QCOMPARE(prop.isDesignable(), false);
363 QCOMPARE(prop.isResettable(), false);
364 QCOMPARE(prop.isSignalProperty(), false);
365 QCOMPARE(prop.isValid(), false);
366 QCOMPARE(prop.object(), (QObject *)0);
367 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
368 QCOMPARE(prop.propertyType(), 0);
369 QCOMPARE(prop.propertyTypeName(), (const char *)0);
370 QVERIFY(prop.property().name() == 0);
371 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
372 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
373 QVERIFY(binding == 0);
374 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
375 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
376 QVERIFY(expression == 0);
377 QCOMPARE(prop.index(), -1);
378 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
384 QDeclarativeProperty prop(&dobject, QString("defaultProperty"));
386 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
387 binding.data()->setTarget(prop);
388 QVERIFY(binding != 0);
389 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
390 QVERIFY(expression != 0);
392 QObject *obj = new QObject;
394 QCOMPARE(prop.name(), QString("defaultProperty"));
395 QCOMPARE(prop.read(), QVariant(10));
396 QCOMPARE(prop.write(QVariant()), false);
397 QCOMPARE(prop.hasNotifySignal(), false);
398 QCOMPARE(prop.needsNotifySignal(), true);
399 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
400 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
401 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
402 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
403 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
404 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
405 QVERIFY(prop.method().signature() == 0);
406 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
407 QCOMPARE(prop.isProperty(), true);
408 QCOMPARE(prop.isWritable(), false);
409 QCOMPARE(prop.isDesignable(), true);
410 QCOMPARE(prop.isResettable(), false);
411 QCOMPARE(prop.isSignalProperty(), false);
412 QCOMPARE(prop.isValid(), true);
413 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
414 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
415 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
416 QCOMPARE(prop.propertyTypeName(), "int");
417 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
418 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
419 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
420 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
421 QVERIFY(binding != 0);
422 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
423 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
424 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
425 QVERIFY(expression == 0);
426 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
427 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
433 QDeclarativeProperty prop(&dobject, QString("onClicked"));
435 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
436 binding.data()->setTarget(prop);
437 QVERIFY(binding != 0);
438 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
439 QVERIFY(expression != 0);
441 QObject *obj = new QObject;
443 QCOMPARE(prop.name(), QString("onClicked"));
444 QCOMPARE(prop.read(), QVariant());
445 QCOMPARE(prop.write(QVariant("Hello")), false);
446 QCOMPARE(prop.hasNotifySignal(), false);
447 QCOMPARE(prop.needsNotifySignal(), false);
448 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
449 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
450 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
451 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
452 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
453 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
454 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
455 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
456 QCOMPARE(prop.isProperty(), false);
457 QCOMPARE(prop.isWritable(), false);
458 QCOMPARE(prop.isDesignable(), false);
459 QCOMPARE(prop.isResettable(), false);
460 QCOMPARE(prop.isSignalProperty(), true);
461 QCOMPARE(prop.isValid(), true);
462 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
463 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
464 QCOMPARE(prop.propertyType(), 0);
465 QCOMPARE(prop.propertyTypeName(), (const char *)0);
466 QCOMPARE(prop.property().name(), (const char *)0);
467 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
468 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
469 QVERIFY(binding == 0);
470 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
471 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
472 QVERIFY(expression != 0);
473 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
474 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
475 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
481 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
483 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
484 binding.data()->setTarget(prop);
485 QVERIFY(binding != 0);
486 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
487 QVERIFY(expression != 0);
489 QObject *obj = new QObject;
491 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
492 QCOMPARE(prop.read(), QVariant());
493 QCOMPARE(prop.write(QVariant("Hello")), false);
494 QCOMPARE(prop.hasNotifySignal(), false);
495 QCOMPARE(prop.needsNotifySignal(), false);
496 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
497 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
498 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
499 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
500 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
501 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
502 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
503 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
504 QCOMPARE(prop.isProperty(), false);
505 QCOMPARE(prop.isWritable(), false);
506 QCOMPARE(prop.isDesignable(), false);
507 QCOMPARE(prop.isResettable(), false);
508 QCOMPARE(prop.isSignalProperty(), true);
509 QCOMPARE(prop.isValid(), true);
510 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
511 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
512 QCOMPARE(prop.propertyType(), 0);
513 QCOMPARE(prop.propertyTypeName(), (const char *)0);
514 QCOMPARE(prop.property().name(), (const char *)0);
515 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
516 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
517 QVERIFY(binding == 0);
518 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
519 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
520 QVERIFY(expression != 0);
521 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
522 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
523 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
529 void tst_qdeclarativeproperty::qmlmetaproperty_object_context()
531 QObject object; // Has no default property
532 PropertyObject dobject; // Has default property
535 QDeclarativeProperty prop(&object, engine.rootContext());
537 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
538 QVERIFY(binding != 0);
539 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
540 QVERIFY(expression != 0);
542 QObject *obj = new QObject;
544 QCOMPARE(prop.name(), QString());
545 QCOMPARE(prop.read(), QVariant());
546 QCOMPARE(prop.write(QVariant()), false);
547 QCOMPARE(prop.hasNotifySignal(), false);
548 QCOMPARE(prop.needsNotifySignal(), false);
549 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
550 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
551 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
552 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
553 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
554 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
555 QVERIFY(prop.method().signature() == 0);
556 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
557 QCOMPARE(prop.isProperty(), false);
558 QCOMPARE(prop.isWritable(), false);
559 QCOMPARE(prop.isDesignable(), false);
560 QCOMPARE(prop.isResettable(), false);
561 QCOMPARE(prop.isSignalProperty(), false);
562 QCOMPARE(prop.isValid(), false);
563 QCOMPARE(prop.object(), (QObject *)0);
564 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
565 QCOMPARE(prop.propertyType(), 0);
566 QCOMPARE(prop.propertyTypeName(), (const char *)0);
567 QVERIFY(prop.property().name() == 0);
568 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
569 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
570 QVERIFY(binding == 0);
571 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
572 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
573 QVERIFY(expression == 0);
574 QCOMPARE(prop.index(), -1);
575 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
581 QDeclarativeProperty prop(&dobject, engine.rootContext());
583 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
584 binding.data()->setTarget(prop);
585 QVERIFY(binding != 0);
586 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
587 QVERIFY(expression != 0);
589 QObject *obj = new QObject;
591 QCOMPARE(prop.name(), QString("defaultProperty"));
592 QCOMPARE(prop.read(), QVariant(10));
593 QCOMPARE(prop.write(QVariant()), false);
594 QCOMPARE(prop.hasNotifySignal(), false);
595 QCOMPARE(prop.needsNotifySignal(), true);
596 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
597 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
598 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
599 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
600 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
601 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
602 QVERIFY(prop.method().signature() == 0);
603 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
604 QCOMPARE(prop.isProperty(), true);
605 QCOMPARE(prop.isWritable(), false);
606 QCOMPARE(prop.isDesignable(), true);
607 QCOMPARE(prop.isResettable(), false);
608 QCOMPARE(prop.isSignalProperty(), false);
609 QCOMPARE(prop.isValid(), true);
610 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
611 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
612 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
613 QCOMPARE(prop.propertyTypeName(), "int");
614 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
615 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
616 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
617 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
618 QVERIFY(binding != 0);
619 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
620 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
621 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
622 QVERIFY(expression == 0);
623 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
624 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
630 void tst_qdeclarativeproperty::qmlmetaproperty_object_string_context()
633 PropertyObject dobject;
636 QDeclarativeProperty prop(&object, QString("defaultProperty"), engine.rootContext());
638 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
639 QVERIFY(binding != 0);
640 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
641 QVERIFY(expression != 0);
643 QObject *obj = new QObject;
645 QCOMPARE(prop.name(), QString());
646 QCOMPARE(prop.read(), QVariant());
647 QCOMPARE(prop.write(QVariant()), false);
648 QCOMPARE(prop.hasNotifySignal(), false);
649 QCOMPARE(prop.needsNotifySignal(), false);
650 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
651 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
652 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
653 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
654 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
655 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
656 QVERIFY(prop.method().signature() == 0);
657 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
658 QCOMPARE(prop.isProperty(), false);
659 QCOMPARE(prop.isWritable(), false);
660 QCOMPARE(prop.isDesignable(), false);
661 QCOMPARE(prop.isResettable(), false);
662 QCOMPARE(prop.isSignalProperty(), false);
663 QCOMPARE(prop.isValid(), false);
664 QCOMPARE(prop.object(), (QObject *)0);
665 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
666 QCOMPARE(prop.propertyType(), 0);
667 QCOMPARE(prop.propertyTypeName(), (const char *)0);
668 QVERIFY(prop.property().name() == 0);
669 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
670 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
671 QVERIFY(binding == 0);
672 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
673 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
674 QVERIFY(expression == 0);
675 QCOMPARE(prop.index(), -1);
676 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
682 QDeclarativeProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
684 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
685 binding.data()->setTarget(prop);
686 QVERIFY(binding != 0);
687 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
688 QVERIFY(expression != 0);
690 QObject *obj = new QObject;
692 QCOMPARE(prop.name(), QString("defaultProperty"));
693 QCOMPARE(prop.read(), QVariant(10));
694 QCOMPARE(prop.write(QVariant()), false);
695 QCOMPARE(prop.hasNotifySignal(), false);
696 QCOMPARE(prop.needsNotifySignal(), true);
697 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
698 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
699 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
700 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
701 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
702 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
703 QVERIFY(prop.method().signature() == 0);
704 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
705 QCOMPARE(prop.isProperty(), true);
706 QCOMPARE(prop.isWritable(), false);
707 QCOMPARE(prop.isDesignable(), true);
708 QCOMPARE(prop.isResettable(), false);
709 QCOMPARE(prop.isSignalProperty(), false);
710 QCOMPARE(prop.isValid(), true);
711 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
712 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
713 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
714 QCOMPARE(prop.propertyTypeName(), "int");
715 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
716 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
717 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
718 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
719 QVERIFY(binding != 0);
720 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
721 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
722 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
723 QVERIFY(expression == 0);
724 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
725 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
731 QDeclarativeProperty prop(&dobject, QString("onClicked"), engine.rootContext());
733 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
734 binding.data()->setTarget(prop);
735 QVERIFY(binding != 0);
736 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
737 QVERIFY(expression != 0);
739 QObject *obj = new QObject;
741 QCOMPARE(prop.name(), QString("onClicked"));
742 QCOMPARE(prop.read(), QVariant());
743 QCOMPARE(prop.write(QVariant("Hello")), false);
744 QCOMPARE(prop.hasNotifySignal(), false);
745 QCOMPARE(prop.needsNotifySignal(), false);
746 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
747 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
748 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
749 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
750 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
751 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
752 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
753 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
754 QCOMPARE(prop.isProperty(), false);
755 QCOMPARE(prop.isWritable(), false);
756 QCOMPARE(prop.isDesignable(), false);
757 QCOMPARE(prop.isResettable(), false);
758 QCOMPARE(prop.isSignalProperty(), true);
759 QCOMPARE(prop.isValid(), true);
760 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
761 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
762 QCOMPARE(prop.propertyType(), 0);
763 QCOMPARE(prop.propertyTypeName(), (const char *)0);
764 QCOMPARE(prop.property().name(), (const char *)0);
765 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
766 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
767 QVERIFY(binding == 0);
768 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
769 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
770 QVERIFY(expression != 0);
771 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
772 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
773 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
779 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
781 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
782 binding.data()->setTarget(prop);
783 QVERIFY(binding != 0);
784 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
785 QVERIFY(expression != 0);
787 QObject *obj = new QObject;
789 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
790 QCOMPARE(prop.read(), QVariant());
791 QCOMPARE(prop.write(QVariant("Hello")), false);
792 QCOMPARE(prop.hasNotifySignal(), false);
793 QCOMPARE(prop.needsNotifySignal(), false);
794 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
795 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
796 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
797 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
798 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
799 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
800 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
801 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
802 QCOMPARE(prop.isProperty(), false);
803 QCOMPARE(prop.isWritable(), false);
804 QCOMPARE(prop.isDesignable(), false);
805 QCOMPARE(prop.isResettable(), false);
806 QCOMPARE(prop.isSignalProperty(), true);
807 QCOMPARE(prop.isValid(), true);
808 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
809 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
810 QCOMPARE(prop.propertyType(), 0);
811 QCOMPARE(prop.propertyTypeName(), (const char *)0);
812 QCOMPARE(prop.property().name(), (const char *)0);
813 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
814 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
815 QVERIFY(binding == 0);
816 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
817 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
818 QVERIFY(expression != 0);
819 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
820 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
821 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
827 void tst_qdeclarativeproperty::name()
830 QDeclarativeProperty p;
831 QCOMPARE(p.name(), QString());
836 QDeclarativeProperty p(&o);
837 QCOMPARE(p.name(), QString("defaultProperty"));
842 QDeclarativeProperty p(&o, QString("objectName"));
843 QCOMPARE(p.name(), QString("objectName"));
848 QDeclarativeProperty p(&o, "onClicked");
849 QCOMPARE(p.name(), QString("onClicked"));
854 QDeclarativeProperty p(&o, "onClicked");
855 QCOMPARE(p.name(), QString());
860 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
861 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
866 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
867 QCOMPARE(p.name(), QString());
872 QDeclarativeProperty p(&o, "foo");
873 QCOMPARE(p.name(), QString());
877 QDeclarativeProperty p(0, "foo");
878 QCOMPARE(p.name(), QString());
883 QDeclarativeProperty p(&o, "rectProperty");
884 QCOMPARE(p.name(), QString("rectProperty"));
889 QDeclarativeProperty p(&o, "rectProperty.x");
890 QCOMPARE(p.name(), QString("rectProperty.x"));
895 QDeclarativeProperty p(&o, "rectProperty.foo");
896 QCOMPARE(p.name(), QString());
900 void tst_qdeclarativeproperty::read()
904 QDeclarativeProperty p;
905 QCOMPARE(p.read(), QVariant());
911 QDeclarativeProperty p(&o);
912 QCOMPARE(p.read(), QVariant(10));
915 // Invalid default prop
918 QDeclarativeProperty p(&o);
919 QCOMPARE(p.read(), QVariant());
922 // Value prop by name
926 QDeclarativeProperty p(&o, "objectName");
927 QCOMPARE(p.read(), QVariant(QString()));
929 o.setObjectName("myName");
931 QCOMPARE(p.read(), QVariant("myName"));
934 // Value prop by name (static)
938 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant(QString()));
940 o.setObjectName("myName");
942 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant("myName"));
948 QDeclarativeProperty p(&o, "rectProperty.x");
949 QCOMPARE(p.read(), QVariant(10));
952 // Invalid value-type prop
955 QDeclarativeProperty p(&o, "rectProperty.foo");
956 QCOMPARE(p.read(), QVariant());
962 QDeclarativeProperty p(&o, "onClicked");
963 QCOMPARE(p.read(), QVariant());
965 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
966 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
968 QCOMPARE(p.read(), QVariant());
971 // Automatic signal property
974 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
975 QCOMPARE(p.read(), QVariant());
977 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
978 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
980 QCOMPARE(p.read(), QVariant());
985 PropertyObject *o = new PropertyObject;
986 QDeclarativeProperty p(o, "rectProperty.x");
987 QCOMPARE(p.read(), QVariant(10));
989 QCOMPARE(p.read(), QVariant());
995 QDeclarativeProperty p(&o, "qmlObject");
996 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
997 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
998 QVariant v = p.read();
999 QVERIFY(v.userType() == QMetaType::QObjectStar);
1000 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1003 QDeclarativeComponent component(&engine, TEST_FILE("readSynthesizedObject.qml"));
1004 QObject *object = component.create();
1005 QVERIFY(object != 0);
1007 QDeclarativeProperty p(object, "test", &engine);
1009 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1010 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1012 QVariant v = p.read();
1013 QVERIFY(v.userType() == QMetaType::QObjectStar);
1014 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1015 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1018 QDeclarativeComponent component(&engine, TEST_FILE("readSynthesizedObject.qml"));
1019 QObject *object = component.create();
1020 QVERIFY(object != 0);
1022 QVariant v = QDeclarativeProperty::read(object, "test", &engine);
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 // Attached property
1030 QDeclarativeComponent component(&engine);
1031 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1032 QObject *object = component.create();
1033 QVERIFY(object != 0);
1035 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1036 QCOMPARE(p.read(), QVariant(13));
1040 QDeclarativeComponent component(&engine);
1041 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1042 QObject *object = component.create();
1043 QVERIFY(object != 0);
1045 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1046 QCOMPARE(p.read(), QVariant(10));
1050 QDeclarativeComponent component(&engine);
1051 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1052 QObject *object = component.create();
1053 QVERIFY(object != 0);
1055 QDeclarativeProperty p(object, "Foo.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 QCOMPARE(QDeclarativeProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1070 void tst_qdeclarativeproperty::write()
1074 QDeclarativeProperty p;
1075 QCOMPARE(p.write(QVariant(10)), false);
1078 // Read-only default prop
1081 QDeclarativeProperty p(&o);
1082 QCOMPARE(p.write(QVariant(10)), false);
1085 // Invalid default prop
1088 QDeclarativeProperty p(&o);
1089 QCOMPARE(p.write(QVariant(10)), false);
1092 // Read-only prop by name
1095 QDeclarativeProperty p(&o, QString("defaultProperty"));
1096 QCOMPARE(p.write(QVariant(10)), false);
1099 // Writable prop by name
1102 QDeclarativeProperty p(&o, QString("objectName"));
1103 QCOMPARE(o.objectName(), QString());
1104 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1105 QCOMPARE(o.objectName(), QString("myName"));
1108 // Writable prop by name (static)
1111 QCOMPARE(QDeclarativeProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1112 QCOMPARE(o.objectName(), QString("myName"));
1117 PropertyObject *o = new PropertyObject;
1118 QDeclarativeProperty p(o, QString("objectName"));
1119 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1120 QCOMPARE(o->objectName(), QString("myName"));
1124 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1130 QDeclarativeProperty p(&o, "onClicked");
1131 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1133 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1134 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1136 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1138 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1141 // Automatic signal property
1144 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1145 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1147 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1148 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1150 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1152 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1155 // Value-type property
1158 QDeclarativeProperty p(&o, "wrectProperty");
1160 QCOMPARE(o.wrectProperty(), QRect());
1161 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1162 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1164 QDeclarativeProperty p2(&o, "wrectProperty.x");
1165 QCOMPARE(p2.read(), QVariant(1));
1166 QCOMPARE(p2.write(QVariant(6)), true);
1167 QCOMPARE(p2.read(), QVariant(6));
1168 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1174 QDeclarativeProperty p(&o, "url");
1176 QCOMPARE(p.write(QUrl("main.qml")), true);
1177 QCOMPARE(o.url(), QUrl("main.qml"));
1179 QDeclarativeProperty p2(&o, "url", engine.rootContext());
1181 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1182 QVERIFY(result != QUrl("main.qml"));
1184 QCOMPARE(p2.write(QUrl("main.qml")), true);
1185 QCOMPARE(o.url(), result);
1190 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml")), true);
1191 QCOMPARE(o.url(), QUrl("main.qml"));
1193 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1194 QVERIFY(result != QUrl("main.qml"));
1196 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1197 QCOMPARE(o.url(), result);
1200 // Attached property
1202 QDeclarativeComponent component(&engine);
1203 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1204 QObject *object = component.create();
1205 QVERIFY(object != 0);
1207 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1208 p.write(QVariant(99));
1209 QCOMPARE(p.read(), QVariant(99));
1213 QDeclarativeComponent component(&engine);
1214 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1215 QObject *object = component.create();
1216 QVERIFY(object != 0);
1218 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1219 p.write(QVariant(99));
1220 QCOMPARE(p.read(), QVariant(99));
1225 void tst_qdeclarativeproperty::reset()
1229 QDeclarativeProperty p;
1230 QCOMPARE(p.isResettable(), false);
1231 QCOMPARE(p.reset(), false);
1234 // Read-only default prop
1237 QDeclarativeProperty p(&o);
1238 QCOMPARE(p.isResettable(), false);
1239 QCOMPARE(p.reset(), false);
1242 // Invalid default prop
1245 QDeclarativeProperty p(&o);
1246 QCOMPARE(p.isResettable(), false);
1247 QCOMPARE(p.reset(), false);
1250 // Non-resettable-only prop by name
1253 QDeclarativeProperty p(&o, QString("defaultProperty"));
1254 QCOMPARE(p.isResettable(), false);
1255 QCOMPARE(p.reset(), false);
1258 // Resettable prop by name
1261 QDeclarativeProperty p(&o, QString("resettableProperty"));
1263 QCOMPARE(p.read(), QVariant(9));
1264 QCOMPARE(p.write(QVariant(11)), true);
1265 QCOMPARE(p.read(), QVariant(11));
1267 QCOMPARE(p.isResettable(), true);
1268 QCOMPARE(p.reset(), true);
1270 QCOMPARE(p.read(), QVariant(9));
1275 PropertyObject *o = new PropertyObject;
1277 QDeclarativeProperty p(o, QString("resettableProperty"));
1279 QCOMPARE(p.isResettable(), true);
1280 QCOMPARE(p.reset(), true);
1284 QCOMPARE(p.isResettable(), false);
1285 QCOMPARE(p.reset(), false);
1291 QDeclarativeProperty p(&o, "onClicked");
1293 QCOMPARE(p.isResettable(), false);
1294 QCOMPARE(p.reset(), false);
1297 // Automatic signal property
1300 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1302 QCOMPARE(p.isResettable(), false);
1303 QCOMPARE(p.reset(), false);
1307 void tst_qdeclarativeproperty::writeObjectToList()
1309 QDeclarativeComponent containerComponent(&engine);
1310 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1311 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1312 QVERIFY(container != 0);
1313 QDeclarativeListReference list(container, "children");
1314 QVERIFY(list.count() == 1);
1316 MyQmlObject *object = new MyQmlObject;
1317 QDeclarativeProperty prop(container, "children");
1318 prop.write(qVariantFromValue(object));
1319 QCOMPARE(list.count(), 1);
1320 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1323 Q_DECLARE_METATYPE(QList<QObject *>);
1324 void tst_qdeclarativeproperty::writeListToList()
1326 QDeclarativeComponent containerComponent(&engine);
1327 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1328 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1329 QVERIFY(container != 0);
1330 QDeclarativeListReference list(container, "children");
1331 QVERIFY(list.count() == 1);
1333 QList<QObject*> objList;
1334 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1335 QDeclarativeProperty prop(container, "children");
1336 prop.write(qVariantFromValue(objList));
1337 QCOMPARE(list.count(), 4);
1339 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1340 /*QList<MyQmlObject*> typedObjList;
1341 typedObjList << new MyQmlObject();
1342 prop.write(qVariantFromValue(&typedObjList));
1343 QCOMPARE(container->children()->size(), 1);*/
1346 void tst_qdeclarativeproperty::crashOnValueProperty()
1348 QDeclarativeEngine *engine = new QDeclarativeEngine;
1349 QDeclarativeComponent component(engine);
1351 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1352 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1355 QDeclarativeProperty p(obj, "wrectProperty.x", qmlContext(obj));
1356 QCOMPARE(p.name(), QString("wrectProperty.x"));
1358 QCOMPARE(p.read(), QVariant(10));
1360 //don't crash once the engine is deleted
1364 QCOMPARE(p.propertyTypeName(), "int");
1365 QCOMPARE(p.read(), QVariant(10));
1366 p.write(QVariant(20));
1367 QCOMPARE(p.read(), QVariant(20));
1371 void tst_qdeclarativeproperty::aliasPropertyBindings()
1373 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyBindings.qml"));
1375 QObject *object = component.create();
1376 QVERIFY(object != 0);
1378 QCOMPARE(object->property("realProperty").toReal(), 90.);
1379 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1381 object->setProperty("test", 10);
1383 QCOMPARE(object->property("realProperty").toReal(), 110.);
1384 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1386 QDeclarativeProperty realProperty(object, QLatin1String("realProperty"));
1387 QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty"));
1389 // Check there is a binding on these two properties
1390 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1391 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1393 // Check that its the same binding on these two properties
1394 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1395 QDeclarativePropertyPrivate::binding(aliasProperty));
1397 // Change the binding
1398 object->setProperty("state", QString("switch"));
1400 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1401 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1402 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1403 QDeclarativePropertyPrivate::binding(aliasProperty));
1405 QCOMPARE(object->property("realProperty").toReal(), 96.);
1406 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1408 // Check the old binding really has not effect any more
1409 object->setProperty("test", 4);
1411 QCOMPARE(object->property("realProperty").toReal(), 96.);
1412 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1414 object->setProperty("test2", 9);
1416 QCOMPARE(object->property("realProperty").toReal(), 288.);
1417 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1420 object->setProperty("state", QString(""));
1422 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1423 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1424 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1425 QDeclarativePropertyPrivate::binding(aliasProperty));
1427 QCOMPARE(object->property("realProperty").toReal(), 20.);
1428 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1430 object->setProperty("test2", 3);
1432 QCOMPARE(object->property("realProperty").toReal(), 20.);
1433 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1438 void tst_qdeclarativeproperty::copy()
1440 PropertyObject object;
1442 QDeclarativeProperty *property = new QDeclarativeProperty(&object, QLatin1String("defaultProperty"));
1443 QCOMPARE(property->name(), QString("defaultProperty"));
1444 QCOMPARE(property->read(), QVariant(10));
1445 QCOMPARE(property->type(), QDeclarativeProperty::Property);
1446 QCOMPARE(property->propertyTypeCategory(), QDeclarativeProperty::Normal);
1447 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1449 QDeclarativeProperty p1(*property);
1450 QCOMPARE(p1.name(), QString("defaultProperty"));
1451 QCOMPARE(p1.read(), QVariant(10));
1452 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1453 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1454 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1456 QDeclarativeProperty p2(&object, QLatin1String("url"));
1457 QCOMPARE(p2.name(), QString("url"));
1459 QCOMPARE(p2.name(), QString("defaultProperty"));
1460 QCOMPARE(p2.read(), QVariant(10));
1461 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1462 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1463 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1465 delete property; property = 0;
1467 QCOMPARE(p1.name(), QString("defaultProperty"));
1468 QCOMPARE(p1.read(), QVariant(10));
1469 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1470 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1471 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1473 QCOMPARE(p2.name(), QString("defaultProperty"));
1474 QCOMPARE(p2.read(), QVariant(10));
1475 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1476 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1477 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1480 void tst_qdeclarativeproperty::noContext()
1482 QDeclarativeComponent compA(&engine, TEST_FILE("NoContextTypeA.qml"));
1483 QDeclarativeComponent compB(&engine, TEST_FILE("NoContextTypeB.qml"));
1485 QObject *a = compA.create();
1487 QObject *b = compB.create();
1490 QVERIFY(QDeclarativeProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1496 void tst_qdeclarativeproperty::initTestCase()
1498 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1499 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1500 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1503 QTEST_MAIN(tst_qdeclarativeproperty)
1505 #include "tst_qdeclarativeproperty.moc"