Adapt to Qt5 meta-object changes
[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 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_qquickstates::initTestCase()
153 {
154     QQmlDataTest::initTestCase();
155     qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
156 }
157
158 QByteArray tst_qquickstates::fullDataPath(const QString &path) const
159 {
160     return testFileUrl(path).toString().toUtf8();
161 }
162
163 void tst_qquickstates::basicChanges()
164 {
165     QQmlEngine engine;
166
167     {
168         QQmlComponent 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         QQmlComponent 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         QQmlComponent 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         QQmlComponent 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 = prop.notifySignal().methodSignature();
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_qquickstates::attachedPropertyChanges()
259 {
260     QQmlEngine engine;
261
262     QQmlComponent 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_qquickstates::basicExtension()
280 {
281     QQmlEngine engine;
282
283     {
284         QQmlComponent 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         QQmlComponent 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_qquickstates::basicBinding()
346 {
347     QQmlEngine engine;
348
349     {
350         QQmlComponent 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         QQmlComponent 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         QQmlComponent 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         QQmlComponent 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_qquickstates::signalOverride()
463 {
464     QQmlEngine engine;
465
466     {
467         QQmlComponent 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         QQmlComponent 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_qquickstates::signalOverrideCrash()
499 {
500     QQmlEngine engine;
501
502     QQmlComponent 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_qquickstates::signalOverrideCrash2()
511 {
512     QQmlEngine engine;
513
514     QQmlComponent 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_qquickstates::signalOverrideCrash3()
526 {
527     QQmlEngine engine;
528
529     QQmlComponent 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_qquickstates::parentChange()
542 {
543     QQmlEngine engine;
544
545     {
546         QQmlComponent 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         QQmlListReference list(rect, "states");
554         QQuickState *state = qobject_cast<QQuickState*>(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         QQmlComponent 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         QQmlComponent 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         QQmlComponent 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_qquickstates::parentChangeErrors()
626 {
627     QQmlEngine engine;
628
629     {
630         QQmlComponent 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         QQmlComponent 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_qquickstates::anchorChanges()
663 {
664     QQmlEngine engine;
665
666     QQmlComponent 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     QQmlListReference list(rect, "states");
675     QQuickState *state = qobject_cast<QQuickState*>(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     QCOMPARE(aChanges->anchors()->left().script(), QLatin1String("undefined"));
683     QCOMPARE(aChanges->anchors()->right().script(), QLatin1String("container.right"));
684
685     rectPrivate->setState("right");
686     QCOMPARE(innerRect->x(), qreal(150));
687     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
688     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid);  //### was reset (how do we distinguish from not set at all)
689     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
690     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
691
692     rectPrivate->setState("");
693     QCOMPARE(innerRect->x(), qreal(5));
694
695     delete rect;
696 }
697
698 void tst_qquickstates::anchorChanges2()
699 {
700     QQmlEngine engine;
701
702     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
703     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
704     QVERIFY(rect != 0);
705     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
706
707     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
708     QVERIFY(innerRect != 0);
709
710     rectPrivate->setState("right");
711     QCOMPARE(innerRect->x(), qreal(150));
712
713     rectPrivate->setState("");
714     QCOMPARE(innerRect->x(), qreal(5));
715
716     delete rect;
717 }
718
719 void tst_qquickstates::anchorChanges3()
720 {
721     QQmlEngine engine;
722
723     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
724     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
725     QVERIFY(rect != 0);
726     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
727
728     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
729     QVERIFY(innerRect != 0);
730
731     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
732     QVERIFY(leftGuideline != 0);
733
734     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
735     QVERIFY(bottomGuideline != 0);
736
737     QQmlListReference list(rect, "states");
738     QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
739     QVERIFY(state != 0);
740
741     qmlExecuteDeferred(state);
742     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
743     QVERIFY(aChanges != 0);
744
745     QCOMPARE(aChanges->anchors()->top().script(), QLatin1String("container.top"));
746     QCOMPARE(aChanges->anchors()->bottom().script(), QLatin1String("bottomGuideline.bottom"));
747
748     rectPrivate->setState("reanchored");
749     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
750     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
751     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
752     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
753     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
754     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
755     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
756     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
757     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
758
759     QCOMPARE(innerRect->x(), qreal(10));
760     QCOMPARE(innerRect->y(), qreal(0));
761     QCOMPARE(innerRect->width(), qreal(190));
762     QCOMPARE(innerRect->height(), qreal(150));
763
764     rectPrivate->setState("");
765     QCOMPARE(innerRect->x(), qreal(0));
766     QCOMPARE(innerRect->y(), qreal(10));
767     QCOMPARE(innerRect->width(), qreal(150));
768     QCOMPARE(innerRect->height(), qreal(190));
769
770     delete rect;
771 }
772
773 void tst_qquickstates::anchorChanges4()
774 {
775     QQmlEngine engine;
776
777     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges4.qml"));
778     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
779     QVERIFY(rect != 0);
780
781     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
782     QVERIFY(innerRect != 0);
783
784     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
785     QVERIFY(leftGuideline != 0);
786
787     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
788     QVERIFY(bottomGuideline != 0);
789
790     QQmlListReference list(rect, "states");
791     QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
792     QVERIFY(state != 0);
793
794     qmlExecuteDeferred(state);
795     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
796     QVERIFY(aChanges != 0);
797
798     QCOMPARE(aChanges->anchors()->horizontalCenter().script(), QLatin1String("bottomGuideline.horizontalCenter"));
799     QCOMPARE(aChanges->anchors()->verticalCenter().script(), QLatin1String("leftGuideline.verticalCenter"));
800
801     QQuickItemPrivate::get(rect)->setState("reanchored");
802     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
803     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().item);
804     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
805     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QQuickItemPrivate::get(leftGuideline)->verticalCenter().item);
806     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QQuickItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
807
808     delete rect;
809 }
810
811 void tst_qquickstates::anchorChanges5()
812 {
813     QQmlEngine engine;
814
815     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges5.qml"));
816     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
817     QVERIFY(rect != 0);
818
819     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
820     QVERIFY(innerRect != 0);
821
822     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
823     QVERIFY(leftGuideline != 0);
824
825     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
826     QVERIFY(bottomGuideline != 0);
827
828     QQmlListReference list(rect, "states");
829     QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
830     QVERIFY(state != 0);
831
832     qmlExecuteDeferred(state);
833     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
834     QVERIFY(aChanges != 0);
835
836     QCOMPARE(aChanges->anchors()->baseline().script(), QLatin1String("leftGuideline.baseline"));
837
838     QQuickItemPrivate::get(rect)->setState("reanchored");
839     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
840     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().item);
841     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
842     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->baseline().item, QQuickItemPrivate::get(leftGuideline)->baseline().item);
843     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->baseline().anchorLine, QQuickItemPrivate::get(leftGuideline)->baseline().anchorLine);
844
845     delete rect;
846 }
847
848 void mirrorAnchors(QQuickItem *item) {
849     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
850     itemPrivate->setLayoutMirror(true);
851 }
852
853 qreal offsetRTL(QQuickItem *anchorItem, QQuickItem *item) {
854     return anchorItem->width()+2*anchorItem->x()-item->width();
855 }
856
857 void tst_qquickstates::anchorChangesRTL()
858 {
859     QQmlEngine engine;
860
861     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
862     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
863     QVERIFY(rect != 0);
864     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
865
866     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
867     QVERIFY(innerRect != 0);
868     mirrorAnchors(innerRect);
869
870     QQmlListReference list(rect, "states");
871     QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
872     QVERIFY(state != 0);
873
874     qmlExecuteDeferred(state);
875     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
876     QVERIFY(aChanges != 0);
877
878     rectPrivate->setState("right");
879     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
880     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
881     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid);  //### was reset (how do we distinguish from not set at all)
882     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
883     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
884
885     rectPrivate->setState("");
886     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
887
888     delete rect;
889 }
890
891 void tst_qquickstates::anchorChangesRTL2()
892 {
893     QQmlEngine engine;
894
895     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
896     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
897     QVERIFY(rect != 0);
898     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
899
900     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
901     QVERIFY(innerRect != 0);
902     mirrorAnchors(innerRect);
903
904     rectPrivate->setState("right");
905     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
906
907     rectPrivate->setState("");
908     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
909
910     delete rect;
911 }
912
913 void tst_qquickstates::anchorChangesRTL3()
914 {
915     QQmlEngine engine;
916
917     QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
918     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
919     QVERIFY(rect != 0);
920     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
921
922     QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
923     QVERIFY(innerRect != 0);
924     mirrorAnchors(innerRect);
925
926     QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
927     QVERIFY(leftGuideline != 0);
928
929     QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
930     QVERIFY(bottomGuideline != 0);
931
932     QQmlListReference list(rect, "states");
933     QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
934     QVERIFY(state != 0);
935
936     qmlExecuteDeferred(state);
937     QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
938     QVERIFY(aChanges != 0);
939
940     rectPrivate->setState("reanchored");
941     QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
942     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
943     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
944     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
945     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
946     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
947     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
948     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
949     QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
950
951     QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
952     QCOMPARE(innerRect->y(), qreal(0));
953     // between left side of parent and leftGuideline.x: 10, which has width 0
954     QCOMPARE(innerRect->width(), qreal(10));
955     QCOMPARE(innerRect->height(), qreal(150));
956
957     rectPrivate->setState("");
958     QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
959     QCOMPARE(innerRect->y(), qreal(10));
960     // between right side of parent and left side of rightGuideline.x: 150, which has width 0
961     QCOMPARE(innerRect->width(), qreal(50));
962     QCOMPARE(innerRect->height(), qreal(190));
963
964     delete rect;
965 }
966
967 //QTBUG-9609
968 void tst_qquickstates::anchorChangesCrash()
969 {
970     QQmlEngine engine;
971
972     QQmlComponent rectComponent(&engine, testFileUrl("anchorChangesCrash.qml"));
973     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
974     QVERIFY(rect != 0);
975
976     QQuickItemPrivate::get(rect)->setState("reanchored");
977
978     delete rect;
979 }
980
981 // QTBUG-12273
982 void tst_qquickstates::anchorRewindBug()
983 {
984     QQuickView *view = new QQuickView;
985     view->setSource(testFileUrl("anchorRewindBug.qml"));
986
987     view->show();
988     view->requestActivateWindow();
989
990     QTest::qWaitForWindowShown(view);
991
992     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
993     QVERIFY(rect != 0);
994
995     QQuickItem * column = rect->findChild<QQuickItem*>("column");
996
997     QVERIFY(column != 0);
998     QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
999     QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
1000     QCOMPARE(column->height(), 200.0);
1001     QQuickItemPrivate::get(rect)->setState("reanchored");
1002
1003     // column height and width should stay implicit
1004     // and column's implicit resizing should still work
1005     QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
1006     QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
1007     QTRY_COMPARE(column->height(), 100.0);
1008
1009     QQuickItemPrivate::get(rect)->setState("");
1010
1011     // column height and width should stay implicit
1012     // and column's implicit resizing should still work
1013     QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
1014     QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
1015     QTRY_COMPARE(column->height(), 200.0);
1016
1017     delete view;
1018 }
1019
1020 // QTBUG-11834
1021 void tst_qquickstates::anchorRewindBug2()
1022 {
1023     QQmlEngine engine;
1024
1025     QQmlComponent rectComponent(&engine, testFileUrl("anchorRewindBug2.qml"));
1026     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1027     QVERIFY(rect != 0);
1028
1029     QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
1030
1031     QVERIFY(mover != 0);
1032     QCOMPARE(mover->y(), qreal(0.0));
1033     QCOMPARE(mover->width(), qreal(50.0));
1034
1035     QQuickItemPrivate::get(rect)->setState("anchored");
1036     QCOMPARE(mover->y(), qreal(250.0));
1037     QCOMPARE(mover->width(), qreal(200.0));
1038
1039     QQuickItemPrivate::get(rect)->setState("");
1040     QCOMPARE(mover->y(), qreal(0.0));
1041     QCOMPARE(mover->width(), qreal(50.0));
1042
1043     delete rect;
1044 }
1045
1046 void tst_qquickstates::script()
1047 {
1048     QQmlEngine engine;
1049
1050     {
1051         QQmlComponent rectComponent(&engine, testFileUrl("script.qml"));
1052         QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1053         QVERIFY(rect != 0);
1054         QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1055         QCOMPARE(rect->color(),QColor("red"));
1056
1057         rectPrivate->setState("blue");
1058         QCOMPARE(rect->color(),QColor("blue"));
1059
1060         rectPrivate->setState("");
1061         QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
1062     }
1063 }
1064
1065 void tst_qquickstates::restoreEntryValues()
1066 {
1067     QQmlEngine engine;
1068
1069     QQmlComponent rectComponent(&engine, testFileUrl("restoreEntryValues.qml"));
1070     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1071     QVERIFY(rect != 0);
1072     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1073     QCOMPARE(rect->color(),QColor("red"));
1074
1075     rectPrivate->setState("blue");
1076     QCOMPARE(rect->color(),QColor("blue"));
1077
1078     rectPrivate->setState("");
1079     QCOMPARE(rect->color(),QColor("blue"));
1080 }
1081
1082 void tst_qquickstates::explicitChanges()
1083 {
1084     QQmlEngine engine;
1085
1086     QQmlComponent rectComponent(&engine, testFileUrl("explicit.qml"));
1087     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1088     QVERIFY(rect != 0);
1089     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1090     QQmlListReference list(rect, "states");
1091     QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
1092     QVERIFY(state != 0);
1093
1094     qmlExecuteDeferred(state);
1095     QQuickPropertyChanges *changes = qobject_cast<QQuickPropertyChanges*>(rect->findChild<QQuickPropertyChanges*>("changes"));
1096     QVERIFY(changes != 0);
1097     QVERIFY(changes->isExplicit());
1098
1099     QCOMPARE(rect->color(),QColor("red"));
1100
1101     rectPrivate->setState("blue");
1102     QCOMPARE(rect->color(),QColor("blue"));
1103
1104     rect->setProperty("sourceColor", QColor("green"));
1105     QCOMPARE(rect->color(),QColor("blue"));
1106
1107     rectPrivate->setState("");
1108     QCOMPARE(rect->color(),QColor("red"));
1109     rect->setProperty("sourceColor", QColor("yellow"));
1110     QCOMPARE(rect->color(),QColor("red"));
1111
1112     rectPrivate->setState("blue");
1113     QCOMPARE(rect->color(),QColor("yellow"));
1114 }
1115
1116 void tst_qquickstates::propertyErrors()
1117 {
1118     QQmlEngine engine;
1119     QQmlComponent rectComponent(&engine, testFileUrl("propertyErrors.qml"));
1120     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1121     QVERIFY(rect != 0);
1122
1123     QCOMPARE(rect->color(),QColor("red"));
1124
1125     QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1126     QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
1127     QQuickItemPrivate::get(rect)->setState("blue");
1128 }
1129
1130 void tst_qquickstates::incorrectRestoreBug()
1131 {
1132     QQmlEngine engine;
1133
1134     QQmlComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
1135     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1136     QVERIFY(rect != 0);
1137     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1138     QCOMPARE(rect->color(),QColor("red"));
1139
1140     rectPrivate->setState("blue");
1141     QCOMPARE(rect->color(),QColor("blue"));
1142
1143     rectPrivate->setState("");
1144     QCOMPARE(rect->color(),QColor("red"));
1145
1146     // make sure if we change the base state value, we then restore to it correctly
1147     rect->setColor(QColor("green"));
1148
1149     rectPrivate->setState("blue");
1150     QCOMPARE(rect->color(),QColor("blue"));
1151
1152     rectPrivate->setState("");
1153     QCOMPARE(rect->color(),QColor("green"));
1154 }
1155
1156 void tst_qquickstates::autoStateAtStartupRestoreBug()
1157 {
1158     QQmlEngine engine;
1159
1160     QQmlComponent component(&engine, testFileUrl("autoStateAtStartupRestoreBug.qml"));
1161     QObject *obj = component.create();
1162
1163     QVERIFY(obj != 0);
1164     QCOMPARE(obj->property("test").toInt(), 3);
1165
1166     obj->setProperty("input", 2);
1167
1168     QCOMPARE(obj->property("test").toInt(), 9);
1169
1170     delete obj;
1171 }
1172
1173 void tst_qquickstates::deletingChange()
1174 {
1175     QQmlEngine engine;
1176
1177     QQmlComponent rectComponent(&engine, testFileUrl("deleting.qml"));
1178     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1179     QVERIFY(rect != 0);
1180     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1181     rectPrivate->setState("blue");
1182     QCOMPARE(rect->color(),QColor("blue"));
1183     QCOMPARE(rect->radius(),qreal(5));
1184
1185     rectPrivate->setState("");
1186     QCOMPARE(rect->color(),QColor("red"));
1187     QCOMPARE(rect->radius(),qreal(0));
1188
1189     QQuickPropertyChanges *pc = rect->findChild<QQuickPropertyChanges*>("pc1");
1190     QVERIFY(pc != 0);
1191     delete pc;
1192
1193     QQuickState *state = rect->findChild<QQuickState*>();
1194     QVERIFY(state != 0);
1195     qmlExecuteDeferred(state);
1196     QCOMPARE(state->operationCount(), 1);
1197
1198     rectPrivate->setState("blue");
1199     QCOMPARE(rect->color(),QColor("red"));
1200     QCOMPARE(rect->radius(),qreal(5));
1201
1202     delete rect;
1203 }
1204
1205 void tst_qquickstates::deletingState()
1206 {
1207     QQmlEngine engine;
1208
1209     QQmlComponent rectComponent(&engine, testFileUrl("deletingState.qml"));
1210     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1211     QVERIFY(rect != 0);
1212
1213     QQuickStateGroup *sg = rect->findChild<QQuickStateGroup*>();
1214     QVERIFY(sg != 0);
1215     QVERIFY(sg->findState("blue") != 0);
1216
1217     sg->setState("blue");
1218     QCOMPARE(rect->color(),QColor("blue"));
1219
1220     sg->setState("");
1221     QCOMPARE(rect->color(),QColor("red"));
1222
1223     QQuickState *state = rect->findChild<QQuickState*>();
1224     QVERIFY(state != 0);
1225     delete state;
1226
1227     QVERIFY(sg->findState("blue") == 0);
1228
1229     //### should we warn that state doesn't exist
1230     sg->setState("blue");
1231     QCOMPARE(rect->color(),QColor("red"));
1232
1233     delete rect;
1234 }
1235
1236 void tst_qquickstates::tempState()
1237 {
1238     QQmlEngine engine;
1239
1240     QQmlComponent rectComponent(&engine, testFileUrl("legalTempState.qml"));
1241     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1242     QVERIFY(rect != 0);
1243     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1244     QTest::ignoreMessage(QtDebugMsg, "entering placed");
1245     QTest::ignoreMessage(QtDebugMsg, "entering idle");
1246     rectPrivate->setState("placed");
1247     QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
1248 }
1249
1250 void tst_qquickstates::illegalTempState()
1251 {
1252     QQmlEngine engine;
1253
1254     QQmlComponent rectComponent(&engine, testFileUrl("illegalTempState.qml"));
1255     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1256     QVERIFY(rect != 0);
1257     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1258     QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
1259     rectPrivate->setState("placed");
1260     QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
1261 }
1262
1263 void tst_qquickstates::nonExistantProperty()
1264 {
1265     QQmlEngine engine;
1266
1267     QQmlComponent rectComponent(&engine, testFileUrl("nonExistantProp.qml"));
1268     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1269     QVERIFY(rect != 0);
1270     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1271     QTest::ignoreMessage(QtWarningMsg, fullDataPath("nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1272     rectPrivate->setState("blue");
1273     QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
1274 }
1275
1276 void tst_qquickstates::reset()
1277 {
1278     QQmlEngine engine;
1279
1280     QQmlComponent c(&engine, testFileUrl("reset.qml"));
1281     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1282     QVERIFY(rect != 0);
1283
1284     QQuickImage *image = rect->findChild<QQuickImage*>();
1285     QVERIFY(image != 0);
1286     QCOMPARE(image->width(), qreal(40.));
1287     QCOMPARE(image->height(), qreal(20.));
1288
1289     QQuickItemPrivate::get(rect)->setState("state1");
1290
1291     QCOMPARE(image->width(), 20.0);
1292     QCOMPARE(image->height(), qreal(20.));
1293
1294     delete rect;
1295 }
1296
1297 void tst_qquickstates::illegalObjectCreation()
1298 {
1299     QQmlEngine engine;
1300
1301     QQmlComponent component(&engine, testFileUrl("illegalObj.qml"));
1302     QList<QQmlError> errors = component.errors();
1303     QVERIFY(errors.count() == 1);
1304     const QQmlError &error = errors.at(0);
1305     QCOMPARE(error.line(), 9);
1306     QCOMPARE(error.column(), 23);
1307     QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
1308 }
1309
1310 void tst_qquickstates::whenOrdering()
1311 {
1312     QQmlEngine engine;
1313
1314     QQmlComponent c(&engine, testFileUrl("whenOrdering.qml"));
1315     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1316     QVERIFY(rect != 0);
1317     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1318
1319     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1320     rect->setProperty("condition2", true);
1321     QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
1322     rect->setProperty("condition1", true);
1323     QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1324     rect->setProperty("condition2", false);
1325     QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1326     rect->setProperty("condition2", true);
1327     QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1328     rect->setProperty("condition1", false);
1329     rect->setProperty("condition2", false);
1330     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1331 }
1332
1333 void tst_qquickstates::urlResolution()
1334 {
1335     QQmlEngine engine;
1336
1337     QQmlComponent c(&engine, testFileUrl("urlResolution.qml"));
1338     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1339     QVERIFY(rect != 0);
1340
1341     QQuickItem *myType = rect->findChild<QQuickItem*>("MyType");
1342     QQuickImage *image1 = rect->findChild<QQuickImage*>("image1");
1343     QQuickImage *image2 = rect->findChild<QQuickImage*>("image2");
1344     QQuickImage *image3 = rect->findChild<QQuickImage*>("image3");
1345     QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
1346
1347     QQuickItemPrivate::get(myType)->setState("SetImageState");
1348     QUrl resolved = testFileUrl("Implementation/images/qt-logo.png");
1349     QCOMPARE(image1->source(), resolved);
1350     QCOMPARE(image2->source(), resolved);
1351     QCOMPARE(image3->source(), resolved);
1352
1353     delete rect;
1354 }
1355
1356 void tst_qquickstates::unnamedWhen()
1357 {
1358     QQmlEngine engine;
1359
1360     QQmlComponent c(&engine, testFileUrl("unnamedWhen.qml"));
1361     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1362     QVERIFY(rect != 0);
1363     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1364
1365     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1366     QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1367     rect->setProperty("triggerState", true);
1368     QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1369     QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1370     rect->setProperty("triggerState", false);
1371     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1372     QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1373 }
1374
1375 void tst_qquickstates::returnToBase()
1376 {
1377     QQmlEngine engine;
1378
1379     QQmlComponent c(&engine, testFileUrl("returnToBase.qml"));
1380     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1381     QVERIFY(rect != 0);
1382     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1383
1384     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1385     QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1386     rect->setProperty("triggerState", true);
1387     QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1388     QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1389     rect->setProperty("triggerState", false);
1390     QCOMPARE(rectPrivate->state(), QLatin1String(""));
1391     QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
1392 }
1393
1394 //QTBUG-12559
1395 void tst_qquickstates::extendsBug()
1396 {
1397     QQmlEngine engine;
1398
1399     QQmlComponent c(&engine, testFileUrl("extendsBug.qml"));
1400     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1401     QVERIFY(rect != 0);
1402     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1403     QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
1404
1405     rectPrivate->setState("b");
1406     QCOMPARE(greenRect->x(), qreal(100));
1407     QCOMPARE(greenRect->y(), qreal(100));
1408 }
1409
1410 void tst_qquickstates::editProperties()
1411 {
1412     QQmlEngine engine;
1413
1414     QQmlComponent c(&engine, testFileUrl("editProperties.qml"));
1415     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1416     QVERIFY(rect != 0);
1417
1418     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1419
1420     QQuickStateGroup *stateGroup = rectPrivate->_states();
1421     QVERIFY(stateGroup != 0);
1422     qmlExecuteDeferred(stateGroup);
1423
1424     QQuickState *blueState = stateGroup->findState("blue");
1425     QVERIFY(blueState != 0);
1426     qmlExecuteDeferred(blueState);
1427
1428     QQuickPropertyChanges *propertyChangesBlue = qobject_cast<QQuickPropertyChanges*>(blueState->operationAt(0));
1429     QVERIFY(propertyChangesBlue != 0);
1430
1431     QQuickState *greenState = stateGroup->findState("green");
1432     QVERIFY(greenState != 0);
1433     qmlExecuteDeferred(greenState);
1434
1435     QQuickPropertyChanges *propertyChangesGreen = qobject_cast<QQuickPropertyChanges*>(greenState->operationAt(0));
1436     QVERIFY(propertyChangesGreen != 0);
1437
1438     QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
1439     QVERIFY(childRect != 0);
1440     QCOMPARE(childRect->width(), qreal(402));
1441     QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1442     QCOMPARE(childRect->height(), qreal(200));
1443
1444     rectPrivate->setState("blue");
1445     QCOMPARE(childRect->width(), qreal(50));
1446     QCOMPARE(childRect->height(), qreal(40));
1447     QVERIFY(!QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1448     QVERIFY(blueState->bindingInRevertList(childRect, "width"));
1449
1450
1451     rectPrivate->setState("green");
1452     QCOMPARE(childRect->width(), qreal(200));
1453     QCOMPARE(childRect->height(), qreal(100));
1454     QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1455
1456
1457     rectPrivate->setState("");
1458
1459
1460     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1461     QVERIFY(propertyChangesBlue->containsValue("width"));
1462     QVERIFY(!propertyChangesBlue->containsProperty("x"));
1463     QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1464     QVERIFY(!propertyChangesBlue->value("x").isValid());
1465
1466     propertyChangesBlue->changeValue("width", 60);
1467     QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1468     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1469
1470
1471     propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1472     QVERIFY(!propertyChangesBlue->containsValue("width"));
1473     QVERIFY(propertyChangesBlue->containsExpression("width"));
1474     QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1475     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1476
1477     propertyChangesBlue->changeValue("width", 50);
1478     QVERIFY(propertyChangesBlue->containsValue("width"));
1479     QVERIFY(!propertyChangesBlue->containsExpression("width"));
1480     QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1481     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1482
1483     QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1484     rectPrivate->setState("blue");
1485     QCOMPARE(childRect->width(), qreal(50));
1486     QCOMPARE(childRect->height(), qreal(40));
1487
1488     propertyChangesBlue->changeValue("width", 60);
1489     QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1490     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1491     QCOMPARE(childRect->width(), qreal(60));
1492     QVERIFY(!QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1493
1494     propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1495     QVERIFY(!propertyChangesBlue->containsValue("width"));
1496     QVERIFY(propertyChangesBlue->containsExpression("width"));
1497     QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1498     QCOMPARE(propertyChangesBlue->actions().length(), 2);
1499     QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1500     QCOMPARE(childRect->width(), qreal(200));
1501
1502     propertyChangesBlue->changeValue("width", 50);
1503     QCOMPARE(childRect->width(), qreal(50));
1504
1505     rectPrivate->setState("");
1506     QCOMPARE(childRect->width(), qreal(402));
1507     QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1508
1509     QCOMPARE(propertyChangesGreen->actions().length(), 2);
1510     rectPrivate->setState("green");
1511     QCOMPARE(childRect->width(), qreal(200));
1512     QCOMPARE(childRect->height(), qreal(100));
1513     QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1514     QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1515     QCOMPARE(propertyChangesGreen->actions().length(), 2);
1516
1517
1518     propertyChangesGreen->removeProperty("height");
1519     QVERIFY(!QQmlPropertyPrivate::binding(QQmlProperty(childRect, "height")));
1520     QCOMPARE(childRect->height(), qreal(200));
1521
1522     QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1523     QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
1524     propertyChangesGreen->removeProperty("width");
1525     QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1526     QCOMPARE(childRect->width(), qreal(402));
1527     QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
1528     QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
1529
1530     propertyChangesBlue->removeProperty("width");
1531     QCOMPARE(childRect->width(), qreal(402));
1532
1533     rectPrivate->setState("blue");
1534     QCOMPARE(childRect->width(), qreal(402));
1535     QCOMPARE(childRect->height(), qreal(40));
1536 }
1537
1538 void tst_qquickstates::QTBUG_14830()
1539 {
1540     QQmlEngine engine;
1541
1542     QQmlComponent c(&engine, testFileUrl("QTBUG-14830.qml"));
1543     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1544     QVERIFY(rect != 0);
1545     QQuickItem *item = rect->findChild<QQuickItem*>("area");
1546
1547     QCOMPARE(item->width(), qreal(171));
1548 }
1549
1550 void tst_qquickstates::avoidFastForward()
1551 {
1552     QQmlEngine engine;
1553
1554     //shouldn't fast forward if there isn't a transition
1555     QQmlComponent c(&engine, testFileUrl("avoidFastForward.qml"));
1556     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1557     QVERIFY(rect != 0);
1558
1559     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1560     rectPrivate->setState("a");
1561     QCOMPARE(rect->property("updateCount").toInt(), 1);
1562 }
1563
1564 //QTBUG-22583
1565 void tst_qquickstates::revertListBug()
1566 {
1567     QQmlEngine engine;
1568
1569     QQmlComponent c(&engine, testFileUrl("revertListBug.qml"));
1570     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1571     QVERIFY(rect != 0);
1572
1573     QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
1574     QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
1575     QQuickItem *origParent1 = rect->findChild<QQuickItem*>("originalParent1");
1576     QQuickItem *origParent2 = rect->findChild<QQuickItem*>("originalParent2");
1577     QQuickItem *newParent = rect->findChild<QQuickItem*>("newParent");
1578
1579     QCOMPARE(rect1->parentItem(), origParent1);
1580     QCOMPARE(rect2->parentItem(), origParent2);
1581
1582     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1583     rectPrivate->setState("reparented");
1584
1585     QCOMPARE(rect1->parentItem(), newParent);
1586     QCOMPARE(rect2->parentItem(), origParent2);
1587
1588     rectPrivate->setState("");
1589
1590     QCOMPARE(rect1->parentItem(), origParent1);
1591     QCOMPARE(rect2->parentItem(), origParent2);
1592
1593     QMetaObject::invokeMethod(rect, "switchTargetItem");
1594
1595     rectPrivate->setState("reparented");
1596
1597     QCOMPARE(rect1->parentItem(), origParent1);
1598     QCOMPARE(rect2->parentItem(), newParent);
1599
1600     rectPrivate->setState("");
1601
1602     QCOMPARE(rect1->parentItem(), origParent1);
1603     QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
1604 }
1605
1606 QTEST_MAIN(tst_qquickstates)
1607
1608 #include "tst_qquickstates.moc"