Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick2 / qdeclarativestates / tst_qdeclarativestates.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
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 <QtQuick/qquickview.h>
45 #include <private/qquickstateoperations_p.h>
46 #include <private/qquickanchors_p_p.h>
47 #include <QtQuick/private/qquickrectangle_p.h>
48 #include <private/qquickimage_p.h>
49 #include <QtQuick/private/qdeclarativepropertychanges_p.h>
50 #include <QtQuick/private/qdeclarativestategroup_p.h>
51 #include <private/qquickitem_p.h>
52 #include <private/qdeclarativeproperty_p.h>
53 #include "../../shared/util.h"
54
55 class MyAttached : public QObject
56 {
57     Q_OBJECT
58     Q_PROPERTY(int foo READ foo WRITE setFoo)
59 public:
60     MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
61
62     int foo() const { return m_foo; }
63     void setFoo(int f) { m_foo = f; }
64
65 private:
66     int m_foo;
67 };
68
69 class MyRect : public QQuickRectangle
70 {
71    Q_OBJECT
72    Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
73 public:
74     MyRect() {}
75
76     void doSomething() { emit didSomething(); }
77
78     int propertyWithNotify() const { return m_prop; }
79     void setPropertyWithNotify(int i) { m_prop = i; emit oddlyNamedNotifySignal(); }
80
81     static MyAttached *qmlAttachedProperties(QObject *o) {
82         return new MyAttached(o);
83     }
84 Q_SIGNALS:
85     void didSomething();
86     void oddlyNamedNotifySignal();
87
88 private:
89     int m_prop;
90 };
91
92 QML_DECLARE_TYPE(MyRect)
93 QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
94
95 class tst_qdeclarativestates : public QDeclarativeDataTest
96 {
97     Q_OBJECT
98 public:
99     tst_qdeclarativestates() {}
100
101 private:
102     QByteArray fullDataPath(const QString &path) const;
103
104 private slots:
105     void initTestCase();
106
107     void basicChanges();
108     void attachedPropertyChanges();
109     void basicExtension();
110     void basicBinding();
111     void signalOverride();
112     void signalOverrideCrash();
113     void signalOverrideCrash2();
114     void signalOverrideCrash3();
115     void parentChange();
116     void parentChangeErrors();
117     void anchorChanges();
118     void anchorChanges2();
119     void anchorChanges3();
120     void anchorChanges4();
121     void anchorChanges5();
122     void anchorChangesRTL();
123     void anchorChangesRTL2();
124     void anchorChangesRTL3();
125     void anchorChangesCrash();
126     void anchorRewindBug();
127     void anchorRewindBug2();
128     void script();
129     void restoreEntryValues();
130     void explicitChanges();
131     void propertyErrors();
132     void incorrectRestoreBug();
133     void autoStateAtStartupRestoreBug();
134     void deletingChange();
135     void deletingState();
136     void tempState();
137     void illegalTempState();
138     void nonExistantProperty();
139     void reset();
140     void illegalObjectCreation();
141     void whenOrdering();
142     void urlResolution();
143     void unnamedWhen();
144     void returnToBase();
145     void extendsBug();
146     void editProperties();
147     void QTBUG_14830();
148     void avoidFastForward();
149     void revertListBug();
150 };
151
152 void tst_qdeclarativestates::initTestCase()
153 {
154     QDeclarativeDataTest::initTestCase();
155     qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
156 }
157
158 QByteArray tst_qdeclarativestates::fullDataPath(const QString &path) const
159 {
160     return testFileUrl(path).toString().toUtf8();
161 }
162
163 void tst_qdeclarativestates::basicChanges()
164 {
165     QDeclarativeEngine engine;
166
167     {
168         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
169         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
170         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
171         QVERIFY(rect != 0);
172
173         QCOMPARE(rect->color(),QColor("red"));
174
175         rectPrivate->setState("blue");
176         QCOMPARE(rect->color(),QColor("blue"));
177
178         rectPrivate->setState("");
179         QCOMPARE(rect->color(),QColor("red"));
180     }
181
182     {
183         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicChanges2.qml"));
184         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
185         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
186         QVERIFY(rect != 0);
187
188         QCOMPARE(rect->color(),QColor("red"));
189
190         rectPrivate->setState("blue");
191         QCOMPARE(rect->color(),QColor("blue"));
192
193         rectPrivate->setState("green");
194         QCOMPARE(rect->color(),QColor("green"));
195
196         rectPrivate->setState("");
197         QCOMPARE(rect->color(),QColor("red"));
198
199         rectPrivate->setState("green");
200         QCOMPARE(rect->color(),QColor("green"));
201     }
202
203     {
204         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicChanges3.qml"));
205         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
206         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
207         QVERIFY(rect != 0);
208
209         QCOMPARE(rect->color(),QColor("red"));
210         QCOMPARE(rect->border()->width(),1.0);
211
212         rectPrivate->setState("blue");
213         QCOMPARE(rect->color(),QColor("blue"));
214         QCOMPARE(rect->border()->width(),1.0);
215
216         rectPrivate->setState("bordered");
217         QCOMPARE(rect->color(),QColor("red"));
218         QCOMPARE(rect->border()->width(),2.0);
219
220         rectPrivate->setState("");
221         QCOMPARE(rect->color(),QColor("red"));
222         QCOMPARE(rect->border()->width(),1.0);
223         //### we should be checking that this is an implicit rather than explicit 1 (which currently fails)
224
225         rectPrivate->setState("bordered");
226         QCOMPARE(rect->color(),QColor("red"));
227         QCOMPARE(rect->border()->width(),2.0);
228
229         rectPrivate->setState("blue");
230         QCOMPARE(rect->color(),QColor("blue"));
231         QCOMPARE(rect->border()->width(),1.0);
232
233     }
234
235     {
236         // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
237         // signal using 'onPropertyWithNotifyChanged' even though the signal name is
238         // actually 'oddlyNamedNotifySignal'
239
240         QDeclarativeComponent component(&engine, testFileUrl("basicChanges4.qml"));
241         QVERIFY(component.isReady());
242
243         MyRect *rect = qobject_cast<MyRect*>(component.create());
244         QVERIFY(rect != 0);
245
246         QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
247         QVERIFY(prop.hasNotifySignal());
248         QString notifySignal = QByteArray(prop.notifySignal().signature());
249         QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
250
251         QCOMPARE(rect->color(), QColor(Qt::red));
252
253         rect->setPropertyWithNotify(100);
254         QCOMPARE(rect->color(), QColor(Qt::blue));
255     }
256 }
257
258 void tst_qdeclarativestates::attachedPropertyChanges()
259 {
260     QDeclarativeEngine engine;
261
262     QDeclarativeComponent component(&engine, testFileUrl("attachedPropertyChanges.qml"));
263     QVERIFY(component.isReady());
264
265     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
266     QVERIFY(item != 0);
267     QCOMPARE(item->width(), 50.0);
268
269     // Ensure attached property has been changed
270     QObject *attObj = qmlAttachedPropertiesObject<MyRect>(item, false);
271     QVERIFY(attObj);
272
273     MyAttached *att = qobject_cast<MyAttached*>(attObj);
274     QVERIFY(att);
275
276     QCOMPARE(att->foo(), 1);
277 }
278
279 void tst_qdeclarativestates::basicExtension()
280 {
281     QDeclarativeEngine engine;
282
283     {
284         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicExtension.qml"));
285         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
286         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
287         QVERIFY(rect != 0);
288
289         QCOMPARE(rect->color(),QColor("red"));
290         QCOMPARE(rect->border()->width(),1.0);
291
292         rectPrivate->setState("blue");
293         QCOMPARE(rect->color(),QColor("blue"));
294         QCOMPARE(rect->border()->width(),1.0);
295
296         rectPrivate->setState("bordered");
297         QCOMPARE(rect->color(),QColor("blue"));
298         QCOMPARE(rect->border()->width(),2.0);
299
300         rectPrivate->setState("blue");
301         QCOMPARE(rect->color(),QColor("blue"));
302         QCOMPARE(rect->border()->width(),1.0);
303
304         rectPrivate->setState("");
305         QCOMPARE(rect->color(),QColor("red"));
306         QCOMPARE(rect->border()->width(),1.0);
307
308         rectPrivate->setState("bordered");
309         QCOMPARE(rect->color(),QColor("blue"));
310         QCOMPARE(rect->border()->width(),2.0);
311
312         rectPrivate->setState("");
313         QCOMPARE(rect->color(),QColor("red"));
314         QCOMPARE(rect->border()->width(),1.0);
315     }
316
317     {
318         QDeclarativeComponent rectComponent(&engine, testFileUrl("fakeExtension.qml"));
319         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
320         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
321         QVERIFY(rect != 0);
322
323         QCOMPARE(rect->color(),QColor("red"));
324
325         rectPrivate->setState("blue");
326         QCOMPARE(rect->color(),QColor("blue"));
327
328         rectPrivate->setState("green");
329         QCOMPARE(rect->color(),QColor("green"));
330
331         rectPrivate->setState("blue");
332         QCOMPARE(rect->color(),QColor("blue"));
333
334         rectPrivate->setState("green");
335         QCOMPARE(rect->color(),QColor("green"));
336
337         rectPrivate->setState("");
338         QCOMPARE(rect->color(),QColor("red"));
339
340         rectPrivate->setState("green");
341         QCOMPARE(rect->color(),QColor("green"));
342     }
343 }
344
345 void tst_qdeclarativestates::basicBinding()
346 {
347     QDeclarativeEngine engine;
348
349     {
350         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicBinding.qml"));
351         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
352         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
353         QVERIFY(rect != 0);
354
355         QCOMPARE(rect->color(),QColor("red"));
356
357         rectPrivate->setState("blue");
358         QCOMPARE(rect->color(),QColor("blue"));
359
360         rectPrivate->setState("");
361         QCOMPARE(rect->color(),QColor("red"));
362
363         rectPrivate->setState("blue");
364         QCOMPARE(rect->color(),QColor("blue"));
365         rect->setProperty("sourceColor", QColor("green"));
366         QCOMPARE(rect->color(),QColor("green"));
367
368         rectPrivate->setState("");
369         QCOMPARE(rect->color(),QColor("red"));
370         rect->setProperty("sourceColor", QColor("yellow"));
371         QCOMPARE(rect->color(),QColor("red"));
372
373         rectPrivate->setState("blue");
374         QCOMPARE(rect->color(),QColor("yellow"));
375     }
376
377     {
378         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicBinding2.qml"));
379         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
380         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
381         QVERIFY(rect != 0);
382
383         QCOMPARE(rect->color(),QColor("red"));
384
385         rectPrivate->setState("blue");
386         QCOMPARE(rect->color(),QColor("blue"));
387
388         rectPrivate->setState("");
389         QCOMPARE(rect->color(),QColor("red"));
390
391         rectPrivate->setState("blue");
392         QCOMPARE(rect->color(),QColor("blue"));
393         rect->setProperty("sourceColor", QColor("green"));
394         QCOMPARE(rect->color(),QColor("blue"));
395
396         rectPrivate->setState("");
397         QCOMPARE(rect->color(),QColor("green"));
398         rect->setProperty("sourceColor", QColor("yellow"));
399         QCOMPARE(rect->color(),QColor("yellow"));
400
401         rectPrivate->setState("blue");
402         QCOMPARE(rect->color(),QColor("blue"));
403
404         rectPrivate->setState("");
405         QCOMPARE(rect->color(),QColor("yellow"));
406     }
407
408     {
409         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicBinding3.qml"));
410         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
411         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
412         QVERIFY(rect != 0);
413
414         QCOMPARE(rect->color(),QColor("red"));
415         rect->setProperty("sourceColor", QColor("green"));
416         QCOMPARE(rect->color(),QColor("green"));
417
418         rectPrivate->setState("blue");
419         QCOMPARE(rect->color(),QColor("blue"));
420         rect->setProperty("sourceColor", QColor("red"));
421         QCOMPARE(rect->color(),QColor("blue"));
422         rect->setProperty("sourceColor2", QColor("yellow"));
423         QCOMPARE(rect->color(),QColor("yellow"));
424
425         rectPrivate->setState("");
426         QCOMPARE(rect->color(),QColor("red"));
427         rect->setProperty("sourceColor2", QColor("green"));
428         QCOMPARE(rect->color(),QColor("red"));
429         rect->setProperty("sourceColor", QColor("yellow"));
430         QCOMPARE(rect->color(),QColor("yellow"));
431     }
432
433     {
434         QDeclarativeComponent rectComponent(&engine, testFileUrl("basicBinding4.qml"));
435         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
436         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
437         QVERIFY(rect != 0);
438
439         QCOMPARE(rect->color(),QColor("red"));
440
441         rectPrivate->setState("blue");
442         QCOMPARE(rect->color(),QColor("blue"));
443         rect->setProperty("sourceColor", QColor("yellow"));
444         QCOMPARE(rect->color(),QColor("yellow"));
445
446         rectPrivate->setState("green");
447         QCOMPARE(rect->color(),QColor("green"));
448         rect->setProperty("sourceColor", QColor("purple"));
449         QCOMPARE(rect->color(),QColor("green"));
450
451         rectPrivate->setState("blue");
452         QCOMPARE(rect->color(),QColor("purple"));
453
454         rectPrivate->setState("green");
455         QCOMPARE(rect->color(),QColor("green"));
456
457         rectPrivate->setState("");
458         QCOMPARE(rect->color(),QColor("red"));
459     }
460 }
461
462 void tst_qdeclarativestates::signalOverride()
463 {
464     QDeclarativeEngine engine;
465
466     {
467         QDeclarativeComponent rectComponent(&engine, testFileUrl("signalOverride.qml"));
468         MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
469         QVERIFY(rect != 0);
470
471         QCOMPARE(rect->color(),QColor("red"));
472         rect->doSomething();
473         QCOMPARE(rect->color(),QColor("blue"));
474
475         QQuickItemPrivate::get(rect)->setState("green");
476         rect->doSomething();
477         QCOMPARE(rect->color(),QColor("green"));
478     }
479
480     {
481         QDeclarativeComponent rectComponent(&engine, testFileUrl("signalOverride2.qml"));
482         MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
483         QVERIFY(rect != 0);
484
485         QCOMPARE(rect->color(),QColor("white"));
486         rect->doSomething();
487         QCOMPARE(rect->color(),QColor("blue"));
488
489         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("extendedRect"));
490         QQuickItemPrivate::get(innerRect)->setState("green");
491         rect->doSomething();
492         QCOMPARE(rect->color(),QColor("blue"));
493         QCOMPARE(innerRect->color(),QColor("green"));
494         QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
495     }
496 }
497
498 void tst_qdeclarativestates::signalOverrideCrash()
499 {
500     QDeclarativeEngine engine;
501
502     QDeclarativeComponent rectComponent(&engine, testFileUrl("signalOverrideCrash.qml"));
503     MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
504     QVERIFY(rect != 0);
505
506     QQuickItemPrivate::get(rect)->setState("overridden");
507     rect->doSomething();
508 }
509
510 void tst_qdeclarativestates::signalOverrideCrash2()
511 {
512     QDeclarativeEngine engine;
513
514     QDeclarativeComponent rectComponent(&engine, testFileUrl("signalOverrideCrash2.qml"));
515     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
516     QVERIFY(rect != 0);
517
518     QQuickItemPrivate::get(rect)->setState("state1");
519     QQuickItemPrivate::get(rect)->setState("state2");
520     QQuickItemPrivate::get(rect)->setState("state1");
521
522     delete rect;
523 }
524
525 void tst_qdeclarativestates::signalOverrideCrash3()
526 {
527     QDeclarativeEngine engine;
528
529     QDeclarativeComponent rectComponent(&engine, testFileUrl("signalOverrideCrash3.qml"));
530     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
531     QVERIFY(rect != 0);
532
533     QQuickItemPrivate::get(rect)->setState("state1");
534     QQuickItemPrivate::get(rect)->setState("");
535     QQuickItemPrivate::get(rect)->setState("state2");
536     QQuickItemPrivate::get(rect)->setState("");
537
538     delete rect;
539 }
540
541 void tst_qdeclarativestates::parentChange()
542 {
543     QDeclarativeEngine engine;
544
545     {
546         QDeclarativeComponent rectComponent(&engine, testFileUrl("parentChange1.qml"));
547         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
548         QVERIFY(rect != 0);
549
550         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
551         QVERIFY(innerRect != 0);
552
553         QDeclarativeListReference list(rect, "states");
554         QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
555         QVERIFY(state != 0);
556
557         qmlExecuteDeferred(state);
558         QQuickParentChange *pChange = qobject_cast<QQuickParentChange*>(state->operationAt(0));
559         QVERIFY(pChange != 0);
560         QQuickItem *nParent = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("NewParent"));
561         QVERIFY(nParent != 0);
562
563         QCOMPARE(pChange->parent(), nParent);
564
565         QQuickItemPrivate::get(rect)->setState("reparented");
566         QCOMPARE(innerRect->rotation(), qreal(0));
567         QCOMPARE(innerRect->scale(), qreal(1));
568         QCOMPARE(innerRect->x(), qreal(-133));
569         QCOMPARE(innerRect->y(), qreal(-300));
570     }
571
572     {
573         QDeclarativeComponent rectComponent(&engine, testFileUrl("parentChange2.qml"));
574         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
575         QVERIFY(rect != 0);
576         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
577         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
578         QVERIFY(innerRect != 0);
579
580         rectPrivate->setState("reparented");
581         QCOMPARE(innerRect->rotation(), qreal(15));
582         QCOMPARE(innerRect->scale(), qreal(.5));
583         QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-19.9075));
584         QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-8.73433));
585     }
586
587     {
588         QDeclarativeComponent rectComponent(&engine, testFileUrl("parentChange3.qml"));
589         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
590         QVERIFY(rect != 0);
591         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
592         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
593         QVERIFY(innerRect != 0);
594
595         rectPrivate->setState("reparented");
596         QCOMPARE(innerRect->rotation(), qreal(-37));
597         QCOMPARE(innerRect->scale(), qreal(.25));
598         QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-217.305));
599         QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-164.413));
600
601         rectPrivate->setState("");
602         QCOMPARE(innerRect->rotation(), qreal(0));
603         QCOMPARE(innerRect->scale(), qreal(1));
604         QCOMPARE(innerRect->x(), qreal(5));
605         //do a non-qFuzzyCompare fuzzy compare
606         QVERIFY(innerRect->y() < qreal(0.00001) && innerRect->y() > qreal(-0.00001));
607     }
608
609     {
610         QDeclarativeComponent rectComponent(&engine, testFileUrl("parentChange6.qml"));
611         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
612         QVERIFY(rect != 0);
613
614         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
615         QVERIFY(innerRect != 0);
616
617         QQuickItemPrivate::get(rect)->setState("reparented");
618         QCOMPARE(innerRect->rotation(), qreal(180));
619         QCOMPARE(innerRect->scale(), qreal(1));
620         QCOMPARE(innerRect->x(), qreal(-105));
621         QCOMPARE(innerRect->y(), qreal(-105));
622     }
623 }
624
625 void tst_qdeclarativestates::parentChangeErrors()
626 {
627     QDeclarativeEngine engine;
628
629     {
630         QDeclarativeComponent rectComponent(&engine, testFileUrl("parentChange4.qml"));
631         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
632         QVERIFY(rect != 0);
633
634         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
635         QVERIFY(innerRect != 0);
636
637         QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange4.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under non-uniform scale");
638         QQuickItemPrivate::get(rect)->setState("reparented");
639         QCOMPARE(innerRect->rotation(), qreal(0));
640         QCOMPARE(innerRect->scale(), qreal(1));
641         QCOMPARE(innerRect->x(), qreal(5));
642         QCOMPARE(innerRect->y(), qreal(5));
643     }
644
645     {
646         QDeclarativeComponent rectComponent(&engine, testFileUrl("parentChange5.qml"));
647         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
648         QVERIFY(rect != 0);
649
650         QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
651         QVERIFY(innerRect != 0);
652
653         QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange5.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under complex transform");
654         QQuickItemPrivate::get(rect)->setState("reparented");
655         QCOMPARE(innerRect->rotation(), qreal(0));
656         QCOMPARE(innerRect->scale(), qreal(1));
657         QCOMPARE(innerRect->x(), qreal(5));
658         QCOMPARE(innerRect->y(), qreal(5));
659     }
660 }
661
662 void tst_qdeclarativestates::anchorChanges()
663 {
664     QDeclarativeEngine engine;
665
666     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
667     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
668     QVERIFY(rect != 0);
669     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
670
671     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
672     QVERIFY(innerRect != 0);
673
674     QDeclarativeListReference list(rect, "states");
675     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
676     QVERIFY(state != 0);
677
678     qmlExecuteDeferred(state);
679     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
680     QVERIFY(aChanges != 0);
681
682     rectPrivate->setState("right");
683     QCOMPARE(innerRect->x(), qreal(150));
684     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
685     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid);  //### was reset (how do we distinguish from not set at all)
686     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
687     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
688
689     rectPrivate->setState("");
690     QCOMPARE(innerRect->x(), qreal(5));
691
692     delete rect;
693 }
694
695 void tst_qdeclarativestates::anchorChanges2()
696 {
697     QDeclarativeEngine engine;
698
699     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
700     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
701     QVERIFY(rect != 0);
702     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
703
704     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
705     QVERIFY(innerRect != 0);
706
707     rectPrivate->setState("right");
708     QCOMPARE(innerRect->x(), qreal(150));
709
710     rectPrivate->setState("");
711     QCOMPARE(innerRect->x(), qreal(5));
712
713     delete rect;
714 }
715
716 void tst_qdeclarativestates::anchorChanges3()
717 {
718     QDeclarativeEngine engine;
719
720     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
721     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
722     QVERIFY(rect != 0);
723     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
724
725     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
726     QVERIFY(innerRect != 0);
727
728     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
729     QVERIFY(leftGuideline != 0);
730
731     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
732     QVERIFY(bottomGuideline != 0);
733
734     QDeclarativeListReference list(rect, "states");
735     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
736     QVERIFY(state != 0);
737
738     qmlExecuteDeferred(state);
739     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
740     QVERIFY(aChanges != 0);
741
742     rectPrivate->setState("reanchored");
743     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
744     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
745     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
746     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
747     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
748     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
749     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
750     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
751     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
752
753     QCOMPARE(innerRect->x(), qreal(10));
754     QCOMPARE(innerRect->y(), qreal(0));
755     QCOMPARE(innerRect->width(), qreal(190));
756     QCOMPARE(innerRect->height(), qreal(150));
757
758     rectPrivate->setState("");
759     QCOMPARE(innerRect->x(), qreal(0));
760     QCOMPARE(innerRect->y(), qreal(10));
761     QCOMPARE(innerRect->width(), qreal(150));
762     QCOMPARE(innerRect->height(), qreal(190));
763
764     delete rect;
765 }
766
767 void tst_qdeclarativestates::anchorChanges4()
768 {
769     QDeclarativeEngine engine;
770
771     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges4.qml"));
772     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
773     QVERIFY(rect != 0);
774
775     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
776     QVERIFY(innerRect != 0);
777
778     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
779     QVERIFY(leftGuideline != 0);
780
781     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
782     QVERIFY(bottomGuideline != 0);
783
784     QDeclarativeListReference list(rect, "states");
785     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
786     QVERIFY(state != 0);
787
788     qmlExecuteDeferred(state);
789     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
790     QVERIFY(aChanges != 0);
791
792     QQuickItemPrivate::get(rect)->setState("reanchored");
793     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
794     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().item);
795     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
796     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QQuickItemPrivate::get(leftGuideline)->verticalCenter().item);
797     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QQuickItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
798
799     delete rect;
800 }
801
802 void tst_qdeclarativestates::anchorChanges5()
803 {
804     QDeclarativeEngine engine;
805
806     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges5.qml"));
807     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
808     QVERIFY(rect != 0);
809
810     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
811     QVERIFY(innerRect != 0);
812
813     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
814     QVERIFY(leftGuideline != 0);
815
816     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
817     QVERIFY(bottomGuideline != 0);
818
819     QDeclarativeListReference list(rect, "states");
820     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
821     QVERIFY(state != 0);
822
823     qmlExecuteDeferred(state);
824     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
825     QVERIFY(aChanges != 0);
826
827     QQuickItemPrivate::get(rect)->setState("reanchored");
828     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
829     //QCOMPARE(aChanges->anchors()->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
830     //QCOMPARE(aChanges->anchors()->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
831     //QCOMPARE(aChanges->anchors()->baseline().item, leftGuideline->baseline().item);
832     //QCOMPARE(aChanges->anchors()->baseline().anchorLine, leftGuideline->baseline().anchorLine);
833
834     delete rect;
835 }
836
837 void mirrorAnchors(QQuickItem *item) {
838     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
839     itemPrivate->setLayoutMirror(true);
840 }
841
842 qreal offsetRTL(QQuickItem *anchorItem, QQuickItem *item) {
843     return anchorItem->width()+2*anchorItem->x()-item->width();
844 }
845
846 void tst_qdeclarativestates::anchorChangesRTL()
847 {
848     QDeclarativeEngine engine;
849
850     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
851     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
852     QVERIFY(rect != 0);
853     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
854
855     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
856     QVERIFY(innerRect != 0);
857     mirrorAnchors(innerRect);
858
859     QDeclarativeListReference list(rect, "states");
860     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
861     QVERIFY(state != 0);
862
863     qmlExecuteDeferred(state);
864     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
865     QVERIFY(aChanges != 0);
866
867     rectPrivate->setState("right");
868     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
869     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
870     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid);  //### was reset (how do we distinguish from not set at all)
871     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
872     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
873
874     rectPrivate->setState("");
875     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
876
877     delete rect;
878 }
879
880 void tst_qdeclarativestates::anchorChangesRTL2()
881 {
882     QDeclarativeEngine engine;
883
884     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
885     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
886     QVERIFY(rect != 0);
887     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
888
889     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
890     QVERIFY(innerRect != 0);
891     mirrorAnchors(innerRect);
892
893     rectPrivate->setState("right");
894     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
895
896     rectPrivate->setState("");
897     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
898
899     delete rect;
900 }
901
902 void tst_qdeclarativestates::anchorChangesRTL3()
903 {
904     QDeclarativeEngine engine;
905
906     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
907     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
908     QVERIFY(rect != 0);
909     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
910
911     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
912     QVERIFY(innerRect != 0);
913     mirrorAnchors(innerRect);
914
915     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
916     QVERIFY(leftGuideline != 0);
917
918     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
919     QVERIFY(bottomGuideline != 0);
920
921     QDeclarativeListReference list(rect, "states");
922     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
923     QVERIFY(state != 0);
924
925     qmlExecuteDeferred(state);
926     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
927     QVERIFY(aChanges != 0);
928
929     rectPrivate->setState("reanchored");
930     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
931     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
932     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
933     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
934     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
935     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
936     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
937     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
938     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
939
940     QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
941     QCOMPARE(innerRect->y(), qreal(0));
942     // between left side of parent and leftGuideline.x: 10, which has width 0
943     QCOMPARE(innerRect->width(), qreal(10));
944     QCOMPARE(innerRect->height(), qreal(150));
945
946     rectPrivate->setState("");
947     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
948     QCOMPARE(innerRect->y(), qreal(10));
949     // between right side of parent and left side of rightGuideline.x: 150, which has width 0
950     QCOMPARE(innerRect->width(), qreal(50));
951     QCOMPARE(innerRect->height(), qreal(190));
952
953     delete rect;
954 }
955
956 //QTBUG-9609
957 void tst_qdeclarativestates::anchorChangesCrash()
958 {
959     QDeclarativeEngine engine;
960
961     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChangesCrash.qml"));
962     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
963     QVERIFY(rect != 0);
964
965     QQuickItemPrivate::get(rect)->setState("reanchored");
966
967     delete rect;
968 }
969
970 // QTBUG-12273
971 void tst_qdeclarativestates::anchorRewindBug()
972 {
973     QQuickView *view = new QQuickView;
974     view->setSource(testFileUrl("anchorRewindBug.qml"));
975
976     view->show();
977     view->requestActivateWindow();
978
979     QTest::qWaitForWindowShown(view);
980
981     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
982     QVERIFY(rect != 0);
983
984     QQuickItem * column = rect->findChild<QQuickItem*>("column");
985
986     QVERIFY(column != 0);
987     QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
988     QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
989     QCOMPARE(column->height(), 200.0);
990     QQuickItemPrivate::get(rect)->setState("reanchored");
991
992     // column height and width should stay implicit
993     // and column's implicit resizing should still work
994     QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
995     QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
996     QTRY_COMPARE(column->height(), 100.0);
997
998     QQuickItemPrivate::get(rect)->setState("");
999
1000     // column height and width should stay implicit
1001     // and column's implicit resizing should still work
1002     QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
1003     QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
1004     QTRY_COMPARE(column->height(), 200.0);
1005
1006     delete view;
1007 }
1008
1009 // QTBUG-11834
1010 void tst_qdeclarativestates::anchorRewindBug2()
1011 {
1012     QDeclarativeEngine engine;
1013
1014     QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorRewindBug2.qml"));
1015     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1016     QVERIFY(rect != 0);
1017
1018     QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
1019
1020     QVERIFY(mover != 0);
1021     QCOMPARE(mover->y(), qreal(0.0));
1022     QCOMPARE(mover->width(), qreal(50.0));
1023
1024     QQuickItemPrivate::get(rect)->setState("anchored");
1025     QCOMPARE(mover->y(), qreal(250.0));
1026     QCOMPARE(mover->width(), qreal(200.0));
1027
1028     QQuickItemPrivate::get(rect)->setState("");
1029     QCOMPARE(mover->y(), qreal(0.0));
1030     QCOMPARE(mover->width(), qreal(50.0));
1031
1032     delete rect;
1033 }
1034
1035 void tst_qdeclarativestates::script()
1036 {
1037     QDeclarativeEngine engine;
1038
1039     {
1040         QDeclarativeComponent rectComponent(&engine, testFileUrl("script.qml"));
1041         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1042         QVERIFY(rect != 0);
1043         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1044         QCOMPARE(rect->color(),QColor("red"));
1045
1046         rectPrivate->setState("blue");
1047         QCOMPARE(rect->color(),QColor("blue"));
1048
1049         rectPrivate->setState("");
1050         QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
1051     }
1052 }
1053
1054 void tst_qdeclarativestates::restoreEntryValues()
1055 {
1056     QDeclarativeEngine engine;
1057
1058     QDeclarativeComponent rectComponent(&engine, testFileUrl("restoreEntryValues.qml"));
1059     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1060     QVERIFY(rect != 0);
1061     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1062     QCOMPARE(rect->color(),QColor("red"));
1063
1064     rectPrivate->setState("blue");
1065     QCOMPARE(rect->color(),QColor("blue"));
1066
1067     rectPrivate->setState("");
1068     QCOMPARE(rect->color(),QColor("blue"));
1069 }
1070
1071 void tst_qdeclarativestates::explicitChanges()
1072 {
1073     QDeclarativeEngine engine;
1074
1075     QDeclarativeComponent rectComponent(&engine, testFileUrl("explicit.qml"));
1076     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1077     QVERIFY(rect != 0);
1078     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1079     QDeclarativeListReference list(rect, "states");
1080     QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
1081     QVERIFY(state != 0);
1082
1083     qmlExecuteDeferred(state);
1084     QDeclarativePropertyChanges *changes = qobject_cast<QDeclarativePropertyChanges*>(rect->findChild<QDeclarativePropertyChanges*>("changes"));
1085     QVERIFY(changes != 0);
1086     QVERIFY(changes->isExplicit());
1087
1088     QCOMPARE(rect->color(),QColor("red"));
1089
1090     rectPrivate->setState("blue");
1091     QCOMPARE(rect->color(),QColor("blue"));
1092
1093     rect->setProperty("sourceColor", QColor("green"));
1094     QCOMPARE(rect->color(),QColor("blue"));
1095
1096     rectPrivate->setState("");
1097     QCOMPARE(rect->color(),QColor("red"));
1098     rect->setProperty("sourceColor", QColor("yellow"));
1099     QCOMPARE(rect->color(),QColor("red"));
1100
1101     rectPrivate->setState("blue");
1102     QCOMPARE(rect->color(),QColor("yellow"));
1103 }
1104
1105 void tst_qdeclarativestates::propertyErrors()
1106 {
1107     QDeclarativeEngine engine;
1108     QDeclarativeComponent rectComponent(&engine, testFileUrl("propertyErrors.qml"));
1109     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1110     QVERIFY(rect != 0);
1111
1112     QCOMPARE(rect->color(),QColor("red"));
1113
1114     QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1115     QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
1116     QQuickItemPrivate::get(rect)->setState("blue");
1117 }
1118
1119 void tst_qdeclarativestates::incorrectRestoreBug()
1120 {
1121     QDeclarativeEngine engine;
1122
1123     QDeclarativeComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
1124     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1125     QVERIFY(rect != 0);
1126     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1127     QCOMPARE(rect->color(),QColor("red"));
1128
1129     rectPrivate->setState("blue");
1130     QCOMPARE(rect->color(),QColor("blue"));
1131
1132     rectPrivate->setState("");
1133     QCOMPARE(rect->color(),QColor("red"));
1134
1135     // make sure if we change the base state value, we then restore to it correctly
1136     rect->setColor(QColor("green"));
1137
1138     rectPrivate->setState("blue");
1139     QCOMPARE(rect->color(),QColor("blue"));
1140
1141     rectPrivate->setState("");
1142     QCOMPARE(rect->color(),QColor("green"));
1143 }
1144
1145 void tst_qdeclarativestates::autoStateAtStartupRestoreBug()
1146 {
1147     QDeclarativeEngine engine;
1148
1149     QDeclarativeComponent component(&engine, testFileUrl("autoStateAtStartupRestoreBug.qml"));
1150     QObject *obj = component.create();
1151
1152     QVERIFY(obj != 0);
1153     QCOMPARE(obj->property("test").toInt(), 3);
1154
1155     obj->setProperty("input", 2);
1156
1157     QCOMPARE(obj->property("test").toInt(), 9);
1158
1159     delete obj;
1160 }
1161
1162 void tst_qdeclarativestates::deletingChange()
1163 {
1164     QDeclarativeEngine engine;
1165
1166     QDeclarativeComponent rectComponent(&engine, testFileUrl("deleting.qml"));
1167     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1168     QVERIFY(rect != 0);
1169     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1170     rectPrivate->setState("blue");
1171     QCOMPARE(rect->color(),QColor("blue"));
1172     QCOMPARE(rect->radius(),qreal(5));
1173
1174     rectPrivate->setState("");
1175     QCOMPARE(rect->color(),QColor("red"));
1176     QCOMPARE(rect->radius(),qreal(0));
1177
1178     QDeclarativePropertyChanges *pc = rect->findChild<QDeclarativePropertyChanges*>("pc1");
1179     QVERIFY(pc != 0);
1180     delete pc;
1181
1182     QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
1183     QVERIFY(state != 0);
1184     qmlExecuteDeferred(state);
1185     QCOMPARE(state->operationCount(), 1);
1186
1187     rectPrivate->setState("blue");
1188     QCOMPARE(rect->color(),QColor("red"));
1189     QCOMPARE(rect->radius(),qreal(5));
1190
1191     delete rect;
1192 }
1193
1194 void tst_qdeclarativestates::deletingState()
1195 {
1196     QDeclarativeEngine engine;
1197
1198     QDeclarativeComponent rectComponent(&engine, testFileUrl("deletingState.qml"));
1199     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1200     QVERIFY(rect != 0);
1201
1202     QDeclarativeStateGroup *sg = rect->findChild<QDeclarativeStateGroup*>();
1203     QVERIFY(sg != 0);
1204     QVERIFY(sg->findState("blue") != 0);
1205
1206     sg->setState("blue");
1207     QCOMPARE(rect->color(),QColor("blue"));
1208
1209     sg->setState("");
1210     QCOMPARE(rect->color(),QColor("red"));
1211
1212     QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
1213     QVERIFY(state != 0);
1214     delete state;
1215
1216     QVERIFY(sg->findState("blue") == 0);
1217
1218     //### should we warn that state doesn't exist
1219     sg->setState("blue");
1220     QCOMPARE(rect->color(),QColor("red"));
1221
1222     delete rect;
1223 }
1224
1225 void tst_qdeclarativestates::tempState()
1226 {
1227     QDeclarativeEngine engine;
1228
1229     QDeclarativeComponent rectComponent(&engine, testFileUrl("legalTempState.qml"));
1230     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1231     QVERIFY(rect != 0);
1232     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1233     QTest::ignoreMessage(QtDebugMsg, "entering placed");
1234     QTest::ignoreMessage(QtDebugMsg, "entering idle");
1235     rectPrivate->setState("placed");
1236     QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
1237 }
1238
1239 void tst_qdeclarativestates::illegalTempState()
1240 {
1241     QDeclarativeEngine engine;
1242
1243     QDeclarativeComponent rectComponent(&engine, testFileUrl("illegalTempState.qml"));
1244     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1245     QVERIFY(rect != 0);
1246     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1247     QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
1248     rectPrivate->setState("placed");
1249     QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
1250 }
1251
1252 void tst_qdeclarativestates::nonExistantProperty()
1253 {
1254     QDeclarativeEngine engine;
1255
1256     QDeclarativeComponent rectComponent(&engine, testFileUrl("nonExistantProp.qml"));
1257     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1258     QVERIFY(rect != 0);
1259     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1260     QTest::ignoreMessage(QtWarningMsg, fullDataPath("nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1261     rectPrivate->setState("blue");
1262     QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
1263 }
1264
1265 void tst_qdeclarativestates::reset()
1266 {
1267     QDeclarativeEngine engine;
1268
1269     QDeclarativeComponent c(&engine, testFileUrl("reset.qml"));
1270     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1271     QVERIFY(rect != 0);
1272
1273     QQuickImage *image = rect->findChild<QQuickImage*>();
1274     QVERIFY(image != 0);
1275     QCOMPARE(image->width(), qreal(40.));
1276     QCOMPARE(image->height(), qreal(20.));
1277
1278     QQuickItemPrivate::get(rect)->setState("state1");
1279
1280     QCOMPARE(image->width(), 20.0);
1281     QCOMPARE(image->height(), qreal(20.));
1282
1283     delete rect;
1284 }
1285
1286 void tst_qdeclarativestates::illegalObjectCreation()
1287 {
1288     QDeclarativeEngine engine;
1289
1290     QDeclarativeComponent component(&engine, testFileUrl("illegalObj.qml"));
1291     QList<QDeclarativeError> errors = component.errors();
1292     QVERIFY(errors.count() == 1);
1293     const QDeclarativeError &error = errors.at(0);
1294     QCOMPARE(error.line(), 9);
1295     QCOMPARE(error.column(), 23);
1296     QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
1297 }
1298
1299 void tst_qdeclarativestates::whenOrdering()
1300 {
1301     QDeclarativeEngine engine;
1302
1303     QDeclarativeComponent c(&engine, testFileUrl("whenOrdering.qml"));
1304     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1305     QVERIFY(rect != 0);
1306     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1307
1308     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1309     rect->setProperty("condition2", true);
1310     QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
1311     rect->setProperty("condition1", true);
1312     QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1313     rect->setProperty("condition2", false);
1314     QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1315     rect->setProperty("condition2", true);
1316     QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1317     rect->setProperty("condition1", false);
1318     rect->setProperty("condition2", false);
1319     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1320 }
1321
1322 void tst_qdeclarativestates::urlResolution()
1323 {
1324     QDeclarativeEngine engine;
1325
1326     QDeclarativeComponent c(&engine, testFileUrl("urlResolution.qml"));
1327     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1328     QVERIFY(rect != 0);
1329
1330     QQuickItem *myType = rect->findChild<QQuickItem*>("MyType");
1331     QQuickImage *image1 = rect->findChild<QQuickImage*>("image1");
1332     QQuickImage *image2 = rect->findChild<QQuickImage*>("image2");
1333     QQuickImage *image3 = rect->findChild<QQuickImage*>("image3");
1334     QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
1335
1336     QQuickItemPrivate::get(myType)->setState("SetImageState");
1337     QUrl resolved = testFileUrl("Implementation/images/qt-logo.png");
1338     QCOMPARE(image1->source(), resolved);
1339     QCOMPARE(image2->source(), resolved);
1340     QCOMPARE(image3->source(), resolved);
1341
1342     delete rect;
1343 }
1344
1345 void tst_qdeclarativestates::unnamedWhen()
1346 {
1347     QDeclarativeEngine engine;
1348
1349     QDeclarativeComponent c(&engine, testFileUrl("unnamedWhen.qml"));
1350     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1351     QVERIFY(rect != 0);
1352     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1353
1354     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1355     QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1356     rect->setProperty("triggerState", true);
1357     QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1358     QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1359     rect->setProperty("triggerState", false);
1360     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1361     QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1362 }
1363
1364 void tst_qdeclarativestates::returnToBase()
1365 {
1366     QDeclarativeEngine engine;
1367
1368     QDeclarativeComponent c(&engine, testFileUrl("returnToBase.qml"));
1369     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1370     QVERIFY(rect != 0);
1371     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1372
1373     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1374     QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1375     rect->setProperty("triggerState", true);
1376     QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1377     QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1378     rect->setProperty("triggerState", false);
1379     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1380     QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
1381 }
1382
1383 //QTBUG-12559
1384 void tst_qdeclarativestates::extendsBug()
1385 {
1386     QDeclarativeEngine engine;
1387
1388     QDeclarativeComponent c(&engine, testFileUrl("extendsBug.qml"));
1389     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1390     QVERIFY(rect != 0);
1391     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1392     QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
1393
1394     rectPrivate->setState("b");
1395     QCOMPARE(greenRect->x(), qreal(100));
1396     QCOMPARE(greenRect->y(), qreal(100));
1397 }
1398
1399 void tst_qdeclarativestates::editProperties()
1400 {
1401     QDeclarativeEngine engine;
1402
1403     QDeclarativeComponent c(&engine, testFileUrl("editProperties.qml"));
1404     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1405     QVERIFY(rect != 0);
1406
1407     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1408
1409     QDeclarativeStateGroup *stateGroup = rectPrivate->_states();
1410     QVERIFY(stateGroup != 0);
1411     qmlExecuteDeferred(stateGroup);
1412
1413     QDeclarativeState *blueState = stateGroup->findState("blue");
1414     QVERIFY(blueState != 0);
1415     qmlExecuteDeferred(blueState);
1416
1417     QDeclarativePropertyChanges *propertyChangesBlue = qobject_cast<QDeclarativePropertyChanges*>(blueState->operationAt(0));
1418     QVERIFY(propertyChangesBlue != 0);
1419
1420     QDeclarativeState *greenState = stateGroup->findState("green");
1421     QVERIFY(greenState != 0);
1422     qmlExecuteDeferred(greenState);
1423
1424     QDeclarativePropertyChanges *propertyChangesGreen = qobject_cast<QDeclarativePropertyChanges*>(greenState->operationAt(0));
1425     QVERIFY(propertyChangesGreen != 0);
1426
1427     QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
1428     QVERIFY(childRect != 0);
1429     QCOMPARE(childRect->width(), qreal(402));
1430     QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1431     QCOMPARE(childRect->height(), qreal(200));
1432
1433     rectPrivate->setState("blue");
1434     QCOMPARE(childRect->width(), qreal(50));
1435     QCOMPARE(childRect->height(), qreal(40));
1436     QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1437     QVERIFY(blueState->bindingInRevertList(childRect, "width"));
1438
1439
1440     rectPrivate->setState("green");
1441     QCOMPARE(childRect->width(), qreal(200));
1442     QCOMPARE(childRect->height(), qreal(100));
1443     QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1444
1445
1446     rectPrivate->setState("");
1447
1448
1449     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1450     QVERIFY(propertyChangesBlue->containsValue("width"));
1451     QVERIFY(!propertyChangesBlue->containsProperty("x"));
1452     QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1453     QVERIFY(!propertyChangesBlue->value("x").isValid());
1454
1455     propertyChangesBlue->changeValue("width", 60);
1456     QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1457     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1458
1459
1460     propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1461     QVERIFY(!propertyChangesBlue->containsValue("width"));
1462     QVERIFY(propertyChangesBlue->containsExpression("width"));
1463     QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1464     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1465
1466     propertyChangesBlue->changeValue("width", 50);
1467     QVERIFY(propertyChangesBlue->containsValue("width"));
1468     QVERIFY(!propertyChangesBlue->containsExpression("width"));
1469     QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1470     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1471
1472     QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1473     rectPrivate->setState("blue");
1474     QCOMPARE(childRect->width(), qreal(50));
1475     QCOMPARE(childRect->height(), qreal(40));
1476
1477     propertyChangesBlue->changeValue("width", 60);
1478     QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1479     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1480     QCOMPARE(childRect->width(), qreal(60));
1481     QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1482
1483     propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1484     QVERIFY(!propertyChangesBlue->containsValue("width"));
1485     QVERIFY(propertyChangesBlue->containsExpression("width"));
1486     QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1487     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1488     QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1489     QCOMPARE(childRect->width(), qreal(200));
1490
1491     propertyChangesBlue->changeValue("width", 50);
1492     QCOMPARE(childRect->width(), qreal(50));
1493
1494     rectPrivate->setState("");
1495     QCOMPARE(childRect->width(), qreal(402));
1496     QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1497
1498     QCOMPARE(propertyChangesGreen->actions().length(), 2);
1499     rectPrivate->setState("green");
1500     QCOMPARE(childRect->width(), qreal(200));
1501     QCOMPARE(childRect->height(), qreal(100));
1502     QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1503     QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1504     QCOMPARE(propertyChangesGreen->actions().length(), 2);
1505
1506
1507     propertyChangesGreen->removeProperty("height");
1508     QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "height")));
1509     QCOMPARE(childRect->height(), qreal(200));
1510
1511     QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1512     QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
1513     propertyChangesGreen->removeProperty("width");
1514     QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1515     QCOMPARE(childRect->width(), qreal(402));
1516     QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
1517     QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
1518
1519     propertyChangesBlue->removeProperty("width");
1520     QCOMPARE(childRect->width(), qreal(402));
1521
1522     rectPrivate->setState("blue");
1523     QCOMPARE(childRect->width(), qreal(402));
1524     QCOMPARE(childRect->height(), qreal(40));
1525 }
1526
1527 void tst_qdeclarativestates::QTBUG_14830()
1528 {
1529     QDeclarativeEngine engine;
1530
1531     QDeclarativeComponent c(&engine, testFileUrl("QTBUG-14830.qml"));
1532     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1533     QVERIFY(rect != 0);
1534     QQuickItem *item = rect->findChild<QQuickItem*>("area");
1535
1536     QCOMPARE(item->width(), qreal(171));
1537 }
1538
1539 void tst_qdeclarativestates::avoidFastForward()
1540 {
1541     QDeclarativeEngine engine;
1542
1543     //shouldn't fast forward if there isn't a transition
1544     QDeclarativeComponent c(&engine, testFileUrl("avoidFastForward.qml"));
1545     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1546     QVERIFY(rect != 0);
1547
1548     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1549     rectPrivate->setState("a");
1550     QCOMPARE(rect->property("updateCount").toInt(), 1);
1551 }
1552
1553 //QTBUG-22583
1554 void tst_qdeclarativestates::revertListBug()
1555 {
1556     QDeclarativeEngine engine;
1557
1558     QDeclarativeComponent c(&engine, testFileUrl("revertListBug.qml"));
1559     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1560     QVERIFY(rect != 0);
1561
1562     QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
1563     QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
1564     QQuickItem *origParent1 = rect->findChild<QQuickItem*>("originalParent1");
1565     QQuickItem *origParent2 = rect->findChild<QQuickItem*>("originalParent2");
1566     QQuickItem *newParent = rect->findChild<QQuickItem*>("newParent");
1567
1568     QCOMPARE(rect1->parentItem(), origParent1);
1569     QCOMPARE(rect2->parentItem(), origParent2);
1570
1571     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1572     rectPrivate->setState("reparented");
1573
1574     QCOMPARE(rect1->parentItem(), newParent);
1575     QCOMPARE(rect2->parentItem(), origParent2);
1576
1577     rectPrivate->setState("");
1578
1579     QCOMPARE(rect1->parentItem(), origParent1);
1580     QCOMPARE(rect2->parentItem(), origParent2);
1581
1582     QMetaObject::invokeMethod(rect, "switchTargetItem");
1583
1584     rectPrivate->setState("reparented");
1585
1586     QCOMPARE(rect1->parentItem(), origParent1);
1587     QCOMPARE(rect2->parentItem(), newParent);
1588
1589     rectPrivate->setState("");
1590
1591     QCOMPARE(rect1->parentItem(), origParent1);
1592     QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
1593 }
1594
1595 QTEST_MAIN(tst_qdeclarativestates)
1596
1597 #include "tst_qdeclarativestates.moc"