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