1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtDeclarative/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>
50 #include "../../shared/util.h"
53 class MyQmlObject : public QObject
60 QML_DECLARE_TYPE(MyQmlObject);
62 class MyAttached : public QObject
65 Q_PROPERTY(int foo READ foo WRITE setFoo)
67 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
69 int foo() const { return m_foo; }
70 void setFoo(int f) { m_foo = f; }
76 class MyContainer : public QObject
79 Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children)
83 QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); }
85 static MyAttached *qmlAttachedProperties(QObject *o) {
86 return new MyAttached(o);
90 QList<MyQmlObject*> m_children;
93 QML_DECLARE_TYPE(MyContainer);
94 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
96 class tst_qdeclarativeproperty : public QDeclarativeDataTest
100 tst_qdeclarativeproperty() {}
106 void qmlmetaproperty();
107 void qmlmetaproperty_object();
108 void qmlmetaproperty_object_string();
109 void qmlmetaproperty_object_context();
110 void qmlmetaproperty_object_string_context();
119 void writeObjectToList();
120 void writeListToList();
124 void urlHandling_data();
128 void crashOnValueProperty();
129 void aliasPropertyBindings();
134 QDeclarativeEngine engine;
137 void tst_qdeclarativeproperty::qmlmetaproperty()
139 QDeclarativeProperty prop;
141 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
142 QVERIFY(binding != 0);
143 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
144 QVERIFY(expression != 0);
146 QObject *obj = new QObject;
148 QCOMPARE(prop.name(), QString());
149 QCOMPARE(prop.read(), QVariant());
150 QCOMPARE(prop.write(QVariant()), false);
151 QCOMPARE(prop.hasNotifySignal(), false);
152 QCOMPARE(prop.needsNotifySignal(), false);
153 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
154 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
155 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
156 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
157 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
158 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
159 QVERIFY(prop.method().signature() == 0);
160 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
161 QCOMPARE(prop.isProperty(), false);
162 QCOMPARE(prop.isWritable(), false);
163 QCOMPARE(prop.isDesignable(), false);
164 QCOMPARE(prop.isResettable(), false);
165 QCOMPARE(prop.isSignalProperty(), false);
166 QCOMPARE(prop.isValid(), false);
167 QCOMPARE(prop.object(), (QObject *)0);
168 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
169 QCOMPARE(prop.propertyType(), 0);
170 QCOMPARE(prop.propertyTypeName(), (const char *)0);
171 QVERIFY(prop.property().name() == 0);
172 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
173 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
174 QVERIFY(binding == 0);
175 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
176 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
177 QVERIFY(expression == 0);
178 QCOMPARE(prop.index(), -1);
179 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
184 class PropertyObject : public QObject
187 Q_PROPERTY(int defaultProperty READ defaultProperty)
188 Q_PROPERTY(QRect rectProperty READ rectProperty)
189 Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
190 Q_PROPERTY(QUrl url READ url WRITE setUrl)
191 Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
192 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
193 Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
195 Q_CLASSINFO("DefaultProperty", "defaultProperty")
197 PropertyObject() : m_resetProperty(9) {}
199 int defaultProperty() { return 10; }
200 QRect rectProperty() { return QRect(10, 10, 1, 209); }
202 QRect wrectProperty() { return m_rect; }
203 void setWRectProperty(const QRect &r) { m_rect = r; }
205 QUrl url() { return m_url; }
206 void setUrl(const QUrl &u) { m_url = u; }
208 int resettableProperty() const { return m_resetProperty; }
209 void setResettableProperty(int r) { m_resetProperty = r; }
210 void resetProperty() { m_resetProperty = 9; }
212 int propertyWithNotify() const { return m_propertyWithNotify; }
213 void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
215 MyQmlObject *qmlObject() { return &m_qmlObject; }
218 void oddlyNamedNotifySignal();
224 int m_propertyWithNotify;
225 MyQmlObject m_qmlObject;
228 QML_DECLARE_TYPE(PropertyObject);
230 void tst_qdeclarativeproperty::qmlmetaproperty_object()
232 QObject object; // Has no default property
233 PropertyObject dobject; // Has default property
236 QDeclarativeProperty prop(&object);
238 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
239 QVERIFY(binding != 0);
240 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
241 QVERIFY(expression != 0);
243 QObject *obj = new QObject;
245 QCOMPARE(prop.name(), QString());
246 QCOMPARE(prop.read(), QVariant());
247 QCOMPARE(prop.write(QVariant()), false);
248 QCOMPARE(prop.hasNotifySignal(), false);
249 QCOMPARE(prop.needsNotifySignal(), false);
250 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
251 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
252 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
253 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
254 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
255 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
256 QVERIFY(prop.method().signature() == 0);
257 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
258 QCOMPARE(prop.isProperty(), false);
259 QCOMPARE(prop.isWritable(), false);
260 QCOMPARE(prop.isDesignable(), false);
261 QCOMPARE(prop.isResettable(), false);
262 QCOMPARE(prop.isSignalProperty(), false);
263 QCOMPARE(prop.isValid(), false);
264 QCOMPARE(prop.object(), (QObject *)0);
265 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
266 QCOMPARE(prop.propertyType(), 0);
267 QCOMPARE(prop.propertyTypeName(), (const char *)0);
268 QVERIFY(prop.property().name() == 0);
269 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
270 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
271 QVERIFY(binding == 0);
272 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
273 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
274 QVERIFY(expression == 0);
275 QCOMPARE(prop.index(), -1);
276 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
282 QDeclarativeProperty prop(&dobject);
284 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
285 binding.data()->setTarget(prop);
286 QVERIFY(binding != 0);
287 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
288 QVERIFY(expression != 0);
290 QObject *obj = new QObject;
292 QCOMPARE(prop.name(), QString("defaultProperty"));
293 QCOMPARE(prop.read(), QVariant(10));
294 QCOMPARE(prop.write(QVariant()), false);
295 QCOMPARE(prop.hasNotifySignal(), false);
296 QCOMPARE(prop.needsNotifySignal(), true);
297 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
298 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
299 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
300 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
301 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
302 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
303 QVERIFY(prop.method().signature() == 0);
304 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
305 QCOMPARE(prop.isProperty(), true);
306 QCOMPARE(prop.isWritable(), false);
307 QCOMPARE(prop.isDesignable(), true);
308 QCOMPARE(prop.isResettable(), false);
309 QCOMPARE(prop.isSignalProperty(), false);
310 QCOMPARE(prop.isValid(), true);
311 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
312 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
313 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
314 QCOMPARE(prop.propertyTypeName(), "int");
315 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
316 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
317 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
318 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
319 QVERIFY(binding != 0);
320 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
321 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
322 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
323 QVERIFY(expression == 0);
324 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
325 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
331 void tst_qdeclarativeproperty::qmlmetaproperty_object_string()
334 PropertyObject dobject;
337 QDeclarativeProperty prop(&object, QString("defaultProperty"));
339 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
340 QVERIFY(binding != 0);
341 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
342 QVERIFY(expression != 0);
344 QObject *obj = new QObject;
346 QCOMPARE(prop.name(), QString());
347 QCOMPARE(prop.read(), QVariant());
348 QCOMPARE(prop.write(QVariant()), false);
349 QCOMPARE(prop.hasNotifySignal(), false);
350 QCOMPARE(prop.needsNotifySignal(), false);
351 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
352 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
353 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
354 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
355 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
356 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
357 QVERIFY(prop.method().signature() == 0);
358 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
359 QCOMPARE(prop.isProperty(), false);
360 QCOMPARE(prop.isWritable(), false);
361 QCOMPARE(prop.isDesignable(), false);
362 QCOMPARE(prop.isResettable(), false);
363 QCOMPARE(prop.isSignalProperty(), false);
364 QCOMPARE(prop.isValid(), false);
365 QCOMPARE(prop.object(), (QObject *)0);
366 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
367 QCOMPARE(prop.propertyType(), 0);
368 QCOMPARE(prop.propertyTypeName(), (const char *)0);
369 QVERIFY(prop.property().name() == 0);
370 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
371 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
372 QVERIFY(binding == 0);
373 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
374 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
375 QVERIFY(expression == 0);
376 QCOMPARE(prop.index(), -1);
377 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
383 QDeclarativeProperty prop(&dobject, QString("defaultProperty"));
385 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
386 binding.data()->setTarget(prop);
387 QVERIFY(binding != 0);
388 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
389 QVERIFY(expression != 0);
391 QObject *obj = new QObject;
393 QCOMPARE(prop.name(), QString("defaultProperty"));
394 QCOMPARE(prop.read(), QVariant(10));
395 QCOMPARE(prop.write(QVariant()), false);
396 QCOMPARE(prop.hasNotifySignal(), false);
397 QCOMPARE(prop.needsNotifySignal(), true);
398 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
399 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
400 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
401 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
402 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
403 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
404 QVERIFY(prop.method().signature() == 0);
405 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
406 QCOMPARE(prop.isProperty(), true);
407 QCOMPARE(prop.isWritable(), false);
408 QCOMPARE(prop.isDesignable(), true);
409 QCOMPARE(prop.isResettable(), false);
410 QCOMPARE(prop.isSignalProperty(), false);
411 QCOMPARE(prop.isValid(), true);
412 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
413 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
414 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
415 QCOMPARE(prop.propertyTypeName(), "int");
416 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
417 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
418 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
419 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
420 QVERIFY(binding != 0);
421 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
422 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
423 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
424 QVERIFY(expression == 0);
425 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
426 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
432 QDeclarativeProperty prop(&dobject, QString("onClicked"));
434 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
435 binding.data()->setTarget(prop);
436 QVERIFY(binding != 0);
437 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
438 QVERIFY(expression != 0);
440 QObject *obj = new QObject;
442 QCOMPARE(prop.name(), QString("onClicked"));
443 QCOMPARE(prop.read(), QVariant());
444 QCOMPARE(prop.write(QVariant("Hello")), false);
445 QCOMPARE(prop.hasNotifySignal(), false);
446 QCOMPARE(prop.needsNotifySignal(), false);
447 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
448 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
449 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
450 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
451 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
452 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
453 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
454 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
455 QCOMPARE(prop.isProperty(), false);
456 QCOMPARE(prop.isWritable(), false);
457 QCOMPARE(prop.isDesignable(), false);
458 QCOMPARE(prop.isResettable(), false);
459 QCOMPARE(prop.isSignalProperty(), true);
460 QCOMPARE(prop.isValid(), true);
461 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
462 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
463 QCOMPARE(prop.propertyType(), 0);
464 QCOMPARE(prop.propertyTypeName(), (const char *)0);
465 QCOMPARE(prop.property().name(), (const char *)0);
466 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
467 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
468 QVERIFY(binding == 0);
469 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
470 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
471 QVERIFY(expression != 0);
472 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
473 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
474 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
480 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
482 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
483 binding.data()->setTarget(prop);
484 QVERIFY(binding != 0);
485 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
486 QVERIFY(expression != 0);
488 QObject *obj = new QObject;
490 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
491 QCOMPARE(prop.read(), QVariant());
492 QCOMPARE(prop.write(QVariant("Hello")), false);
493 QCOMPARE(prop.hasNotifySignal(), false);
494 QCOMPARE(prop.needsNotifySignal(), false);
495 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
496 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
497 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
498 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
499 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
500 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
501 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
502 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
503 QCOMPARE(prop.isProperty(), false);
504 QCOMPARE(prop.isWritable(), false);
505 QCOMPARE(prop.isDesignable(), false);
506 QCOMPARE(prop.isResettable(), false);
507 QCOMPARE(prop.isSignalProperty(), true);
508 QCOMPARE(prop.isValid(), true);
509 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
510 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
511 QCOMPARE(prop.propertyType(), 0);
512 QCOMPARE(prop.propertyTypeName(), (const char *)0);
513 QCOMPARE(prop.property().name(), (const char *)0);
514 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
515 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
516 QVERIFY(binding == 0);
517 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
518 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
519 QVERIFY(expression != 0);
520 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
521 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
522 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
528 void tst_qdeclarativeproperty::qmlmetaproperty_object_context()
530 QObject object; // Has no default property
531 PropertyObject dobject; // Has default property
534 QDeclarativeProperty prop(&object, engine.rootContext());
536 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
537 QVERIFY(binding != 0);
538 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
539 QVERIFY(expression != 0);
541 QObject *obj = new QObject;
543 QCOMPARE(prop.name(), QString());
544 QCOMPARE(prop.read(), QVariant());
545 QCOMPARE(prop.write(QVariant()), false);
546 QCOMPARE(prop.hasNotifySignal(), false);
547 QCOMPARE(prop.needsNotifySignal(), false);
548 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
549 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
550 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
551 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
552 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
553 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
554 QVERIFY(prop.method().signature() == 0);
555 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
556 QCOMPARE(prop.isProperty(), false);
557 QCOMPARE(prop.isWritable(), false);
558 QCOMPARE(prop.isDesignable(), false);
559 QCOMPARE(prop.isResettable(), false);
560 QCOMPARE(prop.isSignalProperty(), false);
561 QCOMPARE(prop.isValid(), false);
562 QCOMPARE(prop.object(), (QObject *)0);
563 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
564 QCOMPARE(prop.propertyType(), 0);
565 QCOMPARE(prop.propertyTypeName(), (const char *)0);
566 QVERIFY(prop.property().name() == 0);
567 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
568 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
569 QVERIFY(binding == 0);
570 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
571 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
572 QVERIFY(expression == 0);
573 QCOMPARE(prop.index(), -1);
574 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
580 QDeclarativeProperty prop(&dobject, engine.rootContext());
582 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
583 binding.data()->setTarget(prop);
584 QVERIFY(binding != 0);
585 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
586 QVERIFY(expression != 0);
588 QObject *obj = new QObject;
590 QCOMPARE(prop.name(), QString("defaultProperty"));
591 QCOMPARE(prop.read(), QVariant(10));
592 QCOMPARE(prop.write(QVariant()), false);
593 QCOMPARE(prop.hasNotifySignal(), false);
594 QCOMPARE(prop.needsNotifySignal(), true);
595 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
596 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
597 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
598 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
599 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
600 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
601 QVERIFY(prop.method().signature() == 0);
602 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
603 QCOMPARE(prop.isProperty(), true);
604 QCOMPARE(prop.isWritable(), false);
605 QCOMPARE(prop.isDesignable(), true);
606 QCOMPARE(prop.isResettable(), false);
607 QCOMPARE(prop.isSignalProperty(), false);
608 QCOMPARE(prop.isValid(), true);
609 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
610 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
611 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
612 QCOMPARE(prop.propertyTypeName(), "int");
613 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
614 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
615 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
616 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
617 QVERIFY(binding != 0);
618 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
619 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
620 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
621 QVERIFY(expression == 0);
622 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
623 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
629 void tst_qdeclarativeproperty::qmlmetaproperty_object_string_context()
632 PropertyObject dobject;
635 QDeclarativeProperty prop(&object, QString("defaultProperty"), engine.rootContext());
637 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
638 QVERIFY(binding != 0);
639 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
640 QVERIFY(expression != 0);
642 QObject *obj = new QObject;
644 QCOMPARE(prop.name(), QString());
645 QCOMPARE(prop.read(), QVariant());
646 QCOMPARE(prop.write(QVariant()), false);
647 QCOMPARE(prop.hasNotifySignal(), false);
648 QCOMPARE(prop.needsNotifySignal(), false);
649 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
650 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
651 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
652 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
653 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
654 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
655 QVERIFY(prop.method().signature() == 0);
656 QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
657 QCOMPARE(prop.isProperty(), false);
658 QCOMPARE(prop.isWritable(), false);
659 QCOMPARE(prop.isDesignable(), false);
660 QCOMPARE(prop.isResettable(), false);
661 QCOMPARE(prop.isSignalProperty(), false);
662 QCOMPARE(prop.isValid(), false);
663 QCOMPARE(prop.object(), (QObject *)0);
664 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
665 QCOMPARE(prop.propertyType(), 0);
666 QCOMPARE(prop.propertyTypeName(), (const char *)0);
667 QVERIFY(prop.property().name() == 0);
668 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
669 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
670 QVERIFY(binding == 0);
671 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
672 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
673 QVERIFY(expression == 0);
674 QCOMPARE(prop.index(), -1);
675 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
681 QDeclarativeProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
683 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
684 binding.data()->setTarget(prop);
685 QVERIFY(binding != 0);
686 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
687 QVERIFY(expression != 0);
689 QObject *obj = new QObject;
691 QCOMPARE(prop.name(), QString("defaultProperty"));
692 QCOMPARE(prop.read(), QVariant(10));
693 QCOMPARE(prop.write(QVariant()), false);
694 QCOMPARE(prop.hasNotifySignal(), false);
695 QCOMPARE(prop.needsNotifySignal(), true);
696 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
697 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
698 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
699 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
700 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
701 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
702 QVERIFY(prop.method().signature() == 0);
703 QCOMPARE(prop.type(), QDeclarativeProperty::Property);
704 QCOMPARE(prop.isProperty(), true);
705 QCOMPARE(prop.isWritable(), false);
706 QCOMPARE(prop.isDesignable(), true);
707 QCOMPARE(prop.isResettable(), false);
708 QCOMPARE(prop.isSignalProperty(), false);
709 QCOMPARE(prop.isValid(), true);
710 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
711 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
712 QCOMPARE(prop.propertyType(), (int)QVariant::Int);
713 QCOMPARE(prop.propertyTypeName(), "int");
714 QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
715 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
716 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
717 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
718 QVERIFY(binding != 0);
719 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
720 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
721 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
722 QVERIFY(expression == 0);
723 QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
724 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
730 QDeclarativeProperty prop(&dobject, QString("onClicked"), engine.rootContext());
732 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
733 binding.data()->setTarget(prop);
734 QVERIFY(binding != 0);
735 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
736 QVERIFY(expression != 0);
738 QObject *obj = new QObject;
740 QCOMPARE(prop.name(), QString("onClicked"));
741 QCOMPARE(prop.read(), QVariant());
742 QCOMPARE(prop.write(QVariant("Hello")), false);
743 QCOMPARE(prop.hasNotifySignal(), false);
744 QCOMPARE(prop.needsNotifySignal(), false);
745 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
746 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
747 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
748 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
749 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
750 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
751 QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
752 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
753 QCOMPARE(prop.isProperty(), false);
754 QCOMPARE(prop.isWritable(), false);
755 QCOMPARE(prop.isDesignable(), false);
756 QCOMPARE(prop.isResettable(), false);
757 QCOMPARE(prop.isSignalProperty(), true);
758 QCOMPARE(prop.isValid(), true);
759 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
760 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
761 QCOMPARE(prop.propertyType(), 0);
762 QCOMPARE(prop.propertyTypeName(), (const char *)0);
763 QCOMPARE(prop.property().name(), (const char *)0);
764 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
765 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
766 QVERIFY(binding == 0);
767 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
768 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
769 QVERIFY(expression != 0);
770 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
771 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
772 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
778 QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
780 QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
781 binding.data()->setTarget(prop);
782 QVERIFY(binding != 0);
783 QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
784 QVERIFY(expression != 0);
786 QObject *obj = new QObject;
788 QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
789 QCOMPARE(prop.read(), QVariant());
790 QCOMPARE(prop.write(QVariant("Hello")), false);
791 QCOMPARE(prop.hasNotifySignal(), false);
792 QCOMPARE(prop.needsNotifySignal(), false);
793 QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
794 QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
795 QCOMPARE(prop.connectNotifySignal(obj, 0), false);
796 QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
797 QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
798 QCOMPARE(prop.connectNotifySignal(obj, -1), false);
799 QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
800 QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
801 QCOMPARE(prop.isProperty(), false);
802 QCOMPARE(prop.isWritable(), false);
803 QCOMPARE(prop.isDesignable(), false);
804 QCOMPARE(prop.isResettable(), false);
805 QCOMPARE(prop.isSignalProperty(), true);
806 QCOMPARE(prop.isValid(), true);
807 QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
808 QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
809 QCOMPARE(prop.propertyType(), 0);
810 QCOMPARE(prop.propertyTypeName(), (const char *)0);
811 QCOMPARE(prop.property().name(), (const char *)0);
812 QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
813 QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
814 QVERIFY(binding == 0);
815 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
816 QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
817 QVERIFY(expression != 0);
818 QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
819 QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
820 QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
826 void tst_qdeclarativeproperty::name()
829 QDeclarativeProperty p;
830 QCOMPARE(p.name(), QString());
835 QDeclarativeProperty p(&o);
836 QCOMPARE(p.name(), QString("defaultProperty"));
841 QDeclarativeProperty p(&o, QString("objectName"));
842 QCOMPARE(p.name(), QString("objectName"));
847 QDeclarativeProperty p(&o, "onClicked");
848 QCOMPARE(p.name(), QString("onClicked"));
853 QDeclarativeProperty p(&o, "onClicked");
854 QCOMPARE(p.name(), QString());
859 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
860 QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
865 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
866 QCOMPARE(p.name(), QString());
871 QDeclarativeProperty p(&o, "foo");
872 QCOMPARE(p.name(), QString());
876 QDeclarativeProperty p(0, "foo");
877 QCOMPARE(p.name(), QString());
882 QDeclarativeProperty p(&o, "rectProperty");
883 QCOMPARE(p.name(), QString("rectProperty"));
888 QDeclarativeProperty p(&o, "rectProperty.x");
889 QCOMPARE(p.name(), QString("rectProperty.x"));
894 QDeclarativeProperty p(&o, "rectProperty.foo");
895 QCOMPARE(p.name(), QString());
899 void tst_qdeclarativeproperty::read()
903 QDeclarativeProperty p;
904 QCOMPARE(p.read(), QVariant());
910 QDeclarativeProperty p(&o);
911 QCOMPARE(p.read(), QVariant(10));
914 // Invalid default prop
917 QDeclarativeProperty p(&o);
918 QCOMPARE(p.read(), QVariant());
921 // Value prop by name
925 QDeclarativeProperty p(&o, "objectName");
926 QCOMPARE(p.read(), QVariant(QString()));
928 o.setObjectName("myName");
930 QCOMPARE(p.read(), QVariant("myName"));
933 // Value prop by name (static)
937 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant(QString()));
939 o.setObjectName("myName");
941 QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant("myName"));
947 QDeclarativeProperty p(&o, "rectProperty.x");
948 QCOMPARE(p.read(), QVariant(10));
951 // Invalid value-type prop
954 QDeclarativeProperty p(&o, "rectProperty.foo");
955 QCOMPARE(p.read(), QVariant());
961 QDeclarativeProperty p(&o, "onClicked");
962 QCOMPARE(p.read(), QVariant());
964 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
965 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
967 QCOMPARE(p.read(), QVariant());
970 // Automatic signal property
973 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
974 QCOMPARE(p.read(), QVariant());
976 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
977 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
979 QCOMPARE(p.read(), QVariant());
984 PropertyObject *o = new PropertyObject;
985 QDeclarativeProperty p(o, "rectProperty.x");
986 QCOMPARE(p.read(), QVariant(10));
988 QCOMPARE(p.read(), QVariant());
994 QDeclarativeProperty p(&o, "qmlObject");
995 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
996 QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
997 QVariant v = p.read();
998 QVERIFY(v.userType() == QMetaType::QObjectStar);
999 QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1002 QDeclarativeComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1003 QObject *object = component.create();
1004 QVERIFY(object != 0);
1006 QDeclarativeProperty p(object, "test", &engine);
1008 QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1009 QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1011 QVariant v = p.read();
1012 QVERIFY(v.userType() == QMetaType::QObjectStar);
1013 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1014 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1017 QDeclarativeComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1018 QObject *object = component.create();
1019 QVERIFY(object != 0);
1021 QVariant v = QDeclarativeProperty::read(object, "test", &engine);
1022 QVERIFY(v.userType() == QMetaType::QObjectStar);
1023 QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1024 QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1027 // Attached property
1029 QDeclarativeComponent component(&engine);
1030 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1031 QObject *object = component.create();
1032 QVERIFY(object != 0);
1034 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1035 QCOMPARE(p.read(), QVariant(13));
1039 QDeclarativeComponent component(&engine);
1040 component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1041 QObject *object = component.create();
1042 QVERIFY(object != 0);
1044 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1045 QCOMPARE(p.read(), QVariant(10));
1049 QDeclarativeComponent component(&engine);
1050 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1051 QObject *object = component.create();
1052 QVERIFY(object != 0);
1054 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1055 QCOMPARE(p.read(), QVariant(10));
1059 QDeclarativeComponent component(&engine);
1060 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1061 QObject *object = component.create();
1062 QVERIFY(object != 0);
1064 QCOMPARE(QDeclarativeProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1069 void tst_qdeclarativeproperty::write()
1073 QDeclarativeProperty p;
1074 QCOMPARE(p.write(QVariant(10)), false);
1077 // Read-only default prop
1080 QDeclarativeProperty p(&o);
1081 QCOMPARE(p.write(QVariant(10)), false);
1084 // Invalid default prop
1087 QDeclarativeProperty p(&o);
1088 QCOMPARE(p.write(QVariant(10)), false);
1091 // Read-only prop by name
1094 QDeclarativeProperty p(&o, QString("defaultProperty"));
1095 QCOMPARE(p.write(QVariant(10)), false);
1098 // Writable prop by name
1101 QDeclarativeProperty p(&o, QString("objectName"));
1102 QCOMPARE(o.objectName(), QString());
1103 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1104 QCOMPARE(o.objectName(), QString("myName"));
1107 // Writable prop by name (static)
1110 QCOMPARE(QDeclarativeProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1111 QCOMPARE(o.objectName(), QString("myName"));
1116 PropertyObject *o = new PropertyObject;
1117 QDeclarativeProperty p(o, QString("objectName"));
1118 QCOMPARE(p.write(QVariant(QString("myName"))), true);
1119 QCOMPARE(o->objectName(), QString("myName"));
1123 QCOMPARE(p.write(QVariant(QString("myName"))), false);
1129 QDeclarativeProperty p(&o, "onClicked");
1130 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1132 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1133 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1135 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1137 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1140 // Automatic signal property
1143 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1144 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1146 QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1147 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1149 QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1151 QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1154 // Value-type property
1157 QDeclarativeProperty p(&o, "wrectProperty");
1159 QCOMPARE(o.wrectProperty(), QRect());
1160 QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1161 QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1163 QDeclarativeProperty p2(&o, "wrectProperty.x");
1164 QCOMPARE(p2.read(), QVariant(1));
1165 QCOMPARE(p2.write(QVariant(6)), true);
1166 QCOMPARE(p2.read(), QVariant(6));
1167 QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1173 QDeclarativeProperty p(&o, "url");
1175 QCOMPARE(p.write(QUrl("main.qml")), true);
1176 QCOMPARE(o.url(), QUrl("main.qml"));
1178 QDeclarativeProperty p2(&o, "url", engine.rootContext());
1180 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1181 QVERIFY(result != QUrl("main.qml"));
1183 QCOMPARE(p2.write(QUrl("main.qml")), true);
1184 QCOMPARE(o.url(), result);
1189 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml")), true);
1190 QCOMPARE(o.url(), QUrl("main.qml"));
1192 QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1193 QVERIFY(result != QUrl("main.qml"));
1195 QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1196 QCOMPARE(o.url(), result);
1199 // Attached property
1201 QDeclarativeComponent component(&engine);
1202 component.setData("import Test 1.0\nMyContainer { }", QUrl());
1203 QObject *object = component.create();
1204 QVERIFY(object != 0);
1206 QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1207 p.write(QVariant(99));
1208 QCOMPARE(p.read(), QVariant(99));
1212 QDeclarativeComponent component(&engine);
1213 component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1214 QObject *object = component.create();
1215 QVERIFY(object != 0);
1217 QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1218 p.write(QVariant(99));
1219 QCOMPARE(p.read(), QVariant(99));
1224 void tst_qdeclarativeproperty::reset()
1228 QDeclarativeProperty p;
1229 QCOMPARE(p.isResettable(), false);
1230 QCOMPARE(p.reset(), false);
1233 // Read-only default prop
1236 QDeclarativeProperty p(&o);
1237 QCOMPARE(p.isResettable(), false);
1238 QCOMPARE(p.reset(), false);
1241 // Invalid default prop
1244 QDeclarativeProperty p(&o);
1245 QCOMPARE(p.isResettable(), false);
1246 QCOMPARE(p.reset(), false);
1249 // Non-resettable-only prop by name
1252 QDeclarativeProperty p(&o, QString("defaultProperty"));
1253 QCOMPARE(p.isResettable(), false);
1254 QCOMPARE(p.reset(), false);
1257 // Resettable prop by name
1260 QDeclarativeProperty p(&o, QString("resettableProperty"));
1262 QCOMPARE(p.read(), QVariant(9));
1263 QCOMPARE(p.write(QVariant(11)), true);
1264 QCOMPARE(p.read(), QVariant(11));
1266 QCOMPARE(p.isResettable(), true);
1267 QCOMPARE(p.reset(), true);
1269 QCOMPARE(p.read(), QVariant(9));
1274 PropertyObject *o = new PropertyObject;
1276 QDeclarativeProperty p(o, QString("resettableProperty"));
1278 QCOMPARE(p.isResettable(), true);
1279 QCOMPARE(p.reset(), true);
1283 QCOMPARE(p.isResettable(), false);
1284 QCOMPARE(p.reset(), false);
1290 QDeclarativeProperty p(&o, "onClicked");
1292 QCOMPARE(p.isResettable(), false);
1293 QCOMPARE(p.reset(), false);
1296 // Automatic signal property
1299 QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1301 QCOMPARE(p.isResettable(), false);
1302 QCOMPARE(p.reset(), false);
1306 void tst_qdeclarativeproperty::writeObjectToList()
1308 QDeclarativeComponent containerComponent(&engine);
1309 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1310 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1311 QVERIFY(container != 0);
1312 QDeclarativeListReference list(container, "children");
1313 QVERIFY(list.count() == 1);
1315 MyQmlObject *object = new MyQmlObject;
1316 QDeclarativeProperty prop(container, "children");
1317 prop.write(qVariantFromValue(object));
1318 QCOMPARE(list.count(), 1);
1319 QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1322 Q_DECLARE_METATYPE(QList<QObject *>);
1323 void tst_qdeclarativeproperty::writeListToList()
1325 QDeclarativeComponent containerComponent(&engine);
1326 containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1327 MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1328 QVERIFY(container != 0);
1329 QDeclarativeListReference list(container, "children");
1330 QVERIFY(list.count() == 1);
1332 QList<QObject*> objList;
1333 objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1334 QDeclarativeProperty prop(container, "children");
1335 prop.write(qVariantFromValue(objList));
1336 QCOMPARE(list.count(), 4);
1338 //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1339 /*QList<MyQmlObject*> typedObjList;
1340 typedObjList << new MyQmlObject();
1341 prop.write(qVariantFromValue(&typedObjList));
1342 QCOMPARE(container->children()->size(), 1);*/
1345 void tst_qdeclarativeproperty::urlHandling_data()
1347 QTest::addColumn<QByteArray>("input");
1348 QTest::addColumn<QString>("scheme");
1349 QTest::addColumn<QString>("path");
1350 QTest::addColumn<QByteArray>("encoded");
1352 QTest::newRow("unspecifiedFile")
1353 << QByteArray("main.qml")
1355 << QString("main.qml")
1356 << QByteArray("main.qml");
1358 QTest::newRow("specifiedFile")
1359 << QByteArray("file:///main.qml")
1361 << QString("/main.qml")
1362 << QByteArray("file:///main.qml");
1364 QTest::newRow("httpFile")
1365 << QByteArray("http://www.example.com/main.qml")
1367 << QString("/main.qml")
1368 << QByteArray("http://www.example.com/main.qml");
1370 QTest::newRow("pathFile")
1371 << QByteArray("http://www.example.com/resources/main.qml")
1373 << QString("/resources/main.qml")
1374 << QByteArray("http://www.example.com/resources/main.qml");
1376 QTest::newRow("encodableName")
1377 << QByteArray("http://www.example.com/main file.qml")
1379 << QString("/main file.qml")
1380 << QByteArray("http://www.example.com/main%20file.qml");
1382 QTest::newRow("preencodedName")
1383 << QByteArray("http://www.example.com/resources%7cmain%20file.qml")
1385 << QString("/resources|main file.qml")
1386 << QByteArray("http://www.example.com/resources%7cmain%20file.qml");
1388 QTest::newRow("encodableQuery")
1389 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now working?")
1391 << QString("/main.qml")
1392 << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now%20working?");
1394 QTest::newRow("preencodedQuery")
1395 << QByteArray("http://www.example.com/main.qml?type=text%2fqml&comment=now working%3f")
1397 << QString("/main.qml")
1398 << QByteArray("http://www.example.com/main.qml?type=text%2fqml&comment=now%20working%3f");
1400 QTest::newRow("encodableFragment")
1401 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000|volume+50%")
1403 << QString("/main.qml")
1404 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume+50%25");
1406 QTest::newRow("preencodedFragment")
1407 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7cvolume%2b50%")
1409 << QString("/main.qml")
1410 << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7cvolume%2b50%25");
1413 void tst_qdeclarativeproperty::urlHandling()
1415 QFETCH(QByteArray, input);
1416 QFETCH(QString, scheme);
1417 QFETCH(QString, path);
1418 QFETCH(QByteArray, encoded);
1420 QString inputString(QString::fromUtf8(input));
1424 QDeclarativeProperty p(&o, "url");
1426 // Test url written as QByteArray
1427 QCOMPARE(p.write(input), true);
1428 QUrl byteArrayResult(o.url());
1430 QCOMPARE(byteArrayResult.scheme(), scheme);
1431 QCOMPARE(byteArrayResult.path(), path);
1432 QCOMPARE(byteArrayResult.toEncoded(), encoded);
1437 QDeclarativeProperty p(&o, "url");
1439 // Test url written as QString
1440 QCOMPARE(p.write(inputString), true);
1441 QUrl stringResult(o.url());
1443 QCOMPARE(stringResult.scheme(), scheme);
1444 QCOMPARE(stringResult.path(), path);
1445 QCOMPARE(stringResult.toEncoded(), encoded);
1449 void tst_qdeclarativeproperty::crashOnValueProperty()
1451 QDeclarativeEngine *engine = new QDeclarativeEngine;
1452 QDeclarativeComponent component(engine);
1454 component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1455 PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1458 QDeclarativeProperty p(obj, "wrectProperty.x", qmlContext(obj));
1459 QCOMPARE(p.name(), QString("wrectProperty.x"));
1461 QCOMPARE(p.read(), QVariant(10));
1463 //don't crash once the engine is deleted
1467 QCOMPARE(p.propertyTypeName(), "int");
1468 QCOMPARE(p.read(), QVariant(10));
1469 p.write(QVariant(20));
1470 QCOMPARE(p.read(), QVariant(20));
1474 void tst_qdeclarativeproperty::aliasPropertyBindings()
1476 QDeclarativeComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
1478 QObject *object = component.create();
1479 QVERIFY(object != 0);
1481 QCOMPARE(object->property("realProperty").toReal(), 90.);
1482 QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1484 object->setProperty("test", 10);
1486 QCOMPARE(object->property("realProperty").toReal(), 110.);
1487 QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1489 QDeclarativeProperty realProperty(object, QLatin1String("realProperty"));
1490 QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty"));
1492 // Check there is a binding on these two properties
1493 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1494 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1496 // Check that its the same binding on these two properties
1497 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1498 QDeclarativePropertyPrivate::binding(aliasProperty));
1500 // Change the binding
1501 object->setProperty("state", QString("switch"));
1503 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1504 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1505 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1506 QDeclarativePropertyPrivate::binding(aliasProperty));
1508 QCOMPARE(object->property("realProperty").toReal(), 96.);
1509 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1511 // Check the old binding really has not effect any more
1512 object->setProperty("test", 4);
1514 QCOMPARE(object->property("realProperty").toReal(), 96.);
1515 QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1517 object->setProperty("test2", 9);
1519 QCOMPARE(object->property("realProperty").toReal(), 288.);
1520 QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1523 object->setProperty("state", QString(""));
1525 QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1526 QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1527 QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1528 QDeclarativePropertyPrivate::binding(aliasProperty));
1530 QCOMPARE(object->property("realProperty").toReal(), 20.);
1531 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1533 object->setProperty("test2", 3);
1535 QCOMPARE(object->property("realProperty").toReal(), 20.);
1536 QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1541 void tst_qdeclarativeproperty::copy()
1543 PropertyObject object;
1545 QDeclarativeProperty *property = new QDeclarativeProperty(&object, QLatin1String("defaultProperty"));
1546 QCOMPARE(property->name(), QString("defaultProperty"));
1547 QCOMPARE(property->read(), QVariant(10));
1548 QCOMPARE(property->type(), QDeclarativeProperty::Property);
1549 QCOMPARE(property->propertyTypeCategory(), QDeclarativeProperty::Normal);
1550 QCOMPARE(property->propertyType(), (int)QVariant::Int);
1552 QDeclarativeProperty p1(*property);
1553 QCOMPARE(p1.name(), QString("defaultProperty"));
1554 QCOMPARE(p1.read(), QVariant(10));
1555 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1556 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1557 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1559 QDeclarativeProperty p2(&object, QLatin1String("url"));
1560 QCOMPARE(p2.name(), QString("url"));
1562 QCOMPARE(p2.name(), QString("defaultProperty"));
1563 QCOMPARE(p2.read(), QVariant(10));
1564 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1565 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1566 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1568 delete property; property = 0;
1570 QCOMPARE(p1.name(), QString("defaultProperty"));
1571 QCOMPARE(p1.read(), QVariant(10));
1572 QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1573 QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1574 QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1576 QCOMPARE(p2.name(), QString("defaultProperty"));
1577 QCOMPARE(p2.read(), QVariant(10));
1578 QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1579 QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1580 QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1583 void tst_qdeclarativeproperty::noContext()
1585 QDeclarativeComponent compA(&engine, testFileUrl("NoContextTypeA.qml"));
1586 QDeclarativeComponent compB(&engine, testFileUrl("NoContextTypeB.qml"));
1588 QObject *a = compA.create();
1590 QObject *b = compB.create();
1593 QVERIFY(QDeclarativeProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1599 void tst_qdeclarativeproperty::initTestCase()
1601 QDeclarativeDataTest::initTestCase();
1602 qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1603 qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1604 qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1607 QTEST_MAIN(tst_qdeclarativeproperty)
1609 #include "tst_qdeclarativeproperty.moc"