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 <QtGui/QLineEdit>
48 #include <QtCore/qfileinfo.h>
49 #include <QtCore/qdir.h>
52 // In Symbian OS test data is located in applications private dir
56 inline QUrl TEST_FILE(const QString &filename)
58 QFileInfo fileInfo(__FILE__);
59 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(QLatin1String("data/") + filename));
62 class MyQmlObject : public QObject
69 QML_DECLARE_TYPE(MyQmlObject);
71 class MyAttached : public QObject
74 Q_PROPERTY(int foo READ foo WRITE setFoo)
76 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
78 int foo() const { return m_foo; }
79 void setFoo(int f) { m_foo = f; }
85 class MyContainer : public QObject
88 Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children)
92 QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); }
94 static MyAttached *qmlAttachedProperties(QObject *o) {
95 return new MyAttached(o);
99 QList<MyQmlObject*> m_children;
102 QML_DECLARE_TYPE(MyContainer);
103 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
105 class tst_qdeclarativeproperty : public QObject
109 tst_qdeclarativeproperty() {}
115 void qmlmetaproperty();
116 void qmlmetaproperty_object();
117 void qmlmetaproperty_object_string();
118 void qmlmetaproperty_object_context();
119 void qmlmetaproperty_object_string_context();
128 void writeObjectToList();
129 void writeListToList();
134 void crashOnValueProperty();
135 void aliasPropertyBindings();
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(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
197 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
198 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
200 Q_CLASSINFO("DefaultProperty", "defaultProperty")
202 PropertyObject() : m_resetProperty(9) {}
204 int defaultProperty() { return 10; }
205 QRect rectProperty() { return QRect(10, 10, 1, 209); }
207 QRect wrectProperty() { return m_rect; }
208 void setWRectProperty(const QRect &r) { m_rect = r; }
210 QUrl url() { return m_url; }
211 void setUrl(const QUrl &u) { m_url = u; }
213 int resettableProperty() const { return m_resetProperty; }
214 void setResettableProperty(int r) { m_resetProperty = r; }
215 void resetProperty() { m_resetProperty = 9; }
217 int propertyWithNotify() const { return m_propertyWithNotify; }
218 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
220 MyQmlObject *qmlObject() { return &m_qmlObject; }
223 void oddlyNamedNotifySignal();
229 int m_propertyWithNotify;
230 MyQmlObject m_qmlObject;
233 QML_DECLARE_TYPE(PropertyObject);
235 void tst_qdeclarativeproperty::qmlmetaproperty_object()
237 QObject object; // Has no default property
238 PropertyObject dobject; // Has default property
241 QDeclarativeProperty prop(&object);
243 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
244 QVERIFY(binding != 0);
245 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
246 QVERIFY(expression != 0);
248 QObject *obj = new QObject;
250 QCOMPARE(prop.name(), QString());
251 QCOMPARE(prop.read(), QVariant());
252 QCOMPARE(prop.write(QVariant()), false);
253 QCOMPARE(prop.hasNotifySignal(), false);
254 QCOMPARE(prop.needsNotifySignal(), false);
255 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
256 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
257 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
258 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
259 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
260 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
261 QVERIFY(prop.method().signature() == 0);
262 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
263 QCOMPARE(prop.isProperty(), false);
264 QCOMPARE(prop.isWritable(), false);
265 QCOMPARE(prop.isDesignable(), false);
266 QCOMPARE(prop.isResettable(), false);
267 QCOMPARE(prop.isSignalProperty(), false);
268 QCOMPARE(prop.isValid(), false);
269 QCOMPARE(prop.object(), (QObject *)0);
270 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
271 QCOMPARE(prop.propertyType(), 0);
272 QCOMPARE(prop.propertyTypeName(), (const char *)0);
273 QVERIFY(prop.property().name() == 0);
274 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
275 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
276 QVERIFY(binding == 0);
277 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
278 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
279 QVERIFY(expression == 0);
280 QCOMPARE(prop.index(), -1);
281 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
287 QDeclarativeProperty prop(&dobject);
289 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
290 binding.data()->setTarget(prop);
291 QVERIFY(binding != 0);
292 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
293 QVERIFY(expression != 0);
295 QObject *obj = new QObject;
297 QCOMPARE(prop.name(), QString("defaultProperty"));
298 QCOMPARE(prop.read(), QVariant(10));
299 QCOMPARE(prop.write(QVariant()), false);
300 QCOMPARE(prop.hasNotifySignal(), false);
301 QCOMPARE(prop.needsNotifySignal(), true);
302 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
303 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
304 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
305 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
306 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
307 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
308 QVERIFY(prop.method().signature() == 0);
309 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
310 QCOMPARE(prop.isProperty(), true);
311 QCOMPARE(prop.isWritable(), false);
312 QCOMPARE(prop.isDesignable(), true);
313 QCOMPARE(prop.isResettable(), false);
314 QCOMPARE(prop.isSignalProperty(), false);
315 QCOMPARE(prop.isValid(), true);
316 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
317 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
318 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
319 QCOMPARE(prop.propertyTypeName(), "int");
320 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
321 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
322 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
323 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
324 QVERIFY(binding != 0);
325 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
326 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
327 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
328 QVERIFY(expression == 0);
329 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
330 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
336 void tst_qdeclarativeproperty::qmlmetaproperty_object_string()
339 PropertyObject dobject;
342 QDeclarativeProperty prop(&object, QString("defaultProperty"));
344 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
345 QVERIFY(binding != 0);
346 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
347 QVERIFY(expression != 0);
349 QObject *obj = new QObject;
351 QCOMPARE(prop.name(), QString());
352 QCOMPARE(prop.read(), QVariant());
353 QCOMPARE(prop.write(QVariant()), false);
354 QCOMPARE(prop.hasNotifySignal(), false);
355 QCOMPARE(prop.needsNotifySignal(), false);
356 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
357 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
358 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
359 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
360 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
361 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
362 QVERIFY(prop.method().signature() == 0);
363 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
364 QCOMPARE(prop.isProperty(), false);
365 QCOMPARE(prop.isWritable(), false);
366 QCOMPARE(prop.isDesignable(), false);
367 QCOMPARE(prop.isResettable(), false);
368 QCOMPARE(prop.isSignalProperty(), false);
369 QCOMPARE(prop.isValid(), false);
370 QCOMPARE(prop.object(), (QObject *)0);
371 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
372 QCOMPARE(prop.propertyType(), 0);
373 QCOMPARE(prop.propertyTypeName(), (const char *)0);
374 QVERIFY(prop.property().name() == 0);
375 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
376 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
377 QVERIFY(binding == 0);
378 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
379 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
380 QVERIFY(expression == 0);
381 QCOMPARE(prop.index(), -1);
382 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
388 QDeclarativeProperty prop(&dobject, QString("defaultProperty"));
390 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
391 binding.data()->setTarget(prop);
392 QVERIFY(binding != 0);
393 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
394 QVERIFY(expression != 0);
396 QObject *obj = new QObject;
398 QCOMPARE(prop.name(), QString("defaultProperty"));
399 QCOMPARE(prop.read(), QVariant(10));
400 QCOMPARE(prop.write(QVariant()), false);
401 QCOMPARE(prop.hasNotifySignal(), false);
402 QCOMPARE(prop.needsNotifySignal(), true);
403 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
404 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
405 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
406 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
407 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
408 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
409 QVERIFY(prop.method().signature() == 0);
410 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
411 QCOMPARE(prop.isProperty(), true);
412 QCOMPARE(prop.isWritable(), false);
413 QCOMPARE(prop.isDesignable(), true);
414 QCOMPARE(prop.isResettable(), false);
415 QCOMPARE(prop.isSignalProperty(), false);
416 QCOMPARE(prop.isValid(), true);
417 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
418 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
419 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
420 QCOMPARE(prop.propertyTypeName(), "int");
421 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
422 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
423 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
424 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
425 QVERIFY(binding != 0);
426 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
427 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
428 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
429 QVERIFY(expression == 0);
430 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
431 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
437 QDeclarativeProperty prop(&dobject, QString("onClicked"));
439 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
440 binding.data()->setTarget(prop);
441 QVERIFY(binding != 0);
442 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
443 QVERIFY(expression != 0);
445 QObject *obj = new QObject;
447 QCOMPARE(prop.name(), QString("onClicked"));
448 QCOMPARE(prop.read(), QVariant());
449 QCOMPARE(prop.write(QVariant("Hello")), false);
450 QCOMPARE(prop.hasNotifySignal(), false);
451 QCOMPARE(prop.needsNotifySignal(), false);
452 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
453 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
454 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
455 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
456 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
457 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
458 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
459 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
460 QCOMPARE(prop.isProperty(), false);
461 QCOMPARE(prop.isWritable(), false);
462 QCOMPARE(prop.isDesignable(), false);
463 QCOMPARE(prop.isResettable(), false);
464 QCOMPARE(prop.isSignalProperty(), true);
465 QCOMPARE(prop.isValid(), true);
466 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
467 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
468 QCOMPARE(prop.propertyType(), 0);
469 QCOMPARE(prop.propertyTypeName(), (const char *)0);
470 QCOMPARE(prop.property().name(), (const char *)0);
471 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
472 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
473 QVERIFY(binding == 0);
474 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
475 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
476 QVERIFY(expression != 0);
477 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
478 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
479 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
485 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
487 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
488 binding.data()->setTarget(prop);
489 QVERIFY(binding != 0);
490 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
491 QVERIFY(expression != 0);
493 QObject *obj = new QObject;
495 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
496 QCOMPARE(prop.read(), QVariant());
497 QCOMPARE(prop.write(QVariant("Hello")), false);
498 QCOMPARE(prop.hasNotifySignal(), false);
499 QCOMPARE(prop.needsNotifySignal(), false);
500 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
501 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
502 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
503 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
504 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
505 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
506 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
507 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
508 QCOMPARE(prop.isProperty(), false);
509 QCOMPARE(prop.isWritable(), false);
510 QCOMPARE(prop.isDesignable(), false);
511 QCOMPARE(prop.isResettable(), false);
512 QCOMPARE(prop.isSignalProperty(), true);
513 QCOMPARE(prop.isValid(), true);
514 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
515 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
516 QCOMPARE(prop.propertyType(), 0);
517 QCOMPARE(prop.propertyTypeName(), (const char *)0);
518 QCOMPARE(prop.property().name(), (const char *)0);
519 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
520 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
521 QVERIFY(binding == 0);
522 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
523 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
524 QVERIFY(expression != 0);
525 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
526 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
527 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
533 void tst_qdeclarativeproperty::qmlmetaproperty_object_context()
535 QObject object; // Has no default property
536 PropertyObject dobject; // Has default property
539 QDeclarativeProperty prop(&object, engine.rootContext());
541 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
542 QVERIFY(binding != 0);
543 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
544 QVERIFY(expression != 0);
546 QObject *obj = new QObject;
548 QCOMPARE(prop.name(), QString());
549 QCOMPARE(prop.read(), QVariant());
550 QCOMPARE(prop.write(QVariant()), false);
551 QCOMPARE(prop.hasNotifySignal(), false);
552 QCOMPARE(prop.needsNotifySignal(), false);
553 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
554 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
555 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
556 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
557 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
558 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
559 QVERIFY(prop.method().signature() == 0);
560 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
561 QCOMPARE(prop.isProperty(), false);
562 QCOMPARE(prop.isWritable(), false);
563 QCOMPARE(prop.isDesignable(), false);
564 QCOMPARE(prop.isResettable(), false);
565 QCOMPARE(prop.isSignalProperty(), false);
566 QCOMPARE(prop.isValid(), false);
567 QCOMPARE(prop.object(), (QObject *)0);
568 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
569 QCOMPARE(prop.propertyType(), 0);
570 QCOMPARE(prop.propertyTypeName(), (const char *)0);
571 QVERIFY(prop.property().name() == 0);
572 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
573 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
574 QVERIFY(binding == 0);
575 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
576 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
577 QVERIFY(expression == 0);
578 QCOMPARE(prop.index(), -1);
579 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
585 QDeclarativeProperty prop(&dobject, engine.rootContext());
587 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
588 binding.data()->setTarget(prop);
589 QVERIFY(binding != 0);
590 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
591 QVERIFY(expression != 0);
593 QObject *obj = new QObject;
595 QCOMPARE(prop.name(), QString("defaultProperty"));
596 QCOMPARE(prop.read(), QVariant(10));
597 QCOMPARE(prop.write(QVariant()), false);
598 QCOMPARE(prop.hasNotifySignal(), false);
599 QCOMPARE(prop.needsNotifySignal(), true);
600 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
601 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
602 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
603 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
604 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
605 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
606 QVERIFY(prop.method().signature() == 0);
607 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
608 QCOMPARE(prop.isProperty(), true);
609 QCOMPARE(prop.isWritable(), false);
610 QCOMPARE(prop.isDesignable(), true);
611 QCOMPARE(prop.isResettable(), false);
612 QCOMPARE(prop.isSignalProperty(), false);
613 QCOMPARE(prop.isValid(), true);
614 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
615 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
616 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
617 QCOMPARE(prop.propertyTypeName(), "int");
618 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
619 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
620 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
621 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
622 QVERIFY(binding != 0);
623 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
624 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
625 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
626 QVERIFY(expression == 0);
627 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
628 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
634 void tst_qdeclarativeproperty::qmlmetaproperty_object_string_context()
637 PropertyObject dobject;
640 QDeclarativeProperty prop(&object, QString("defaultProperty"), engine.rootContext());
642 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
643 QVERIFY(binding != 0);
644 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
645 QVERIFY(expression != 0);
647 QObject *obj = new QObject;
649 QCOMPARE(prop.name(), QString());
650 QCOMPARE(prop.read(), QVariant());
651 QCOMPARE(prop.write(QVariant()), false);
652 QCOMPARE(prop.hasNotifySignal(), false);
653 QCOMPARE(prop.needsNotifySignal(), false);
654 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
655 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
656 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
657 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
658 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
659 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
660 QVERIFY(prop.method().signature() == 0);
661 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
662 QCOMPARE(prop.isProperty(), false);
663 QCOMPARE(prop.isWritable(), false);
664 QCOMPARE(prop.isDesignable(), false);
665 QCOMPARE(prop.isResettable(), false);
666 QCOMPARE(prop.isSignalProperty(), false);
667 QCOMPARE(prop.isValid(), false);
668 QCOMPARE(prop.object(), (QObject *)0);
669 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
670 QCOMPARE(prop.propertyType(), 0);
671 QCOMPARE(prop.propertyTypeName(), (const char *)0);
672 QVERIFY(prop.property().name() == 0);
673 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
674 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
675 QVERIFY(binding == 0);
676 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
677 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
678 QVERIFY(expression == 0);
679 QCOMPARE(prop.index(), -1);
680 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
686 QDeclarativeProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
688 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
689 binding.data()->setTarget(prop);
690 QVERIFY(binding != 0);
691 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
692 QVERIFY(expression != 0);
694 QObject *obj = new QObject;
696 QCOMPARE(prop.name(), QString("defaultProperty"));
697 QCOMPARE(prop.read(), QVariant(10));
698 QCOMPARE(prop.write(QVariant()), false);
699 QCOMPARE(prop.hasNotifySignal(), false);
700 QCOMPARE(prop.needsNotifySignal(), true);
701 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
702 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
703 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
704 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
705 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
706 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
707 QVERIFY(prop.method().signature() == 0);
708 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
709 QCOMPARE(prop.isProperty(), true);
710 QCOMPARE(prop.isWritable(), false);
711 QCOMPARE(prop.isDesignable(), true);
712 QCOMPARE(prop.isResettable(), false);
713 QCOMPARE(prop.isSignalProperty(), false);
714 QCOMPARE(prop.isValid(), true);
715 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
716 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
717 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
718 QCOMPARE(prop.propertyTypeName(), "int");
719 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
720 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
721 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
722 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
723 QVERIFY(binding != 0);
724 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
725 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
726 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
727 QVERIFY(expression == 0);
728 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
729 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
735 QDeclarativeProperty prop(&dobject, QString("onClicked"), engine.rootContext());
737 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
738 binding.data()->setTarget(prop);
739 QVERIFY(binding != 0);
740 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
741 QVERIFY(expression != 0);
743 QObject *obj = new QObject;
745 QCOMPARE(prop.name(), QString("onClicked"));
746 QCOMPARE(prop.read(), QVariant());
747 QCOMPARE(prop.write(QVariant("Hello")), false);
748 QCOMPARE(prop.hasNotifySignal(), false);
749 QCOMPARE(prop.needsNotifySignal(), false);
750 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
751 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
752 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
753 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
754 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
755 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
756 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
757 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
758 QCOMPARE(prop.isProperty(), false);
759 QCOMPARE(prop.isWritable(), false);
760 QCOMPARE(prop.isDesignable(), false);
761 QCOMPARE(prop.isResettable(), false);
762 QCOMPARE(prop.isSignalProperty(), true);
763 QCOMPARE(prop.isValid(), true);
764 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
765 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
766 QCOMPARE(prop.propertyType(), 0);
767 QCOMPARE(prop.propertyTypeName(), (const char *)0);
768 QCOMPARE(prop.property().name(), (const char *)0);
769 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
770 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
771 QVERIFY(binding == 0);
772 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
773 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
774 QVERIFY(expression != 0);
775 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
776 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
777 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
783 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
785 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
786 binding.data()->setTarget(prop);
787 QVERIFY(binding != 0);
788 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
789 QVERIFY(expression != 0);
791 QObject *obj = new QObject;
793 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
794 QCOMPARE(prop.read(), QVariant());
795 QCOMPARE(prop.write(QVariant("Hello")), false);
796 QCOMPARE(prop.hasNotifySignal(), false);
797 QCOMPARE(prop.needsNotifySignal(), false);
798 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
799 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
800 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
801 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
802 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
803 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
804 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
805 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
806 QCOMPARE(prop.isProperty(), false);
807 QCOMPARE(prop.isWritable(), false);
808 QCOMPARE(prop.isDesignable(), false);
809 QCOMPARE(prop.isResettable(), false);
810 QCOMPARE(prop.isSignalProperty(), true);
811 QCOMPARE(prop.isValid(), true);
812 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
813 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
814 QCOMPARE(prop.propertyType(), 0);
815 QCOMPARE(prop.propertyTypeName(), (const char *)0);
816 QCOMPARE(prop.property().name(), (const char *)0);
817 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
818 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
819 QVERIFY(binding == 0);
820 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
821 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
822 QVERIFY(expression != 0);
823 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
824 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
825 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
831 void tst_qdeclarativeproperty::name()
834 QDeclarativeProperty p;
835 QCOMPARE(p.name(), QString());
840 QDeclarativeProperty p(&o);
841 QCOMPARE(p.name(), QString("defaultProperty"));
846 QDeclarativeProperty p(&o, QString("objectName"));
847 QCOMPARE(p.name(), QString("objectName"));
852 QDeclarativeProperty p(&o, "onClicked");
853 QCOMPARE(p.name(), QString("onClicked"));
858 QDeclarativeProperty p(&o, "onClicked");
859 QCOMPARE(p.name(), QString());
864 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
865 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
870 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
871 QCOMPARE(p.name(), QString());
876 QDeclarativeProperty p(&o, "foo");
877 QCOMPARE(p.name(), QString());
881 QDeclarativeProperty p(0, "foo");
882 QCOMPARE(p.name(), QString());
887 QDeclarativeProperty p(&o, "rectProperty");
888 QCOMPARE(p.name(), QString("rectProperty"));
893 QDeclarativeProperty p(&o, "rectProperty.x");
894 QCOMPARE(p.name(), QString("rectProperty.x"));
899 QDeclarativeProperty p(&o, "rectProperty.foo");
900 QCOMPARE(p.name(), QString());
904 void tst_qdeclarativeproperty::read()
908 QDeclarativeProperty p;
909 QCOMPARE(p.read(), QVariant());
915 QDeclarativeProperty p(&o);
916 QCOMPARE(p.read(), QVariant(10));
919 // Invalid default prop
922 QDeclarativeProperty p(&o);
923 QCOMPARE(p.read(), QVariant());
926 // Value prop by name
930 QDeclarativeProperty p(&o, "objectName");
931 QCOMPARE(p.read(), QVariant(QString()));
933 o.setObjectName("myName");
935 QCOMPARE(p.read(), QVariant("myName"));
938 // Value prop by name (static)
942 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant(QString()));
944 o.setObjectName("myName");
946 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant("myName"));
952 QDeclarativeProperty p(&o, "rectProperty.x");
953 QCOMPARE(p.read(), QVariant(10));
956 // Invalid value-type prop
959 QDeclarativeProperty p(&o, "rectProperty.foo");
960 QCOMPARE(p.read(), QVariant());
966 QDeclarativeProperty p(&o, "onClicked");
967 QCOMPARE(p.read(), QVariant());
969 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
970 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
972 QCOMPARE(p.read(), QVariant());
975 // Automatic signal property
978 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
979 QCOMPARE(p.read(), QVariant());
981 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
982 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
984 QCOMPARE(p.read(), QVariant());
989 PropertyObject *o = new PropertyObject;
990 QDeclarativeProperty p(o, "rectProperty.x");
991 QCOMPARE(p.read(), QVariant(10));
993 QCOMPARE(p.read(), QVariant());
999 QDeclarativeProperty p(&o, "qmlObject");
1000 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1001 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
1002 QVariant v = p.read();
1003 QVERIFY(v.userType() == QMetaType::QObjectStar);
1004 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1007 QDeclarativeComponent component(&engine, TEST_FILE("readSynthesizedObject.qml"));
1008 QObject *object = component.create();
1009 QVERIFY(object != 0);
1011 QDeclarativeProperty p(object, "test", &engine);
1013 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1014 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1016 QVariant v = p.read();
1017 QVERIFY(v.userType() == QMetaType::QObjectStar);
1018 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1019 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1022 QDeclarativeComponent component(&engine, TEST_FILE("readSynthesizedObject.qml"));
1023 QObject *object = component.create();
1024 QVERIFY(object != 0);
1026 QVariant v = QDeclarativeProperty::read(object, "test", &engine);
1027 QVERIFY(v.userType() == QMetaType::QObjectStar);
1028 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1029 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1032 // Attached property
1034 QDeclarativeComponent component(&engine);
1035 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1036 QObject *object = component.create();
1037 QVERIFY(object != 0);
1039 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1040 QCOMPARE(p.read(), QVariant(13));
1044 QDeclarativeComponent component(&engine);
1045 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1046 QObject *object = component.create();
1047 QVERIFY(object != 0);
1049 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1050 QCOMPARE(p.read(), QVariant(10));
1054 QDeclarativeComponent component(&engine);
1055 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1056 QObject *object = component.create();
1057 QVERIFY(object != 0);
1059 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1060 QCOMPARE(p.read(), QVariant(10));
1064 QDeclarativeComponent component(&engine);
1065 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1066 QObject *object = component.create();
1067 QVERIFY(object != 0);
1069 QCOMPARE(QDeclarativeProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1074 void tst_qdeclarativeproperty::write()
1078 QDeclarativeProperty p;
1079 QCOMPARE(p.write(QVariant(10)), false);
1082 // Read-only default prop
1085 QDeclarativeProperty p(&o);
1086 QCOMPARE(p.write(QVariant(10)), false);
1089 // Invalid default prop
1092 QDeclarativeProperty p(&o);
1093 QCOMPARE(p.write(QVariant(10)), false);
1096 // Read-only prop by name
1099 QDeclarativeProperty p(&o, QString("defaultProperty"));
1100 QCOMPARE(p.write(QVariant(10)), false);
1103 // Writable prop by name
1106 QDeclarativeProperty p(&o, QString("objectName"));
1107 QCOMPARE(o.objectName(), QString());
1108 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1109 QCOMPARE(o.objectName(), QString("myName"));
1112 // Writable prop by name (static)
1115 QCOMPARE(QDeclarativeProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1116 QCOMPARE(o.objectName(), QString("myName"));
1121 PropertyObject *o = new PropertyObject;
1122 QDeclarativeProperty p(o, QString("objectName"));
1123 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1124 QCOMPARE(o->objectName(), QString("myName"));
1128 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1134 QDeclarativeProperty p(&o, "onClicked");
1135 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1137 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1138 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1140 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1142 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1145 // Automatic signal property
1148 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1149 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1151 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1152 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1154 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1156 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1159 // Value-type property
1162 QDeclarativeProperty p(&o, "wrectProperty");
1164 QCOMPARE(o.wrectProperty(), QRect());
1165 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1166 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1168 QDeclarativeProperty p2(&o, "wrectProperty.x");
1169 QCOMPARE(p2.read(), QVariant(1));
1170 QCOMPARE(p2.write(QVariant(6)), true);
1171 QCOMPARE(p2.read(), QVariant(6));
1172 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1178 QDeclarativeProperty p(&o, "url");
1180 QCOMPARE(p.write(QUrl("main.qml")), true);
1181 QCOMPARE(o.url(), QUrl("main.qml"));
1183 QDeclarativeProperty p2(&o, "url", engine.rootContext());
1185 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1186 QVERIFY(result != QUrl("main.qml"));
1188 QCOMPARE(p2.write(QUrl("main.qml")), true);
1189 QCOMPARE(o.url(), result);
1194 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml")), true);
1195 QCOMPARE(o.url(), QUrl("main.qml"));
1197 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1198 QVERIFY(result != QUrl("main.qml"));
1200 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1201 QCOMPARE(o.url(), result);
1204 // Attached property
1206 QDeclarativeComponent component(&engine);
1207 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1208 QObject *object = component.create();
1209 QVERIFY(object != 0);
1211 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1212 p.write(QVariant(99));
1213 QCOMPARE(p.read(), QVariant(99));
1217 QDeclarativeComponent component(&engine);
1218 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1219 QObject *object = component.create();
1220 QVERIFY(object != 0);
1222 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1223 p.write(QVariant(99));
1224 QCOMPARE(p.read(), QVariant(99));
1229 void tst_qdeclarativeproperty::reset()
1233 QDeclarativeProperty p;
1234 QCOMPARE(p.isResettable(), false);
1235 QCOMPARE(p.reset(), false);
1238 // Read-only default prop
1241 QDeclarativeProperty p(&o);
1242 QCOMPARE(p.isResettable(), false);
1243 QCOMPARE(p.reset(), false);
1246 // Invalid default prop
1249 QDeclarativeProperty p(&o);
1250 QCOMPARE(p.isResettable(), false);
1251 QCOMPARE(p.reset(), false);
1254 // Non-resettable-only prop by name
1257 QDeclarativeProperty p(&o, QString("defaultProperty"));
1258 QCOMPARE(p.isResettable(), false);
1259 QCOMPARE(p.reset(), false);
1262 // Resettable prop by name
1265 QDeclarativeProperty p(&o, QString("resettableProperty"));
1267 QCOMPARE(p.read(), QVariant(9));
1268 QCOMPARE(p.write(QVariant(11)), true);
1269 QCOMPARE(p.read(), QVariant(11));
1271 QCOMPARE(p.isResettable(), true);
1272 QCOMPARE(p.reset(), true);
1274 QCOMPARE(p.read(), QVariant(9));
1279 PropertyObject *o = new PropertyObject;
1281 QDeclarativeProperty p(o, QString("resettableProperty"));
1283 QCOMPARE(p.isResettable(), true);
1284 QCOMPARE(p.reset(), true);
1288 QCOMPARE(p.isResettable(), false);
1289 QCOMPARE(p.reset(), false);
1295 QDeclarativeProperty p(&o, "onClicked");
1297 QCOMPARE(p.isResettable(), false);
1298 QCOMPARE(p.reset(), false);
1301 // Automatic signal property
1304 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1306 QCOMPARE(p.isResettable(), false);
1307 QCOMPARE(p.reset(), false);
1311 void tst_qdeclarativeproperty::writeObjectToList()
1313 QDeclarativeComponent containerComponent(&engine);
1314 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1315 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1316 QVERIFY(container != 0);
1317 QDeclarativeListReference list(container, "children");
1318 QVERIFY(list.count() == 1);
1320 MyQmlObject *object = new MyQmlObject;
1321 QDeclarativeProperty prop(container, "children");
1322 prop.write(qVariantFromValue(object));
1323 QCOMPARE(list.count(), 1);
1324 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1327 Q_DECLARE_METATYPE(QList<QObject *>);
1328 void tst_qdeclarativeproperty::writeListToList()
1330 QDeclarativeComponent containerComponent(&engine);
1331 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1332 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1333 QVERIFY(container != 0);
1334 QDeclarativeListReference list(container, "children");
1335 QVERIFY(list.count() == 1);
1337 QList<QObject*> objList;
1338 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1339 QDeclarativeProperty prop(container, "children");
1340 prop.write(qVariantFromValue(objList));
1341 QCOMPARE(list.count(), 4);
1343 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1344 /*QList<MyQmlObject*> typedObjList;
1345 typedObjList << new MyQmlObject();
1346 prop.write(qVariantFromValue(&typedObjList));
1347 QCOMPARE(container->children()->size(), 1);*/
1350 void tst_qdeclarativeproperty::crashOnValueProperty()
1352 QDeclarativeEngine *engine = new QDeclarativeEngine;
1353 QDeclarativeComponent component(engine);
1355 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1356 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1359 QDeclarativeProperty p(obj, "wrectProperty.x", qmlContext(obj));
1360 QCOMPARE(p.name(), QString("wrectProperty.x"));
1362 QCOMPARE(p.read(), QVariant(10));
1364 //don't crash once the engine is deleted
1368 QCOMPARE(p.propertyTypeName(), "int");
1369 QCOMPARE(p.read(), QVariant(10));
1370 p.write(QVariant(20));
1371 QCOMPARE(p.read(), QVariant(20));
1375 void tst_qdeclarativeproperty::aliasPropertyBindings()
1377 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyBindings.qml"));
1379 QObject *object = component.create();
1380 QVERIFY(object != 0);
1382 QCOMPARE(object->property("realProperty").toReal(), 90.);
1383 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1385 object->setProperty("test", 10);
1387 QCOMPARE(object->property("realProperty").toReal(), 110.);
1388 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1390 QDeclarativeProperty realProperty(object, QLatin1String("realProperty"));
1391 QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty"));
1393 // Check there is a binding on these two properties
1394 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1395 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1397 // Check that its the same binding on these two properties
1398 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1399 QDeclarativePropertyPrivate::binding(aliasProperty));
1401 // Change the binding
1402 object->setProperty("state", QString("switch"));
1404 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1405 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1406 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1407 QDeclarativePropertyPrivate::binding(aliasProperty));
1409 QCOMPARE(object->property("realProperty").toReal(), 96.);
1410 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1412 // Check the old binding really has not effect any more
1413 object->setProperty("test", 4);
1415 QCOMPARE(object->property("realProperty").toReal(), 96.);
1416 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1418 object->setProperty("test2", 9);
1420 QCOMPARE(object->property("realProperty").toReal(), 288.);
1421 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1424 object->setProperty("state", QString(""));
1426 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1427 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1428 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1429 QDeclarativePropertyPrivate::binding(aliasProperty));
1431 QCOMPARE(object->property("realProperty").toReal(), 20.);
1432 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1434 object->setProperty("test2", 3);
1436 QCOMPARE(object->property("realProperty").toReal(), 20.);
1437 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1442 void tst_qdeclarativeproperty::copy()
1444 PropertyObject object;
1446 QDeclarativeProperty *property = new QDeclarativeProperty(&object, QLatin1String("defaultProperty"));
1447 QCOMPARE(property->name(), QString("defaultProperty"));
1448 QCOMPARE(property->read(), QVariant(10));
1449 QCOMPARE(property->type(), QDeclarativeProperty::Property);
1450 QCOMPARE(property->propertyTypeCategory(), QDeclarativeProperty::Normal);
1451 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1453 QDeclarativeProperty p1(*property);
1454 QCOMPARE(p1.name(), QString("defaultProperty"));
1455 QCOMPARE(p1.read(), QVariant(10));
1456 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1457 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1458 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1460 QDeclarativeProperty p2(&object, QLatin1String("url"));
1461 QCOMPARE(p2.name(), QString("url"));
1463 QCOMPARE(p2.name(), QString("defaultProperty"));
1464 QCOMPARE(p2.read(), QVariant(10));
1465 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1466 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1467 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1469 delete property; property = 0;
1471 QCOMPARE(p1.name(), QString("defaultProperty"));
1472 QCOMPARE(p1.read(), QVariant(10));
1473 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1474 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1475 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1477 QCOMPARE(p2.name(), QString("defaultProperty"));
1478 QCOMPARE(p2.read(), QVariant(10));
1479 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1480 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1481 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1484 void tst_qdeclarativeproperty::initTestCase()
1486 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1487 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1488 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1492 QTEST_MAIN(tst_qdeclarativeproperty)
1494 #include "tst_qdeclarativeproperty.moc"