bc4053512e70dc934ff1a12c565c082204f0c652
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeproperty / tst_qdeclarativeproperty.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
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
51 inline QUrl TEST_FILE(const QString &filename)
52 {
53     QFileInfo fileInfo(__FILE__);
54     return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(QLatin1String("data/") + filename));
55 }
56
57 class MyQmlObject : public QObject
58 {
59     Q_OBJECT
60 public:
61     MyQmlObject() {}
62 };
63
64 QML_DECLARE_TYPE(MyQmlObject);
65
66 class MyAttached : public QObject
67 {
68     Q_OBJECT
69     Q_PROPERTY(int foo READ foo WRITE setFoo)
70 public:
71     MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
72
73     int foo() const { return m_foo; }
74     void setFoo(int f) { m_foo = f; }
75
76 private:
77     int m_foo;
78 };
79
80 class MyContainer : public QObject
81 {
82     Q_OBJECT
83     Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children)
84 public:
85     MyContainer() {}
86
87     QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); }
88
89     static MyAttached *qmlAttachedProperties(QObject *o) {
90         return new MyAttached(o);
91     }
92
93 private:
94     QList<MyQmlObject*> m_children;
95 };
96
97 QML_DECLARE_TYPE(MyContainer);
98 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
99
100 class tst_qdeclarativeproperty : public QObject
101 {
102     Q_OBJECT
103 public:
104     tst_qdeclarativeproperty() {}
105
106 private slots:
107     void initTestCase();
108
109     // Constructors
110     void qmlmetaproperty();
111     void qmlmetaproperty_object();
112     void qmlmetaproperty_object_string();
113     void qmlmetaproperty_object_context();
114     void qmlmetaproperty_object_string_context();
115
116     // Methods
117     void name();
118     void read();
119     void write();
120     void reset();
121
122     // Functionality
123     void writeObjectToList();
124     void writeListToList();
125
126     //writeToReadOnly();
127
128     // Bugs
129     void crashOnValueProperty();
130     void aliasPropertyBindings();
131     void noContext();
132
133     void copy();
134 private:
135     QDeclarativeEngine engine;
136 };
137
138 void tst_qdeclarativeproperty::qmlmetaproperty()
139 {
140     QDeclarativeProperty prop;
141
142     QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
143     QVERIFY(binding != 0);
144     QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
145     QVERIFY(expression != 0);
146
147     QObject *obj = new QObject;
148
149     QCOMPARE(prop.name(), QString());
150     QCOMPARE(prop.read(), QVariant());
151     QCOMPARE(prop.write(QVariant()), false);
152     QCOMPARE(prop.hasNotifySignal(), false);
153     QCOMPARE(prop.needsNotifySignal(), false);
154     QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
155     QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
156     QCOMPARE(prop.connectNotifySignal(obj, 0), false);
157     QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
158     QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
159     QCOMPARE(prop.connectNotifySignal(obj, -1), false);
160     QVERIFY(prop.method().signature() == 0);
161     QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
162     QCOMPARE(prop.isProperty(), false);
163     QCOMPARE(prop.isWritable(), false);
164     QCOMPARE(prop.isDesignable(), false);
165     QCOMPARE(prop.isResettable(), false);
166     QCOMPARE(prop.isSignalProperty(), false);
167     QCOMPARE(prop.isValid(), false);
168     QCOMPARE(prop.object(), (QObject *)0);
169     QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
170     QCOMPARE(prop.propertyType(), 0);
171     QCOMPARE(prop.propertyTypeName(), (const char *)0);
172     QVERIFY(prop.property().name() == 0);
173     QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
174     QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
175     QVERIFY(binding == 0);
176     QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
177     QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
178     QVERIFY(expression == 0);
179     QCOMPARE(prop.index(), -1);
180     QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
181
182     delete obj;
183 }
184
185 class PropertyObject : public QObject
186 {
187     Q_OBJECT
188     Q_PROPERTY(int defaultProperty READ defaultProperty)
189     Q_PROPERTY(QRect rectProperty READ rectProperty)
190     Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
191     Q_PROPERTY(QUrl url READ url WRITE setUrl)
192     Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
193     Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
194     Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
195
196     Q_CLASSINFO("DefaultProperty", "defaultProperty")
197 public:
198     PropertyObject() : m_resetProperty(9) {}
199
200     int defaultProperty() { return 10; }
201     QRect rectProperty() { return QRect(10, 10, 1, 209); }
202
203     QRect wrectProperty() { return m_rect; }
204     void setWRectProperty(const QRect &r) { m_rect = r; }
205
206     QUrl url() { return m_url; }
207     void setUrl(const QUrl &u) { m_url = u; }
208
209     int resettableProperty() const { return m_resetProperty; }
210     void setResettableProperty(int r) { m_resetProperty = r; }
211     void resetProperty() { m_resetProperty = 9; }
212
213     int propertyWithNotify() const { return m_propertyWithNotify; }
214     void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
215
216     MyQmlObject *qmlObject() { return &m_qmlObject; }
217 signals:
218     void clicked();
219     void oddlyNamedNotifySignal();
220
221 private:
222     int m_resetProperty;
223     QRect m_rect;
224     QUrl m_url;
225     int m_propertyWithNotify;
226     MyQmlObject m_qmlObject;
227 };
228
229 QML_DECLARE_TYPE(PropertyObject);
230
231 void tst_qdeclarativeproperty::qmlmetaproperty_object()
232 {
233     QObject object; // Has no default property
234     PropertyObject dobject; // Has default property
235
236     {
237         QDeclarativeProperty prop(&object);
238
239         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
240         QVERIFY(binding != 0);
241         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
242         QVERIFY(expression != 0);
243
244         QObject *obj = new QObject;
245
246         QCOMPARE(prop.name(), QString());
247         QCOMPARE(prop.read(), QVariant());
248         QCOMPARE(prop.write(QVariant()), false);
249         QCOMPARE(prop.hasNotifySignal(), false);
250         QCOMPARE(prop.needsNotifySignal(), false);
251         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
252         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
253         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
254         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
255         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
256         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
257         QVERIFY(prop.method().signature() == 0);
258         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
259         QCOMPARE(prop.isProperty(), false);
260         QCOMPARE(prop.isWritable(), false);
261         QCOMPARE(prop.isDesignable(), false);
262         QCOMPARE(prop.isResettable(), false);
263         QCOMPARE(prop.isSignalProperty(), false);
264         QCOMPARE(prop.isValid(), false);
265         QCOMPARE(prop.object(), (QObject *)0);
266         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
267         QCOMPARE(prop.propertyType(), 0);
268         QCOMPARE(prop.propertyTypeName(), (const char *)0);
269         QVERIFY(prop.property().name() == 0);
270         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
271         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
272         QVERIFY(binding == 0);
273         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
274         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
275         QVERIFY(expression == 0);
276         QCOMPARE(prop.index(), -1);
277         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
278
279         delete obj;
280     }
281
282     {
283         QDeclarativeProperty prop(&dobject);
284
285         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
286         binding.data()->setTarget(prop);
287         QVERIFY(binding != 0);
288         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
289         QVERIFY(expression != 0);
290
291         QObject *obj = new QObject;
292
293         QCOMPARE(prop.name(), QString("defaultProperty"));
294         QCOMPARE(prop.read(), QVariant(10));
295         QCOMPARE(prop.write(QVariant()), false);
296         QCOMPARE(prop.hasNotifySignal(), false);
297         QCOMPARE(prop.needsNotifySignal(), true);
298         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
299         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
300         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
301         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
302         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
303         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
304         QVERIFY(prop.method().signature() == 0);
305         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
306         QCOMPARE(prop.isProperty(), true);
307         QCOMPARE(prop.isWritable(), false);
308         QCOMPARE(prop.isDesignable(), true);
309         QCOMPARE(prop.isResettable(), false);
310         QCOMPARE(prop.isSignalProperty(), false);
311         QCOMPARE(prop.isValid(), true);
312         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
313         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
314         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
315         QCOMPARE(prop.propertyTypeName(), "int");
316         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
317         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
318         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
319         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
320         QVERIFY(binding != 0);
321         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
322         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
323         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
324         QVERIFY(expression == 0);
325         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
326         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
327
328         delete obj;
329     }
330 }
331
332 void tst_qdeclarativeproperty::qmlmetaproperty_object_string()
333 {
334     QObject object; 
335     PropertyObject dobject; 
336
337     {
338         QDeclarativeProperty prop(&object, QString("defaultProperty"));
339
340         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
341         QVERIFY(binding != 0);
342         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
343         QVERIFY(expression != 0);
344
345         QObject *obj = new QObject;
346
347         QCOMPARE(prop.name(), QString());
348         QCOMPARE(prop.read(), QVariant());
349         QCOMPARE(prop.write(QVariant()), false);
350         QCOMPARE(prop.hasNotifySignal(), false);
351         QCOMPARE(prop.needsNotifySignal(), false);
352         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
353         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
354         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
355         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
356         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
357         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
358         QVERIFY(prop.method().signature() == 0);
359         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
360         QCOMPARE(prop.isProperty(), false);
361         QCOMPARE(prop.isWritable(), false);
362         QCOMPARE(prop.isDesignable(), false);
363         QCOMPARE(prop.isResettable(), false);
364         QCOMPARE(prop.isSignalProperty(), false);
365         QCOMPARE(prop.isValid(), false);
366         QCOMPARE(prop.object(), (QObject *)0);
367         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
368         QCOMPARE(prop.propertyType(), 0);
369         QCOMPARE(prop.propertyTypeName(), (const char *)0);
370         QVERIFY(prop.property().name() == 0);
371         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
372         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
373         QVERIFY(binding == 0);
374         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
375         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
376         QVERIFY(expression == 0);
377         QCOMPARE(prop.index(), -1);
378         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
379
380         delete obj;
381     }
382
383     {
384         QDeclarativeProperty prop(&dobject, QString("defaultProperty"));
385
386         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
387         binding.data()->setTarget(prop);
388         QVERIFY(binding != 0);
389         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
390         QVERIFY(expression != 0);
391
392         QObject *obj = new QObject;
393
394         QCOMPARE(prop.name(), QString("defaultProperty"));
395         QCOMPARE(prop.read(), QVariant(10));
396         QCOMPARE(prop.write(QVariant()), false);
397         QCOMPARE(prop.hasNotifySignal(), false);
398         QCOMPARE(prop.needsNotifySignal(), true);
399         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
400         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
401         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
402         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
403         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
404         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
405         QVERIFY(prop.method().signature() == 0);
406         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
407         QCOMPARE(prop.isProperty(), true);
408         QCOMPARE(prop.isWritable(), false);
409         QCOMPARE(prop.isDesignable(), true);
410         QCOMPARE(prop.isResettable(), false);
411         QCOMPARE(prop.isSignalProperty(), false);
412         QCOMPARE(prop.isValid(), true);
413         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
414         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
415         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
416         QCOMPARE(prop.propertyTypeName(), "int");
417         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
418         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
419         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
420         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
421         QVERIFY(binding != 0);
422         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
423         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
424         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
425         QVERIFY(expression == 0);
426         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
427         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
428
429         delete obj;
430     }
431
432     {
433         QDeclarativeProperty prop(&dobject, QString("onClicked"));
434
435         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
436         binding.data()->setTarget(prop);
437         QVERIFY(binding != 0);
438         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
439         QVERIFY(expression != 0);
440
441         QObject *obj = new QObject;
442
443         QCOMPARE(prop.name(), QString("onClicked"));
444         QCOMPARE(prop.read(), QVariant());
445         QCOMPARE(prop.write(QVariant("Hello")), false);
446         QCOMPARE(prop.hasNotifySignal(), false);
447         QCOMPARE(prop.needsNotifySignal(), false);
448         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
449         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
450         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
451         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
452         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
453         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
454         QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
455         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
456         QCOMPARE(prop.isProperty(), false);
457         QCOMPARE(prop.isWritable(), false);
458         QCOMPARE(prop.isDesignable(), false);
459         QCOMPARE(prop.isResettable(), false);
460         QCOMPARE(prop.isSignalProperty(), true);
461         QCOMPARE(prop.isValid(), true);
462         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
463         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
464         QCOMPARE(prop.propertyType(), 0);
465         QCOMPARE(prop.propertyTypeName(), (const char *)0);
466         QCOMPARE(prop.property().name(), (const char *)0);
467         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
468         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
469         QVERIFY(binding == 0);
470         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
471         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
472         QVERIFY(expression != 0);
473         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
474         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
475         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
476
477         delete obj;
478     }
479
480     {
481         QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
482
483         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
484         binding.data()->setTarget(prop);
485         QVERIFY(binding != 0);
486         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
487         QVERIFY(expression != 0);
488
489         QObject *obj = new QObject;
490
491         QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
492         QCOMPARE(prop.read(), QVariant());
493         QCOMPARE(prop.write(QVariant("Hello")), false);
494         QCOMPARE(prop.hasNotifySignal(), false);
495         QCOMPARE(prop.needsNotifySignal(), false);
496         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
497         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
498         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
499         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
500         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
501         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
502         QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
503         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
504         QCOMPARE(prop.isProperty(), false);
505         QCOMPARE(prop.isWritable(), false);
506         QCOMPARE(prop.isDesignable(), false);
507         QCOMPARE(prop.isResettable(), false);
508         QCOMPARE(prop.isSignalProperty(), true);
509         QCOMPARE(prop.isValid(), true);
510         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
511         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
512         QCOMPARE(prop.propertyType(), 0);
513         QCOMPARE(prop.propertyTypeName(), (const char *)0);
514         QCOMPARE(prop.property().name(), (const char *)0);
515         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
516         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
517         QVERIFY(binding == 0);
518         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
519         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
520         QVERIFY(expression != 0);
521         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
522         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
523         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
524
525         delete obj;
526     }
527 }
528
529 void tst_qdeclarativeproperty::qmlmetaproperty_object_context()
530 {
531     QObject object; // Has no default property
532     PropertyObject dobject; // Has default property
533
534     {
535         QDeclarativeProperty prop(&object, engine.rootContext());
536
537         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
538         QVERIFY(binding != 0);
539         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
540         QVERIFY(expression != 0);
541
542         QObject *obj = new QObject;
543
544         QCOMPARE(prop.name(), QString());
545         QCOMPARE(prop.read(), QVariant());
546         QCOMPARE(prop.write(QVariant()), false);
547         QCOMPARE(prop.hasNotifySignal(), false);
548         QCOMPARE(prop.needsNotifySignal(), false);
549         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
550         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
551         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
552         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
553         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
554         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
555         QVERIFY(prop.method().signature() == 0);
556         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
557         QCOMPARE(prop.isProperty(), false);
558         QCOMPARE(prop.isWritable(), false);
559         QCOMPARE(prop.isDesignable(), false);
560         QCOMPARE(prop.isResettable(), false);
561         QCOMPARE(prop.isSignalProperty(), false);
562         QCOMPARE(prop.isValid(), false);
563         QCOMPARE(prop.object(), (QObject *)0);
564         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
565         QCOMPARE(prop.propertyType(), 0);
566         QCOMPARE(prop.propertyTypeName(), (const char *)0);
567         QVERIFY(prop.property().name() == 0);
568         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
569         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
570         QVERIFY(binding == 0);
571         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
572         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
573         QVERIFY(expression == 0);
574         QCOMPARE(prop.index(), -1);
575         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
576
577         delete obj;
578     }
579
580     {
581         QDeclarativeProperty prop(&dobject, engine.rootContext());
582
583         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
584         binding.data()->setTarget(prop);
585         QVERIFY(binding != 0);
586         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
587         QVERIFY(expression != 0);
588
589         QObject *obj = new QObject;
590
591         QCOMPARE(prop.name(), QString("defaultProperty"));
592         QCOMPARE(prop.read(), QVariant(10));
593         QCOMPARE(prop.write(QVariant()), false);
594         QCOMPARE(prop.hasNotifySignal(), false);
595         QCOMPARE(prop.needsNotifySignal(), true);
596         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
597         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
598         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
599         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
600         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
601         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
602         QVERIFY(prop.method().signature() == 0);
603         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
604         QCOMPARE(prop.isProperty(), true);
605         QCOMPARE(prop.isWritable(), false);
606         QCOMPARE(prop.isDesignable(), true);
607         QCOMPARE(prop.isResettable(), false);
608         QCOMPARE(prop.isSignalProperty(), false);
609         QCOMPARE(prop.isValid(), true);
610         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
611         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
612         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
613         QCOMPARE(prop.propertyTypeName(), "int");
614         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
615         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
616         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
617         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
618         QVERIFY(binding != 0);
619         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
620         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
621         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
622         QVERIFY(expression == 0);
623         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
624         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
625
626         delete obj;
627     }
628 }
629
630 void tst_qdeclarativeproperty::qmlmetaproperty_object_string_context()
631 {
632     QObject object; 
633     PropertyObject dobject; 
634
635     {
636         QDeclarativeProperty prop(&object, QString("defaultProperty"), engine.rootContext());
637
638         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
639         QVERIFY(binding != 0);
640         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
641         QVERIFY(expression != 0);
642
643         QObject *obj = new QObject;
644
645         QCOMPARE(prop.name(), QString());
646         QCOMPARE(prop.read(), QVariant());
647         QCOMPARE(prop.write(QVariant()), false);
648         QCOMPARE(prop.hasNotifySignal(), false);
649         QCOMPARE(prop.needsNotifySignal(), false);
650         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
651         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
652         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
653         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
654         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
655         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
656         QVERIFY(prop.method().signature() == 0);
657         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
658         QCOMPARE(prop.isProperty(), false);
659         QCOMPARE(prop.isWritable(), false);
660         QCOMPARE(prop.isDesignable(), false);
661         QCOMPARE(prop.isResettable(), false);
662         QCOMPARE(prop.isSignalProperty(), false);
663         QCOMPARE(prop.isValid(), false);
664         QCOMPARE(prop.object(), (QObject *)0);
665         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
666         QCOMPARE(prop.propertyType(), 0);
667         QCOMPARE(prop.propertyTypeName(), (const char *)0);
668         QVERIFY(prop.property().name() == 0);
669         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
670         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
671         QVERIFY(binding == 0);
672         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
673         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
674         QVERIFY(expression == 0);
675         QCOMPARE(prop.index(), -1);
676         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
677
678         delete obj;
679     }
680
681     {
682         QDeclarativeProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
683
684         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
685         binding.data()->setTarget(prop);
686         QVERIFY(binding != 0);
687         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
688         QVERIFY(expression != 0);
689
690         QObject *obj = new QObject;
691
692         QCOMPARE(prop.name(), QString("defaultProperty"));
693         QCOMPARE(prop.read(), QVariant(10));
694         QCOMPARE(prop.write(QVariant()), false);
695         QCOMPARE(prop.hasNotifySignal(), false);
696         QCOMPARE(prop.needsNotifySignal(), true);
697         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
698         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
699         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
700         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
701         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
702         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
703         QVERIFY(prop.method().signature() == 0);
704         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
705         QCOMPARE(prop.isProperty(), true);
706         QCOMPARE(prop.isWritable(), false);
707         QCOMPARE(prop.isDesignable(), true);
708         QCOMPARE(prop.isResettable(), false);
709         QCOMPARE(prop.isSignalProperty(), false);
710         QCOMPARE(prop.isValid(), true);
711         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
712         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
713         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
714         QCOMPARE(prop.propertyTypeName(), "int");
715         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
716         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
717         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
718         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
719         QVERIFY(binding != 0);
720         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
721         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
722         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
723         QVERIFY(expression == 0);
724         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
725         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
726
727         delete obj;
728     }
729
730     {
731         QDeclarativeProperty prop(&dobject, QString("onClicked"), engine.rootContext());
732
733         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
734         binding.data()->setTarget(prop);
735         QVERIFY(binding != 0);
736         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
737         QVERIFY(expression != 0);
738
739         QObject *obj = new QObject;
740
741         QCOMPARE(prop.name(), QString("onClicked"));
742         QCOMPARE(prop.read(), QVariant());
743         QCOMPARE(prop.write(QVariant("Hello")), false);
744         QCOMPARE(prop.hasNotifySignal(), false);
745         QCOMPARE(prop.needsNotifySignal(), false);
746         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
747         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
748         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
749         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
750         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
751         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
752         QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
753         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
754         QCOMPARE(prop.isProperty(), false);
755         QCOMPARE(prop.isWritable(), false);
756         QCOMPARE(prop.isDesignable(), false);
757         QCOMPARE(prop.isResettable(), false);
758         QCOMPARE(prop.isSignalProperty(), true);
759         QCOMPARE(prop.isValid(), true);
760         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
761         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
762         QCOMPARE(prop.propertyType(), 0);
763         QCOMPARE(prop.propertyTypeName(), (const char *)0);
764         QCOMPARE(prop.property().name(), (const char *)0);
765         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
766         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
767         QVERIFY(binding == 0);
768         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
769         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
770         QVERIFY(expression != 0);
771         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
772         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
773         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
774
775         delete obj;
776     }
777
778     {
779         QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
780
781         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
782         binding.data()->setTarget(prop);
783         QVERIFY(binding != 0);
784         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
785         QVERIFY(expression != 0);
786
787         QObject *obj = new QObject;
788
789         QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
790         QCOMPARE(prop.read(), QVariant());
791         QCOMPARE(prop.write(QVariant("Hello")), false);
792         QCOMPARE(prop.hasNotifySignal(), false);
793         QCOMPARE(prop.needsNotifySignal(), false);
794         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
795         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
796         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
797         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
798         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
799         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
800         QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
801         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
802         QCOMPARE(prop.isProperty(), false);
803         QCOMPARE(prop.isWritable(), false);
804         QCOMPARE(prop.isDesignable(), false);
805         QCOMPARE(prop.isResettable(), false);
806         QCOMPARE(prop.isSignalProperty(), true);
807         QCOMPARE(prop.isValid(), true);
808         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
809         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
810         QCOMPARE(prop.propertyType(), 0);
811         QCOMPARE(prop.propertyTypeName(), (const char *)0);
812         QCOMPARE(prop.property().name(), (const char *)0);
813         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
814         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
815         QVERIFY(binding == 0);
816         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
817         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
818         QVERIFY(expression != 0);
819         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
820         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
821         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
822
823         delete obj;
824     }
825 }
826
827 void tst_qdeclarativeproperty::name()
828 {
829     { 
830         QDeclarativeProperty p;
831         QCOMPARE(p.name(), QString());
832     }
833
834     {
835         PropertyObject o;
836         QDeclarativeProperty p(&o);
837         QCOMPARE(p.name(), QString("defaultProperty"));
838     }
839
840     {
841         QObject o;
842         QDeclarativeProperty p(&o, QString("objectName"));
843         QCOMPARE(p.name(), QString("objectName"));
844     }
845
846     {
847         PropertyObject o;
848         QDeclarativeProperty p(&o, "onClicked");
849         QCOMPARE(p.name(), QString("onClicked"));
850     }
851
852     {
853         QObject o;
854         QDeclarativeProperty p(&o, "onClicked");
855         QCOMPARE(p.name(), QString());
856     }
857
858     {
859         PropertyObject o;
860         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
861         QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
862     }
863
864     {
865         QObject o;
866         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
867         QCOMPARE(p.name(), QString());
868     }
869
870     {
871         QObject o;
872         QDeclarativeProperty p(&o, "foo");
873         QCOMPARE(p.name(), QString());
874     }
875
876     {
877         QDeclarativeProperty p(0, "foo");
878         QCOMPARE(p.name(), QString());
879     }
880
881     {
882         PropertyObject o;
883         QDeclarativeProperty p(&o, "rectProperty");
884         QCOMPARE(p.name(), QString("rectProperty"));
885     }
886
887     {
888         PropertyObject o;
889         QDeclarativeProperty p(&o, "rectProperty.x");
890         QCOMPARE(p.name(), QString("rectProperty.x"));
891     }
892
893     {
894         PropertyObject o;
895         QDeclarativeProperty p(&o, "rectProperty.foo");
896         QCOMPARE(p.name(), QString());
897     }
898 }
899
900 void tst_qdeclarativeproperty::read()
901 {
902     // Invalid 
903     {
904         QDeclarativeProperty p;
905         QCOMPARE(p.read(), QVariant());
906     }
907
908     // Default prop
909     {
910         PropertyObject o;
911         QDeclarativeProperty p(&o);
912         QCOMPARE(p.read(), QVariant(10));
913     }
914
915     // Invalid default prop
916     {
917         QObject o;
918         QDeclarativeProperty p(&o);
919         QCOMPARE(p.read(), QVariant());
920     }
921
922     // Value prop by name
923     {
924         QObject o;
925
926         QDeclarativeProperty p(&o, "objectName");
927         QCOMPARE(p.read(), QVariant(QString()));
928
929         o.setObjectName("myName");
930
931         QCOMPARE(p.read(), QVariant("myName"));
932     }
933
934     // Value prop by name (static)
935     {
936         QObject o;
937
938         QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant(QString()));
939
940         o.setObjectName("myName");
941
942         QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant("myName"));
943     }
944
945     // Value-type prop
946     {
947         PropertyObject o;
948         QDeclarativeProperty p(&o, "rectProperty.x");
949         QCOMPARE(p.read(), QVariant(10));
950     }
951
952     // Invalid value-type prop
953     {
954         PropertyObject o;
955         QDeclarativeProperty p(&o, "rectProperty.foo");
956         QCOMPARE(p.read(), QVariant());
957     }
958
959     // Signal property
960     {
961         PropertyObject o;
962         QDeclarativeProperty p(&o, "onClicked");
963         QCOMPARE(p.read(), QVariant());
964
965         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
966         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
967
968         QCOMPARE(p.read(), QVariant());
969     }
970
971     // Automatic signal property 
972     {
973         PropertyObject o;
974         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
975         QCOMPARE(p.read(), QVariant());
976
977         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
978         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
979
980         QCOMPARE(p.read(), QVariant());
981     }
982
983     // Deleted object
984     {
985         PropertyObject *o = new PropertyObject;
986         QDeclarativeProperty p(o, "rectProperty.x");
987         QCOMPARE(p.read(), QVariant(10));
988         delete o;
989         QCOMPARE(p.read(), QVariant());
990     }
991
992     // Object property
993     {
994         PropertyObject o;
995         QDeclarativeProperty p(&o, "qmlObject");
996         QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
997         QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
998         QVariant v = p.read();
999         QVERIFY(v.userType() == QMetaType::QObjectStar);
1000         QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1001     }
1002     {
1003         QDeclarativeComponent component(&engine, TEST_FILE("readSynthesizedObject.qml"));
1004         QObject *object = component.create();
1005         QVERIFY(object != 0);
1006
1007         QDeclarativeProperty p(object, "test", &engine);
1008
1009         QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1010         QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1011
1012         QVariant v = p.read();
1013         QVERIFY(v.userType() == QMetaType::QObjectStar);
1014         QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1015         QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1016     }
1017     {   // static
1018         QDeclarativeComponent component(&engine, TEST_FILE("readSynthesizedObject.qml"));
1019         QObject *object = component.create();
1020         QVERIFY(object != 0);
1021
1022         QVariant v = QDeclarativeProperty::read(object, "test", &engine);
1023         QVERIFY(v.userType() == QMetaType::QObjectStar);
1024         QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1025         QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1026     }
1027
1028     // Attached property
1029     {
1030         QDeclarativeComponent component(&engine);
1031         component.setData("import Test 1.0\nMyContainer { }", QUrl());
1032         QObject *object = component.create();
1033         QVERIFY(object != 0);
1034
1035         QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1036         QCOMPARE(p.read(), QVariant(13));
1037         delete object;
1038     }
1039     {
1040         QDeclarativeComponent component(&engine);
1041         component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1042         QObject *object = component.create();
1043         QVERIFY(object != 0);
1044
1045         QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1046         QCOMPARE(p.read(), QVariant(10));
1047         delete object;
1048     }
1049     {
1050         QDeclarativeComponent component(&engine);
1051         component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1052         QObject *object = component.create();
1053         QVERIFY(object != 0);
1054
1055         QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1056         QCOMPARE(p.read(), QVariant(10));
1057         delete object;
1058     }
1059     {   // static
1060         QDeclarativeComponent component(&engine);
1061         component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1062         QObject *object = component.create();
1063         QVERIFY(object != 0);
1064
1065         QCOMPARE(QDeclarativeProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1066         delete object;
1067     }
1068 }
1069
1070 void tst_qdeclarativeproperty::write()
1071 {
1072     // Invalid
1073     {
1074         QDeclarativeProperty p;
1075         QCOMPARE(p.write(QVariant(10)), false);
1076     }
1077
1078     // Read-only default prop
1079     {
1080         PropertyObject o;
1081         QDeclarativeProperty p(&o);
1082         QCOMPARE(p.write(QVariant(10)), false);
1083     }
1084
1085     // Invalid default prop
1086     {
1087         QObject o;
1088         QDeclarativeProperty p(&o);
1089         QCOMPARE(p.write(QVariant(10)), false);
1090     }
1091
1092     // Read-only prop by name
1093     {
1094         PropertyObject o;
1095         QDeclarativeProperty p(&o, QString("defaultProperty"));
1096         QCOMPARE(p.write(QVariant(10)), false);
1097     }
1098
1099     // Writable prop by name
1100     {
1101         PropertyObject o;
1102         QDeclarativeProperty p(&o, QString("objectName"));
1103         QCOMPARE(o.objectName(), QString());
1104         QCOMPARE(p.write(QVariant(QString("myName"))), true);
1105         QCOMPARE(o.objectName(), QString("myName"));
1106     }
1107
1108     // Writable prop by name (static)
1109     {
1110         PropertyObject o;
1111         QCOMPARE(QDeclarativeProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1112         QCOMPARE(o.objectName(), QString("myName"));
1113     }
1114
1115     // Deleted object
1116     {
1117         PropertyObject *o = new PropertyObject;
1118         QDeclarativeProperty p(o, QString("objectName"));
1119         QCOMPARE(p.write(QVariant(QString("myName"))), true);
1120         QCOMPARE(o->objectName(), QString("myName"));
1121
1122         delete o;
1123
1124         QCOMPARE(p.write(QVariant(QString("myName"))), false);
1125     }
1126
1127     // Signal property
1128     {
1129         PropertyObject o;
1130         QDeclarativeProperty p(&o, "onClicked");
1131         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1132
1133         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1134         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1135
1136         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1137
1138         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1139     }
1140
1141     // Automatic signal property
1142     {
1143         PropertyObject o;
1144         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1145         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1146
1147         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1148         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1149
1150         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1151
1152         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1153     }
1154
1155     // Value-type property
1156     {
1157         PropertyObject o;
1158         QDeclarativeProperty p(&o, "wrectProperty");
1159
1160         QCOMPARE(o.wrectProperty(), QRect());
1161         QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1162         QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1163
1164         QDeclarativeProperty p2(&o, "wrectProperty.x");
1165         QCOMPARE(p2.read(), QVariant(1));
1166         QCOMPARE(p2.write(QVariant(6)), true);
1167         QCOMPARE(p2.read(), QVariant(6));
1168         QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1169     }
1170
1171     // URL-property
1172     {
1173         PropertyObject o;
1174         QDeclarativeProperty p(&o, "url");
1175
1176         QCOMPARE(p.write(QUrl("main.qml")), true);
1177         QCOMPARE(o.url(), QUrl("main.qml"));
1178
1179         QDeclarativeProperty p2(&o, "url", engine.rootContext());
1180
1181         QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1182         QVERIFY(result != QUrl("main.qml"));
1183
1184         QCOMPARE(p2.write(QUrl("main.qml")), true);
1185         QCOMPARE(o.url(), result);
1186     }
1187     {   // static
1188         PropertyObject o;
1189
1190         QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml")), true);
1191         QCOMPARE(o.url(), QUrl("main.qml"));
1192
1193         QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1194         QVERIFY(result != QUrl("main.qml"));
1195
1196         QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1197         QCOMPARE(o.url(), result);
1198     }
1199
1200     // Attached property
1201     {
1202         QDeclarativeComponent component(&engine);
1203         component.setData("import Test 1.0\nMyContainer { }", QUrl());
1204         QObject *object = component.create();
1205         QVERIFY(object != 0);
1206
1207         QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1208         p.write(QVariant(99));
1209         QCOMPARE(p.read(), QVariant(99));
1210         delete object;
1211     }
1212     {
1213         QDeclarativeComponent component(&engine);
1214         component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1215         QObject *object = component.create();
1216         QVERIFY(object != 0);
1217
1218         QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1219         p.write(QVariant(99));
1220         QCOMPARE(p.read(), QVariant(99));
1221         delete object;
1222     }
1223 }
1224
1225 void tst_qdeclarativeproperty::reset()
1226 {
1227     // Invalid
1228     {
1229         QDeclarativeProperty p;
1230         QCOMPARE(p.isResettable(), false);
1231         QCOMPARE(p.reset(), false);
1232     }
1233
1234     // Read-only default prop
1235     {
1236         PropertyObject o;
1237         QDeclarativeProperty p(&o);
1238         QCOMPARE(p.isResettable(), false);
1239         QCOMPARE(p.reset(), false);
1240     }
1241
1242     // Invalid default prop
1243     {
1244         QObject o;
1245         QDeclarativeProperty p(&o);
1246         QCOMPARE(p.isResettable(), false);
1247         QCOMPARE(p.reset(), false);
1248     }
1249
1250     // Non-resettable-only prop by name
1251     {
1252         PropertyObject o;
1253         QDeclarativeProperty p(&o, QString("defaultProperty"));
1254         QCOMPARE(p.isResettable(), false);
1255         QCOMPARE(p.reset(), false);
1256     }
1257
1258     // Resettable prop by name
1259     {
1260         PropertyObject o;
1261         QDeclarativeProperty p(&o, QString("resettableProperty"));
1262
1263         QCOMPARE(p.read(), QVariant(9));
1264         QCOMPARE(p.write(QVariant(11)), true);
1265         QCOMPARE(p.read(), QVariant(11));
1266
1267         QCOMPARE(p.isResettable(), true);
1268         QCOMPARE(p.reset(), true);
1269
1270         QCOMPARE(p.read(), QVariant(9));
1271     }
1272
1273     // Deleted object
1274     {
1275         PropertyObject *o = new PropertyObject;
1276
1277         QDeclarativeProperty p(o, QString("resettableProperty"));
1278
1279         QCOMPARE(p.isResettable(), true);
1280         QCOMPARE(p.reset(), true);
1281
1282         delete o;
1283
1284         QCOMPARE(p.isResettable(), false);
1285         QCOMPARE(p.reset(), false);
1286     }
1287
1288     // Signal property
1289     {
1290         PropertyObject o;
1291         QDeclarativeProperty p(&o, "onClicked");
1292
1293         QCOMPARE(p.isResettable(), false);
1294         QCOMPARE(p.reset(), false);
1295     }
1296
1297     // Automatic signal property
1298     {
1299         PropertyObject o;
1300         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1301
1302         QCOMPARE(p.isResettable(), false);
1303         QCOMPARE(p.reset(), false);
1304     }
1305 }
1306
1307 void tst_qdeclarativeproperty::writeObjectToList()
1308 {
1309     QDeclarativeComponent containerComponent(&engine);
1310     containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1311     MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1312     QVERIFY(container != 0);
1313     QDeclarativeListReference list(container, "children");
1314     QVERIFY(list.count() == 1);
1315
1316     MyQmlObject *object = new MyQmlObject;
1317     QDeclarativeProperty prop(container, "children");
1318     prop.write(qVariantFromValue(object));
1319     QCOMPARE(list.count(), 1);
1320     QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1321 }
1322
1323 Q_DECLARE_METATYPE(QList<QObject *>);
1324 void tst_qdeclarativeproperty::writeListToList()
1325 {
1326     QDeclarativeComponent containerComponent(&engine);
1327     containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1328     MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1329     QVERIFY(container != 0);
1330     QDeclarativeListReference list(container, "children");
1331     QVERIFY(list.count() == 1);
1332
1333     QList<QObject*> objList;
1334     objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1335     QDeclarativeProperty prop(container, "children");
1336     prop.write(qVariantFromValue(objList));
1337     QCOMPARE(list.count(), 4);
1338
1339     //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1340     /*QList<MyQmlObject*> typedObjList;
1341     typedObjList << new MyQmlObject();
1342     prop.write(qVariantFromValue(&typedObjList));
1343     QCOMPARE(container->children()->size(), 1);*/
1344 }
1345
1346 void tst_qdeclarativeproperty::crashOnValueProperty()
1347 {
1348     QDeclarativeEngine *engine = new QDeclarativeEngine;
1349     QDeclarativeComponent component(engine);
1350
1351     component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1352     PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1353     QVERIFY(obj != 0);
1354
1355     QDeclarativeProperty p(obj, "wrectProperty.x", qmlContext(obj));
1356     QCOMPARE(p.name(), QString("wrectProperty.x"));
1357
1358     QCOMPARE(p.read(), QVariant(10));
1359
1360     //don't crash once the engine is deleted
1361     delete engine;
1362     engine = 0;
1363
1364     QCOMPARE(p.propertyTypeName(), "int");
1365     QCOMPARE(p.read(), QVariant(10));
1366     p.write(QVariant(20));
1367     QCOMPARE(p.read(), QVariant(20));
1368 }
1369
1370 // QTBUG-13719
1371 void tst_qdeclarativeproperty::aliasPropertyBindings()
1372 {
1373     QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyBindings.qml"));
1374
1375     QObject *object = component.create();
1376     QVERIFY(object != 0);
1377
1378     QCOMPARE(object->property("realProperty").toReal(), 90.);
1379     QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1380
1381     object->setProperty("test", 10);
1382
1383     QCOMPARE(object->property("realProperty").toReal(), 110.);
1384     QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1385
1386     QDeclarativeProperty realProperty(object, QLatin1String("realProperty"));
1387     QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty"));
1388
1389     // Check there is a binding on these two properties
1390     QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1391     QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1392
1393     // Check that its the same binding on these two properties
1394     QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1395              QDeclarativePropertyPrivate::binding(aliasProperty));
1396
1397     // Change the binding
1398     object->setProperty("state", QString("switch"));
1399
1400     QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1401     QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1402     QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1403              QDeclarativePropertyPrivate::binding(aliasProperty));
1404
1405     QCOMPARE(object->property("realProperty").toReal(), 96.);
1406     QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1407
1408     // Check the old binding really has not effect any more
1409     object->setProperty("test", 4);
1410
1411     QCOMPARE(object->property("realProperty").toReal(), 96.);
1412     QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1413
1414     object->setProperty("test2", 9);
1415
1416     QCOMPARE(object->property("realProperty").toReal(), 288.);
1417     QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1418
1419     // Revert
1420     object->setProperty("state", QString(""));
1421
1422     QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1423     QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1424     QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1425              QDeclarativePropertyPrivate::binding(aliasProperty));
1426
1427     QCOMPARE(object->property("realProperty").toReal(), 20.);
1428     QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1429
1430     object->setProperty("test2", 3);
1431
1432     QCOMPARE(object->property("realProperty").toReal(), 20.);
1433     QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1434
1435     delete object;
1436 }
1437
1438 void tst_qdeclarativeproperty::copy()
1439 {
1440     PropertyObject object;
1441
1442     QDeclarativeProperty *property = new QDeclarativeProperty(&object, QLatin1String("defaultProperty"));
1443     QCOMPARE(property->name(), QString("defaultProperty"));
1444     QCOMPARE(property->read(), QVariant(10));
1445     QCOMPARE(property->type(), QDeclarativeProperty::Property);
1446     QCOMPARE(property->propertyTypeCategory(), QDeclarativeProperty::Normal);
1447     QCOMPARE(property->propertyType(), (int)QVariant::Int);
1448
1449     QDeclarativeProperty p1(*property);
1450     QCOMPARE(p1.name(), QString("defaultProperty"));
1451     QCOMPARE(p1.read(), QVariant(10));
1452     QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1453     QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1454     QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1455
1456     QDeclarativeProperty p2(&object, QLatin1String("url"));
1457     QCOMPARE(p2.name(), QString("url"));
1458     p2 = *property;
1459     QCOMPARE(p2.name(), QString("defaultProperty"));
1460     QCOMPARE(p2.read(), QVariant(10));
1461     QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1462     QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1463     QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1464
1465     delete property; property = 0;
1466
1467     QCOMPARE(p1.name(), QString("defaultProperty"));
1468     QCOMPARE(p1.read(), QVariant(10));
1469     QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1470     QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1471     QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1472
1473     QCOMPARE(p2.name(), QString("defaultProperty"));
1474     QCOMPARE(p2.read(), QVariant(10));
1475     QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1476     QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1477     QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1478 }
1479
1480 void tst_qdeclarativeproperty::noContext()
1481 {
1482     QDeclarativeComponent compA(&engine, TEST_FILE("NoContextTypeA.qml"));
1483     QDeclarativeComponent compB(&engine, TEST_FILE("NoContextTypeB.qml"));
1484
1485     QObject *a = compA.create();
1486     QVERIFY(a != 0);
1487     QObject *b = compB.create();
1488     QVERIFY(b != 0);
1489
1490     QVERIFY(QDeclarativeProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1491
1492     delete a;
1493     delete b;
1494 }
1495
1496 void tst_qdeclarativeproperty::initTestCase()
1497 {
1498     qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1499     qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1500     qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1501 }
1502
1503 QTEST_MAIN(tst_qdeclarativeproperty)
1504
1505 #include "tst_qdeclarativeproperty.moc"