1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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"
55 class MyAttached : public QObject
58 Q_PROPERTY(int foo READ foo WRITE setFoo)
60 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
62 int foo() const { return m_foo; }
63 void setFoo(int f) { m_foo = f; }
69 class MyRect : public QQuickRectangle
72 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
76 void doSomething() { emit didSomething(); }
78 int propertyWithNotify() const { return m_prop; }
79 void setPropertyWithNotify(int i) { m_prop = i; emit oddlyNamedNotifySignal(); }
81 static MyAttached *qmlAttachedProperties(QObject *o) {
82 return new MyAttached(o);
86 void oddlyNamedNotifySignal();
92 QML_DECLARE_TYPE(MyRect)
93 QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
95 class tst_qquickstates : public QQmlDataTest
102 QByteArray fullDataPath(const QString &path) const;
108 void attachedPropertyChanges();
109 void basicExtension();
111 void signalOverride();
112 void signalOverrideCrash();
113 void signalOverrideCrash2();
114 void signalOverrideCrash3();
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();
129 void restoreEntryValues();
130 void explicitChanges();
131 void propertyErrors();
132 void incorrectRestoreBug();
133 void autoStateAtStartupRestoreBug();
134 void deletingChange();
135 void deletingState();
137 void illegalTempState();
138 void nonExistantProperty();
140 void illegalObjectCreation();
142 void urlResolution();
146 void editProperties();
148 void avoidFastForward();
149 void revertListBug();
152 void tst_qquickstates::initTestCase()
154 QQmlDataTest::initTestCase();
155 qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
158 QByteArray tst_qquickstates::fullDataPath(const QString &path) const
160 return testFileUrl(path).toString().toUtf8();
163 void tst_qquickstates::basicChanges()
168 QQmlComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
169 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
170 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
173 QCOMPARE(rect->color(),QColor("red"));
175 rectPrivate->setState("blue");
176 QCOMPARE(rect->color(),QColor("blue"));
178 rectPrivate->setState("");
179 QCOMPARE(rect->color(),QColor("red"));
183 QQmlComponent rectComponent(&engine, testFileUrl("basicChanges2.qml"));
184 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
185 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
188 QCOMPARE(rect->color(),QColor("red"));
190 rectPrivate->setState("blue");
191 QCOMPARE(rect->color(),QColor("blue"));
193 rectPrivate->setState("green");
194 QCOMPARE(rect->color(),QColor("green"));
196 rectPrivate->setState("");
197 QCOMPARE(rect->color(),QColor("red"));
199 rectPrivate->setState("green");
200 QCOMPARE(rect->color(),QColor("green"));
204 QQmlComponent rectComponent(&engine, testFileUrl("basicChanges3.qml"));
205 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
206 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
209 QCOMPARE(rect->color(),QColor("red"));
210 QCOMPARE(rect->border()->width(),1.0);
212 rectPrivate->setState("blue");
213 QCOMPARE(rect->color(),QColor("blue"));
214 QCOMPARE(rect->border()->width(),1.0);
216 rectPrivate->setState("bordered");
217 QCOMPARE(rect->color(),QColor("red"));
218 QCOMPARE(rect->border()->width(),2.0);
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)
225 rectPrivate->setState("bordered");
226 QCOMPARE(rect->color(),QColor("red"));
227 QCOMPARE(rect->border()->width(),2.0);
229 rectPrivate->setState("blue");
230 QCOMPARE(rect->color(),QColor("blue"));
231 QCOMPARE(rect->border()->width(),1.0);
236 // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
237 // signal using 'onPropertyWithNotifyChanged' even though the signal name is
238 // actually 'oddlyNamedNotifySignal'
240 QQmlComponent component(&engine, testFileUrl("basicChanges4.qml"));
241 QVERIFY(component.isReady());
243 MyRect *rect = qobject_cast<MyRect*>(component.create());
246 QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
247 QVERIFY(prop.hasNotifySignal());
248 QString notifySignal = QByteArray(prop.notifySignal().signature());
249 QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
251 QCOMPARE(rect->color(), QColor(Qt::red));
253 rect->setPropertyWithNotify(100);
254 QCOMPARE(rect->color(), QColor(Qt::blue));
258 void tst_qquickstates::attachedPropertyChanges()
262 QQmlComponent component(&engine, testFileUrl("attachedPropertyChanges.qml"));
263 QVERIFY(component.isReady());
265 QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
267 QCOMPARE(item->width(), 50.0);
269 // Ensure attached property has been changed
270 QObject *attObj = qmlAttachedPropertiesObject<MyRect>(item, false);
273 MyAttached *att = qobject_cast<MyAttached*>(attObj);
276 QCOMPARE(att->foo(), 1);
279 void tst_qquickstates::basicExtension()
284 QQmlComponent rectComponent(&engine, testFileUrl("basicExtension.qml"));
285 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
286 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
289 QCOMPARE(rect->color(),QColor("red"));
290 QCOMPARE(rect->border()->width(),1.0);
292 rectPrivate->setState("blue");
293 QCOMPARE(rect->color(),QColor("blue"));
294 QCOMPARE(rect->border()->width(),1.0);
296 rectPrivate->setState("bordered");
297 QCOMPARE(rect->color(),QColor("blue"));
298 QCOMPARE(rect->border()->width(),2.0);
300 rectPrivate->setState("blue");
301 QCOMPARE(rect->color(),QColor("blue"));
302 QCOMPARE(rect->border()->width(),1.0);
304 rectPrivate->setState("");
305 QCOMPARE(rect->color(),QColor("red"));
306 QCOMPARE(rect->border()->width(),1.0);
308 rectPrivate->setState("bordered");
309 QCOMPARE(rect->color(),QColor("blue"));
310 QCOMPARE(rect->border()->width(),2.0);
312 rectPrivate->setState("");
313 QCOMPARE(rect->color(),QColor("red"));
314 QCOMPARE(rect->border()->width(),1.0);
318 QQmlComponent rectComponent(&engine, testFileUrl("fakeExtension.qml"));
319 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
320 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
323 QCOMPARE(rect->color(),QColor("red"));
325 rectPrivate->setState("blue");
326 QCOMPARE(rect->color(),QColor("blue"));
328 rectPrivate->setState("green");
329 QCOMPARE(rect->color(),QColor("green"));
331 rectPrivate->setState("blue");
332 QCOMPARE(rect->color(),QColor("blue"));
334 rectPrivate->setState("green");
335 QCOMPARE(rect->color(),QColor("green"));
337 rectPrivate->setState("");
338 QCOMPARE(rect->color(),QColor("red"));
340 rectPrivate->setState("green");
341 QCOMPARE(rect->color(),QColor("green"));
345 void tst_qquickstates::basicBinding()
350 QQmlComponent rectComponent(&engine, testFileUrl("basicBinding.qml"));
351 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
352 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
355 QCOMPARE(rect->color(),QColor("red"));
357 rectPrivate->setState("blue");
358 QCOMPARE(rect->color(),QColor("blue"));
360 rectPrivate->setState("");
361 QCOMPARE(rect->color(),QColor("red"));
363 rectPrivate->setState("blue");
364 QCOMPARE(rect->color(),QColor("blue"));
365 rect->setProperty("sourceColor", QColor("green"));
366 QCOMPARE(rect->color(),QColor("green"));
368 rectPrivate->setState("");
369 QCOMPARE(rect->color(),QColor("red"));
370 rect->setProperty("sourceColor", QColor("yellow"));
371 QCOMPARE(rect->color(),QColor("red"));
373 rectPrivate->setState("blue");
374 QCOMPARE(rect->color(),QColor("yellow"));
378 QQmlComponent rectComponent(&engine, testFileUrl("basicBinding2.qml"));
379 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
380 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
383 QCOMPARE(rect->color(),QColor("red"));
385 rectPrivate->setState("blue");
386 QCOMPARE(rect->color(),QColor("blue"));
388 rectPrivate->setState("");
389 QCOMPARE(rect->color(),QColor("red"));
391 rectPrivate->setState("blue");
392 QCOMPARE(rect->color(),QColor("blue"));
393 rect->setProperty("sourceColor", QColor("green"));
394 QCOMPARE(rect->color(),QColor("blue"));
396 rectPrivate->setState("");
397 QCOMPARE(rect->color(),QColor("green"));
398 rect->setProperty("sourceColor", QColor("yellow"));
399 QCOMPARE(rect->color(),QColor("yellow"));
401 rectPrivate->setState("blue");
402 QCOMPARE(rect->color(),QColor("blue"));
404 rectPrivate->setState("");
405 QCOMPARE(rect->color(),QColor("yellow"));
409 QQmlComponent rectComponent(&engine, testFileUrl("basicBinding3.qml"));
410 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
411 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
414 QCOMPARE(rect->color(),QColor("red"));
415 rect->setProperty("sourceColor", QColor("green"));
416 QCOMPARE(rect->color(),QColor("green"));
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"));
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"));
434 QQmlComponent rectComponent(&engine, testFileUrl("basicBinding4.qml"));
435 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
436 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
439 QCOMPARE(rect->color(),QColor("red"));
441 rectPrivate->setState("blue");
442 QCOMPARE(rect->color(),QColor("blue"));
443 rect->setProperty("sourceColor", QColor("yellow"));
444 QCOMPARE(rect->color(),QColor("yellow"));
446 rectPrivate->setState("green");
447 QCOMPARE(rect->color(),QColor("green"));
448 rect->setProperty("sourceColor", QColor("purple"));
449 QCOMPARE(rect->color(),QColor("green"));
451 rectPrivate->setState("blue");
452 QCOMPARE(rect->color(),QColor("purple"));
454 rectPrivate->setState("green");
455 QCOMPARE(rect->color(),QColor("green"));
457 rectPrivate->setState("");
458 QCOMPARE(rect->color(),QColor("red"));
462 void tst_qquickstates::signalOverride()
467 QQmlComponent rectComponent(&engine, testFileUrl("signalOverride.qml"));
468 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
471 QCOMPARE(rect->color(),QColor("red"));
473 QCOMPARE(rect->color(),QColor("blue"));
475 QQuickItemPrivate::get(rect)->setState("green");
477 QCOMPARE(rect->color(),QColor("green"));
481 QQmlComponent rectComponent(&engine, testFileUrl("signalOverride2.qml"));
482 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
485 QCOMPARE(rect->color(),QColor("white"));
487 QCOMPARE(rect->color(),QColor("blue"));
489 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("extendedRect"));
490 QQuickItemPrivate::get(innerRect)->setState("green");
492 QCOMPARE(rect->color(),QColor("blue"));
493 QCOMPARE(innerRect->color(),QColor("green"));
494 QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
498 void tst_qquickstates::signalOverrideCrash()
502 QQmlComponent rectComponent(&engine, testFileUrl("signalOverrideCrash.qml"));
503 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
506 QQuickItemPrivate::get(rect)->setState("overridden");
510 void tst_qquickstates::signalOverrideCrash2()
514 QQmlComponent rectComponent(&engine, testFileUrl("signalOverrideCrash2.qml"));
515 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
518 QQuickItemPrivate::get(rect)->setState("state1");
519 QQuickItemPrivate::get(rect)->setState("state2");
520 QQuickItemPrivate::get(rect)->setState("state1");
525 void tst_qquickstates::signalOverrideCrash3()
529 QQmlComponent rectComponent(&engine, testFileUrl("signalOverrideCrash3.qml"));
530 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
533 QQuickItemPrivate::get(rect)->setState("state1");
534 QQuickItemPrivate::get(rect)->setState("");
535 QQuickItemPrivate::get(rect)->setState("state2");
536 QQuickItemPrivate::get(rect)->setState("");
541 void tst_qquickstates::parentChange()
546 QQmlComponent rectComponent(&engine, testFileUrl("parentChange1.qml"));
547 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
550 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
551 QVERIFY(innerRect != 0);
553 QQmlListReference list(rect, "states");
554 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
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);
563 QCOMPARE(pChange->parent(), nParent);
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));
573 QQmlComponent rectComponent(&engine, testFileUrl("parentChange2.qml"));
574 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
576 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
577 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
578 QVERIFY(innerRect != 0);
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));
588 QQmlComponent rectComponent(&engine, testFileUrl("parentChange3.qml"));
589 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
591 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
592 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
593 QVERIFY(innerRect != 0);
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));
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));
610 QQmlComponent rectComponent(&engine, testFileUrl("parentChange6.qml"));
611 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
614 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
615 QVERIFY(innerRect != 0);
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));
625 void tst_qquickstates::parentChangeErrors()
630 QQmlComponent rectComponent(&engine, testFileUrl("parentChange4.qml"));
631 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
634 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
635 QVERIFY(innerRect != 0);
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));
646 QQmlComponent rectComponent(&engine, testFileUrl("parentChange5.qml"));
647 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
650 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
651 QVERIFY(innerRect != 0);
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));
662 void tst_qquickstates::anchorChanges()
666 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
667 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
669 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
671 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
672 QVERIFY(innerRect != 0);
674 QQmlListReference list(rect, "states");
675 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
678 qmlExecuteDeferred(state);
679 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
680 QVERIFY(aChanges != 0);
682 QCOMPARE(aChanges->anchors()->left().script(), QLatin1String("undefined"));
683 QCOMPARE(aChanges->anchors()->right().script(), QLatin1String("container.right"));
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);
692 rectPrivate->setState("");
693 QCOMPARE(innerRect->x(), qreal(5));
698 void tst_qquickstates::anchorChanges2()
702 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
703 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
705 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
707 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
708 QVERIFY(innerRect != 0);
710 rectPrivate->setState("right");
711 QCOMPARE(innerRect->x(), qreal(150));
713 rectPrivate->setState("");
714 QCOMPARE(innerRect->x(), qreal(5));
719 void tst_qquickstates::anchorChanges3()
723 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
724 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
726 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
728 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
729 QVERIFY(innerRect != 0);
731 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
732 QVERIFY(leftGuideline != 0);
734 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
735 QVERIFY(bottomGuideline != 0);
737 QQmlListReference list(rect, "states");
738 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
741 qmlExecuteDeferred(state);
742 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
743 QVERIFY(aChanges != 0);
745 QCOMPARE(aChanges->anchors()->top().script(), QLatin1String("container.top"));
746 QCOMPARE(aChanges->anchors()->bottom().script(), QLatin1String("bottomGuideline.bottom"));
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);
759 QCOMPARE(innerRect->x(), qreal(10));
760 QCOMPARE(innerRect->y(), qreal(0));
761 QCOMPARE(innerRect->width(), qreal(190));
762 QCOMPARE(innerRect->height(), qreal(150));
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));
773 void tst_qquickstates::anchorChanges4()
777 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges4.qml"));
778 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
781 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
782 QVERIFY(innerRect != 0);
784 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
785 QVERIFY(leftGuideline != 0);
787 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
788 QVERIFY(bottomGuideline != 0);
790 QQmlListReference list(rect, "states");
791 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
794 qmlExecuteDeferred(state);
795 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
796 QVERIFY(aChanges != 0);
798 QCOMPARE(aChanges->anchors()->horizontalCenter().script(), QLatin1String("bottomGuideline.horizontalCenter"));
799 QCOMPARE(aChanges->anchors()->verticalCenter().script(), QLatin1String("leftGuideline.verticalCenter"));
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);
811 void tst_qquickstates::anchorChanges5()
815 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges5.qml"));
816 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
819 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
820 QVERIFY(innerRect != 0);
822 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
823 QVERIFY(leftGuideline != 0);
825 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
826 QVERIFY(bottomGuideline != 0);
828 QQmlListReference list(rect, "states");
829 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
832 qmlExecuteDeferred(state);
833 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
834 QVERIFY(aChanges != 0);
836 QCOMPARE(aChanges->anchors()->baseline().script(), QLatin1String("leftGuideline.baseline"));
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);
848 void mirrorAnchors(QQuickItem *item) {
849 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
850 itemPrivate->setLayoutMirror(true);
853 qreal offsetRTL(QQuickItem *anchorItem, QQuickItem *item) {
854 return anchorItem->width()+2*anchorItem->x()-item->width();
857 void tst_qquickstates::anchorChangesRTL()
861 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
862 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
864 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
866 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
867 QVERIFY(innerRect != 0);
868 mirrorAnchors(innerRect);
870 QQmlListReference list(rect, "states");
871 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
874 qmlExecuteDeferred(state);
875 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
876 QVERIFY(aChanges != 0);
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);
885 rectPrivate->setState("");
886 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
891 void tst_qquickstates::anchorChangesRTL2()
895 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
896 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
898 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
900 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
901 QVERIFY(innerRect != 0);
902 mirrorAnchors(innerRect);
904 rectPrivate->setState("right");
905 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
907 rectPrivate->setState("");
908 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
913 void tst_qquickstates::anchorChangesRTL3()
917 QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
918 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
920 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
922 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
923 QVERIFY(innerRect != 0);
924 mirrorAnchors(innerRect);
926 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
927 QVERIFY(leftGuideline != 0);
929 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
930 QVERIFY(bottomGuideline != 0);
932 QQmlListReference list(rect, "states");
933 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
936 qmlExecuteDeferred(state);
937 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
938 QVERIFY(aChanges != 0);
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);
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));
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));
968 void tst_qquickstates::anchorChangesCrash()
972 QQmlComponent rectComponent(&engine, testFileUrl("anchorChangesCrash.qml"));
973 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
976 QQuickItemPrivate::get(rect)->setState("reanchored");
982 void tst_qquickstates::anchorRewindBug()
984 QQuickView *view = new QQuickView;
985 view->setSource(testFileUrl("anchorRewindBug.qml"));
988 view->requestActivateWindow();
990 QTest::qWaitForWindowShown(view);
992 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
995 QQuickItem * column = rect->findChild<QQuickItem*>("column");
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");
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);
1009 QQuickItemPrivate::get(rect)->setState("");
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);
1021 void tst_qquickstates::anchorRewindBug2()
1025 QQmlComponent rectComponent(&engine, testFileUrl("anchorRewindBug2.qml"));
1026 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1029 QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
1031 QVERIFY(mover != 0);
1032 QCOMPARE(mover->y(), qreal(0.0));
1033 QCOMPARE(mover->width(), qreal(50.0));
1035 QQuickItemPrivate::get(rect)->setState("anchored");
1036 QCOMPARE(mover->y(), qreal(250.0));
1037 QCOMPARE(mover->width(), qreal(200.0));
1039 QQuickItemPrivate::get(rect)->setState("");
1040 QCOMPARE(mover->y(), qreal(0.0));
1041 QCOMPARE(mover->width(), qreal(50.0));
1046 void tst_qquickstates::script()
1051 QQmlComponent rectComponent(&engine, testFileUrl("script.qml"));
1052 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1054 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1055 QCOMPARE(rect->color(),QColor("red"));
1057 rectPrivate->setState("blue");
1058 QCOMPARE(rect->color(),QColor("blue"));
1060 rectPrivate->setState("");
1061 QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
1065 void tst_qquickstates::restoreEntryValues()
1069 QQmlComponent rectComponent(&engine, testFileUrl("restoreEntryValues.qml"));
1070 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1072 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1073 QCOMPARE(rect->color(),QColor("red"));
1075 rectPrivate->setState("blue");
1076 QCOMPARE(rect->color(),QColor("blue"));
1078 rectPrivate->setState("");
1079 QCOMPARE(rect->color(),QColor("blue"));
1082 void tst_qquickstates::explicitChanges()
1086 QQmlComponent rectComponent(&engine, testFileUrl("explicit.qml"));
1087 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1089 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1090 QQmlListReference list(rect, "states");
1091 QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
1092 QVERIFY(state != 0);
1094 qmlExecuteDeferred(state);
1095 QQuickPropertyChanges *changes = qobject_cast<QQuickPropertyChanges*>(rect->findChild<QQuickPropertyChanges*>("changes"));
1096 QVERIFY(changes != 0);
1097 QVERIFY(changes->isExplicit());
1099 QCOMPARE(rect->color(),QColor("red"));
1101 rectPrivate->setState("blue");
1102 QCOMPARE(rect->color(),QColor("blue"));
1104 rect->setProperty("sourceColor", QColor("green"));
1105 QCOMPARE(rect->color(),QColor("blue"));
1107 rectPrivate->setState("");
1108 QCOMPARE(rect->color(),QColor("red"));
1109 rect->setProperty("sourceColor", QColor("yellow"));
1110 QCOMPARE(rect->color(),QColor("red"));
1112 rectPrivate->setState("blue");
1113 QCOMPARE(rect->color(),QColor("yellow"));
1116 void tst_qquickstates::propertyErrors()
1119 QQmlComponent rectComponent(&engine, testFileUrl("propertyErrors.qml"));
1120 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1123 QCOMPARE(rect->color(),QColor("red"));
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");
1130 void tst_qquickstates::incorrectRestoreBug()
1134 QQmlComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
1135 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1137 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1138 QCOMPARE(rect->color(),QColor("red"));
1140 rectPrivate->setState("blue");
1141 QCOMPARE(rect->color(),QColor("blue"));
1143 rectPrivate->setState("");
1144 QCOMPARE(rect->color(),QColor("red"));
1146 // make sure if we change the base state value, we then restore to it correctly
1147 rect->setColor(QColor("green"));
1149 rectPrivate->setState("blue");
1150 QCOMPARE(rect->color(),QColor("blue"));
1152 rectPrivate->setState("");
1153 QCOMPARE(rect->color(),QColor("green"));
1156 void tst_qquickstates::autoStateAtStartupRestoreBug()
1160 QQmlComponent component(&engine, testFileUrl("autoStateAtStartupRestoreBug.qml"));
1161 QObject *obj = component.create();
1164 QCOMPARE(obj->property("test").toInt(), 3);
1166 obj->setProperty("input", 2);
1168 QCOMPARE(obj->property("test").toInt(), 9);
1173 void tst_qquickstates::deletingChange()
1177 QQmlComponent rectComponent(&engine, testFileUrl("deleting.qml"));
1178 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1180 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1181 rectPrivate->setState("blue");
1182 QCOMPARE(rect->color(),QColor("blue"));
1183 QCOMPARE(rect->radius(),qreal(5));
1185 rectPrivate->setState("");
1186 QCOMPARE(rect->color(),QColor("red"));
1187 QCOMPARE(rect->radius(),qreal(0));
1189 QQuickPropertyChanges *pc = rect->findChild<QQuickPropertyChanges*>("pc1");
1193 QQuickState *state = rect->findChild<QQuickState*>();
1194 QVERIFY(state != 0);
1195 qmlExecuteDeferred(state);
1196 QCOMPARE(state->operationCount(), 1);
1198 rectPrivate->setState("blue");
1199 QCOMPARE(rect->color(),QColor("red"));
1200 QCOMPARE(rect->radius(),qreal(5));
1205 void tst_qquickstates::deletingState()
1209 QQmlComponent rectComponent(&engine, testFileUrl("deletingState.qml"));
1210 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1213 QQuickStateGroup *sg = rect->findChild<QQuickStateGroup*>();
1215 QVERIFY(sg->findState("blue") != 0);
1217 sg->setState("blue");
1218 QCOMPARE(rect->color(),QColor("blue"));
1221 QCOMPARE(rect->color(),QColor("red"));
1223 QQuickState *state = rect->findChild<QQuickState*>();
1224 QVERIFY(state != 0);
1227 QVERIFY(sg->findState("blue") == 0);
1229 //### should we warn that state doesn't exist
1230 sg->setState("blue");
1231 QCOMPARE(rect->color(),QColor("red"));
1236 void tst_qquickstates::tempState()
1240 QQmlComponent rectComponent(&engine, testFileUrl("legalTempState.qml"));
1241 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
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"));
1250 void tst_qquickstates::illegalTempState()
1254 QQmlComponent rectComponent(&engine, testFileUrl("illegalTempState.qml"));
1255 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
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"));
1263 void tst_qquickstates::nonExistantProperty()
1267 QQmlComponent rectComponent(&engine, testFileUrl("nonExistantProp.qml"));
1268 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
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"));
1276 void tst_qquickstates::reset()
1280 QQmlComponent c(&engine, testFileUrl("reset.qml"));
1281 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1284 QQuickImage *image = rect->findChild<QQuickImage*>();
1285 QVERIFY(image != 0);
1286 QCOMPARE(image->width(), qreal(40.));
1287 QCOMPARE(image->height(), qreal(20.));
1289 QQuickItemPrivate::get(rect)->setState("state1");
1291 QCOMPARE(image->width(), 20.0);
1292 QCOMPARE(image->height(), qreal(20.));
1297 void tst_qquickstates::illegalObjectCreation()
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.");
1310 void tst_qquickstates::whenOrdering()
1314 QQmlComponent c(&engine, testFileUrl("whenOrdering.qml"));
1315 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1317 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
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(""));
1333 void tst_qquickstates::urlResolution()
1337 QQmlComponent c(&engine, testFileUrl("urlResolution.qml"));
1338 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
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);
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);
1356 void tst_qquickstates::unnamedWhen()
1360 QQmlComponent c(&engine, testFileUrl("unnamedWhen.qml"));
1361 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1363 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
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(""));
1375 void tst_qquickstates::returnToBase()
1379 QQmlComponent c(&engine, testFileUrl("returnToBase.qml"));
1380 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1382 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
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"));
1395 void tst_qquickstates::extendsBug()
1399 QQmlComponent c(&engine, testFileUrl("extendsBug.qml"));
1400 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1402 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1403 QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
1405 rectPrivate->setState("b");
1406 QCOMPARE(greenRect->x(), qreal(100));
1407 QCOMPARE(greenRect->y(), qreal(100));
1410 void tst_qquickstates::editProperties()
1414 QQmlComponent c(&engine, testFileUrl("editProperties.qml"));
1415 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1418 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1420 QQuickStateGroup *stateGroup = rectPrivate->_states();
1421 QVERIFY(stateGroup != 0);
1422 qmlExecuteDeferred(stateGroup);
1424 QQuickState *blueState = stateGroup->findState("blue");
1425 QVERIFY(blueState != 0);
1426 qmlExecuteDeferred(blueState);
1428 QQuickPropertyChanges *propertyChangesBlue = qobject_cast<QQuickPropertyChanges*>(blueState->operationAt(0));
1429 QVERIFY(propertyChangesBlue != 0);
1431 QQuickState *greenState = stateGroup->findState("green");
1432 QVERIFY(greenState != 0);
1433 qmlExecuteDeferred(greenState);
1435 QQuickPropertyChanges *propertyChangesGreen = qobject_cast<QQuickPropertyChanges*>(greenState->operationAt(0));
1436 QVERIFY(propertyChangesGreen != 0);
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));
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"));
1451 rectPrivate->setState("green");
1452 QCOMPARE(childRect->width(), qreal(200));
1453 QCOMPARE(childRect->height(), qreal(100));
1454 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1457 rectPrivate->setState("");
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());
1466 propertyChangesBlue->changeValue("width", 60);
1467 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1468 QCOMPARE(propertyChangesBlue->actions().length(), 2);
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);
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);
1483 QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
1484 rectPrivate->setState("blue");
1485 QCOMPARE(childRect->width(), qreal(50));
1486 QCOMPARE(childRect->height(), qreal(40));
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")));
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));
1502 propertyChangesBlue->changeValue("width", 50);
1503 QCOMPARE(childRect->width(), qreal(50));
1505 rectPrivate->setState("");
1506 QCOMPARE(childRect->width(), qreal(402));
1507 QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
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);
1518 propertyChangesGreen->removeProperty("height");
1519 QVERIFY(!QQmlPropertyPrivate::binding(QQmlProperty(childRect, "height")));
1520 QCOMPARE(childRect->height(), qreal(200));
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"));
1530 propertyChangesBlue->removeProperty("width");
1531 QCOMPARE(childRect->width(), qreal(402));
1533 rectPrivate->setState("blue");
1534 QCOMPARE(childRect->width(), qreal(402));
1535 QCOMPARE(childRect->height(), qreal(40));
1538 void tst_qquickstates::QTBUG_14830()
1542 QQmlComponent c(&engine, testFileUrl("QTBUG-14830.qml"));
1543 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1545 QQuickItem *item = rect->findChild<QQuickItem*>("area");
1547 QCOMPARE(item->width(), qreal(171));
1550 void tst_qquickstates::avoidFastForward()
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());
1559 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1560 rectPrivate->setState("a");
1561 QCOMPARE(rect->property("updateCount").toInt(), 1);
1565 void tst_qquickstates::revertListBug()
1569 QQmlComponent c(&engine, testFileUrl("revertListBug.qml"));
1570 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
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");
1579 QCOMPARE(rect1->parentItem(), origParent1);
1580 QCOMPARE(rect2->parentItem(), origParent2);
1582 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1583 rectPrivate->setState("reparented");
1585 QCOMPARE(rect1->parentItem(), newParent);
1586 QCOMPARE(rect2->parentItem(), origParent2);
1588 rectPrivate->setState("");
1590 QCOMPARE(rect1->parentItem(), origParent1);
1591 QCOMPARE(rect2->parentItem(), origParent2);
1593 QMetaObject::invokeMethod(rect, "switchTargetItem");
1595 rectPrivate->setState("reparented");
1597 QCOMPARE(rect1->parentItem(), origParent1);
1598 QCOMPARE(rect2->parentItem(), newParent);
1600 rectPrivate->setState("");
1602 QCOMPARE(rect1->parentItem(), origParent1);
1603 QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
1606 QTEST_MAIN(tst_qquickstates)
1608 #include "tst_qquickstates.moc"