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 <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtQuick/qquickview.h>
45 #include <private/qquickstateoperations_p.h>
46 #include <private/qquickanchors_p_p.h>
47 #include <QtQuick/private/qquickrectangle_p.h>
48 #include <private/qquickimage_p.h>
49 #include <QtQuick/private/qdeclarativepropertychanges_p.h>
50 #include <QtQuick/private/qdeclarativestategroup_p.h>
51 #include <private/qquickitem_p.h>
52 #include <private/qdeclarativeproperty_p.h>
53 #include "../../shared/util.h"
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_qdeclarativestates : public QDeclarativeDataTest
99 tst_qdeclarativestates() {}
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_qdeclarativestates::initTestCase()
154 QDeclarativeDataTest::initTestCase();
155 qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
158 QByteArray tst_qdeclarativestates::fullDataPath(const QString &path) const
160 return testFileUrl(path).toString().toUtf8();
163 void tst_qdeclarativestates::basicChanges()
165 QDeclarativeEngine engine;
168 QDeclarativeComponent 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 QDeclarativeComponent 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 QDeclarativeComponent 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 QDeclarativeComponent 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_qdeclarativestates::attachedPropertyChanges()
260 QDeclarativeEngine engine;
262 QDeclarativeComponent 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_qdeclarativestates::basicExtension()
281 QDeclarativeEngine engine;
284 QDeclarativeComponent 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 QDeclarativeComponent 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_qdeclarativestates::basicBinding()
347 QDeclarativeEngine engine;
350 QDeclarativeComponent 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 QDeclarativeComponent 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 QDeclarativeComponent 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 QDeclarativeComponent 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_qdeclarativestates::signalOverride()
464 QDeclarativeEngine engine;
467 QDeclarativeComponent 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 QDeclarativeComponent 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_qdeclarativestates::signalOverrideCrash()
500 QDeclarativeEngine engine;
502 QDeclarativeComponent rectComponent(&engine, testFileUrl("signalOverrideCrash.qml"));
503 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
506 QQuickItemPrivate::get(rect)->setState("overridden");
510 void tst_qdeclarativestates::signalOverrideCrash2()
512 QDeclarativeEngine engine;
514 QDeclarativeComponent 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_qdeclarativestates::signalOverrideCrash3()
527 QDeclarativeEngine engine;
529 QDeclarativeComponent 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_qdeclarativestates::parentChange()
543 QDeclarativeEngine engine;
546 QDeclarativeComponent 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 QDeclarativeListReference list(rect, "states");
554 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(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 QDeclarativeComponent 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 QDeclarativeComponent 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 QDeclarativeComponent 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_qdeclarativestates::parentChangeErrors()
627 QDeclarativeEngine engine;
630 QDeclarativeComponent 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 QDeclarativeComponent 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_qdeclarativestates::anchorChanges()
664 QDeclarativeEngine engine;
666 QDeclarativeComponent 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 QDeclarativeListReference list(rect, "states");
675 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
678 qmlExecuteDeferred(state);
679 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
680 QVERIFY(aChanges != 0);
682 rectPrivate->setState("right");
683 QCOMPARE(innerRect->x(), qreal(150));
684 QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
685 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
686 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
687 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
689 rectPrivate->setState("");
690 QCOMPARE(innerRect->x(), qreal(5));
695 void tst_qdeclarativestates::anchorChanges2()
697 QDeclarativeEngine engine;
699 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
700 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
702 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
704 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
705 QVERIFY(innerRect != 0);
707 rectPrivate->setState("right");
708 QCOMPARE(innerRect->x(), qreal(150));
710 rectPrivate->setState("");
711 QCOMPARE(innerRect->x(), qreal(5));
716 void tst_qdeclarativestates::anchorChanges3()
718 QDeclarativeEngine engine;
720 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
721 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
723 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
725 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
726 QVERIFY(innerRect != 0);
728 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
729 QVERIFY(leftGuideline != 0);
731 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
732 QVERIFY(bottomGuideline != 0);
734 QDeclarativeListReference list(rect, "states");
735 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
738 qmlExecuteDeferred(state);
739 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
740 QVERIFY(aChanges != 0);
742 rectPrivate->setState("reanchored");
743 QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
744 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
745 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
746 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
747 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
748 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
749 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
750 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
751 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
753 QCOMPARE(innerRect->x(), qreal(10));
754 QCOMPARE(innerRect->y(), qreal(0));
755 QCOMPARE(innerRect->width(), qreal(190));
756 QCOMPARE(innerRect->height(), qreal(150));
758 rectPrivate->setState("");
759 QCOMPARE(innerRect->x(), qreal(0));
760 QCOMPARE(innerRect->y(), qreal(10));
761 QCOMPARE(innerRect->width(), qreal(150));
762 QCOMPARE(innerRect->height(), qreal(190));
767 void tst_qdeclarativestates::anchorChanges4()
769 QDeclarativeEngine engine;
771 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges4.qml"));
772 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
775 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
776 QVERIFY(innerRect != 0);
778 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
779 QVERIFY(leftGuideline != 0);
781 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
782 QVERIFY(bottomGuideline != 0);
784 QDeclarativeListReference list(rect, "states");
785 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
788 qmlExecuteDeferred(state);
789 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
790 QVERIFY(aChanges != 0);
792 QQuickItemPrivate::get(rect)->setState("reanchored");
793 QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
794 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().item);
795 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
796 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QQuickItemPrivate::get(leftGuideline)->verticalCenter().item);
797 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QQuickItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
802 void tst_qdeclarativestates::anchorChanges5()
804 QDeclarativeEngine engine;
806 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges5.qml"));
807 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
810 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
811 QVERIFY(innerRect != 0);
813 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
814 QVERIFY(leftGuideline != 0);
816 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
817 QVERIFY(bottomGuideline != 0);
819 QDeclarativeListReference list(rect, "states");
820 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
823 qmlExecuteDeferred(state);
824 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
825 QVERIFY(aChanges != 0);
827 QQuickItemPrivate::get(rect)->setState("reanchored");
828 QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
829 //QCOMPARE(aChanges->anchors()->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
830 //QCOMPARE(aChanges->anchors()->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
831 //QCOMPARE(aChanges->anchors()->baseline().item, leftGuideline->baseline().item);
832 //QCOMPARE(aChanges->anchors()->baseline().anchorLine, leftGuideline->baseline().anchorLine);
837 void mirrorAnchors(QQuickItem *item) {
838 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
839 itemPrivate->setLayoutMirror(true);
842 qreal offsetRTL(QQuickItem *anchorItem, QQuickItem *item) {
843 return anchorItem->width()+2*anchorItem->x()-item->width();
846 void tst_qdeclarativestates::anchorChangesRTL()
848 QDeclarativeEngine engine;
850 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
851 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
853 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
855 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
856 QVERIFY(innerRect != 0);
857 mirrorAnchors(innerRect);
859 QDeclarativeListReference list(rect, "states");
860 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
863 qmlExecuteDeferred(state);
864 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
865 QVERIFY(aChanges != 0);
867 rectPrivate->setState("right");
868 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
869 QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
870 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
871 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
872 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
874 rectPrivate->setState("");
875 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
880 void tst_qdeclarativestates::anchorChangesRTL2()
882 QDeclarativeEngine engine;
884 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
885 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
887 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
889 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
890 QVERIFY(innerRect != 0);
891 mirrorAnchors(innerRect);
893 rectPrivate->setState("right");
894 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
896 rectPrivate->setState("");
897 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
902 void tst_qdeclarativestates::anchorChangesRTL3()
904 QDeclarativeEngine engine;
906 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
907 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
909 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
911 QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
912 QVERIFY(innerRect != 0);
913 mirrorAnchors(innerRect);
915 QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
916 QVERIFY(leftGuideline != 0);
918 QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
919 QVERIFY(bottomGuideline != 0);
921 QDeclarativeListReference list(rect, "states");
922 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
925 qmlExecuteDeferred(state);
926 QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
927 QVERIFY(aChanges != 0);
929 rectPrivate->setState("reanchored");
930 QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
931 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
932 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
933 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
934 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
935 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
936 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
937 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
938 QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
940 QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
941 QCOMPARE(innerRect->y(), qreal(0));
942 // between left side of parent and leftGuideline.x: 10, which has width 0
943 QCOMPARE(innerRect->width(), qreal(10));
944 QCOMPARE(innerRect->height(), qreal(150));
946 rectPrivate->setState("");
947 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
948 QCOMPARE(innerRect->y(), qreal(10));
949 // between right side of parent and left side of rightGuideline.x: 150, which has width 0
950 QCOMPARE(innerRect->width(), qreal(50));
951 QCOMPARE(innerRect->height(), qreal(190));
957 void tst_qdeclarativestates::anchorChangesCrash()
959 QDeclarativeEngine engine;
961 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorChangesCrash.qml"));
962 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
965 QQuickItemPrivate::get(rect)->setState("reanchored");
971 void tst_qdeclarativestates::anchorRewindBug()
973 QQuickView *view = new QQuickView;
974 view->setSource(testFileUrl("anchorRewindBug.qml"));
977 view->requestActivateWindow();
979 QTest::qWaitForWindowShown(view);
981 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
984 QQuickItem * column = rect->findChild<QQuickItem*>("column");
986 QVERIFY(column != 0);
987 QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
988 QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
989 QCOMPARE(column->height(), 200.0);
990 QQuickItemPrivate::get(rect)->setState("reanchored");
992 // column height and width should stay implicit
993 // and column's implicit resizing should still work
994 QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
995 QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
996 QTRY_COMPARE(column->height(), 100.0);
998 QQuickItemPrivate::get(rect)->setState("");
1000 // column height and width should stay implicit
1001 // and column's implicit resizing should still work
1002 QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
1003 QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
1004 QTRY_COMPARE(column->height(), 200.0);
1010 void tst_qdeclarativestates::anchorRewindBug2()
1012 QDeclarativeEngine engine;
1014 QDeclarativeComponent rectComponent(&engine, testFileUrl("anchorRewindBug2.qml"));
1015 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1018 QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
1020 QVERIFY(mover != 0);
1021 QCOMPARE(mover->y(), qreal(0.0));
1022 QCOMPARE(mover->width(), qreal(50.0));
1024 QQuickItemPrivate::get(rect)->setState("anchored");
1025 QCOMPARE(mover->y(), qreal(250.0));
1026 QCOMPARE(mover->width(), qreal(200.0));
1028 QQuickItemPrivate::get(rect)->setState("");
1029 QCOMPARE(mover->y(), qreal(0.0));
1030 QCOMPARE(mover->width(), qreal(50.0));
1035 void tst_qdeclarativestates::script()
1037 QDeclarativeEngine engine;
1040 QDeclarativeComponent rectComponent(&engine, testFileUrl("script.qml"));
1041 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1043 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1044 QCOMPARE(rect->color(),QColor("red"));
1046 rectPrivate->setState("blue");
1047 QCOMPARE(rect->color(),QColor("blue"));
1049 rectPrivate->setState("");
1050 QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
1054 void tst_qdeclarativestates::restoreEntryValues()
1056 QDeclarativeEngine engine;
1058 QDeclarativeComponent rectComponent(&engine, testFileUrl("restoreEntryValues.qml"));
1059 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1061 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1062 QCOMPARE(rect->color(),QColor("red"));
1064 rectPrivate->setState("blue");
1065 QCOMPARE(rect->color(),QColor("blue"));
1067 rectPrivate->setState("");
1068 QCOMPARE(rect->color(),QColor("blue"));
1071 void tst_qdeclarativestates::explicitChanges()
1073 QDeclarativeEngine engine;
1075 QDeclarativeComponent rectComponent(&engine, testFileUrl("explicit.qml"));
1076 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1078 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1079 QDeclarativeListReference list(rect, "states");
1080 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
1081 QVERIFY(state != 0);
1083 qmlExecuteDeferred(state);
1084 QDeclarativePropertyChanges *changes = qobject_cast<QDeclarativePropertyChanges*>(rect->findChild<QDeclarativePropertyChanges*>("changes"));
1085 QVERIFY(changes != 0);
1086 QVERIFY(changes->isExplicit());
1088 QCOMPARE(rect->color(),QColor("red"));
1090 rectPrivate->setState("blue");
1091 QCOMPARE(rect->color(),QColor("blue"));
1093 rect->setProperty("sourceColor", QColor("green"));
1094 QCOMPARE(rect->color(),QColor("blue"));
1096 rectPrivate->setState("");
1097 QCOMPARE(rect->color(),QColor("red"));
1098 rect->setProperty("sourceColor", QColor("yellow"));
1099 QCOMPARE(rect->color(),QColor("red"));
1101 rectPrivate->setState("blue");
1102 QCOMPARE(rect->color(),QColor("yellow"));
1105 void tst_qdeclarativestates::propertyErrors()
1107 QDeclarativeEngine engine;
1108 QDeclarativeComponent rectComponent(&engine, testFileUrl("propertyErrors.qml"));
1109 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1112 QCOMPARE(rect->color(),QColor("red"));
1114 QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1115 QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
1116 QQuickItemPrivate::get(rect)->setState("blue");
1119 void tst_qdeclarativestates::incorrectRestoreBug()
1121 QDeclarativeEngine engine;
1123 QDeclarativeComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
1124 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1126 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1127 QCOMPARE(rect->color(),QColor("red"));
1129 rectPrivate->setState("blue");
1130 QCOMPARE(rect->color(),QColor("blue"));
1132 rectPrivate->setState("");
1133 QCOMPARE(rect->color(),QColor("red"));
1135 // make sure if we change the base state value, we then restore to it correctly
1136 rect->setColor(QColor("green"));
1138 rectPrivate->setState("blue");
1139 QCOMPARE(rect->color(),QColor("blue"));
1141 rectPrivate->setState("");
1142 QCOMPARE(rect->color(),QColor("green"));
1145 void tst_qdeclarativestates::autoStateAtStartupRestoreBug()
1147 QDeclarativeEngine engine;
1149 QDeclarativeComponent component(&engine, testFileUrl("autoStateAtStartupRestoreBug.qml"));
1150 QObject *obj = component.create();
1153 QCOMPARE(obj->property("test").toInt(), 3);
1155 obj->setProperty("input", 2);
1157 QCOMPARE(obj->property("test").toInt(), 9);
1162 void tst_qdeclarativestates::deletingChange()
1164 QDeclarativeEngine engine;
1166 QDeclarativeComponent rectComponent(&engine, testFileUrl("deleting.qml"));
1167 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1169 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1170 rectPrivate->setState("blue");
1171 QCOMPARE(rect->color(),QColor("blue"));
1172 QCOMPARE(rect->radius(),qreal(5));
1174 rectPrivate->setState("");
1175 QCOMPARE(rect->color(),QColor("red"));
1176 QCOMPARE(rect->radius(),qreal(0));
1178 QDeclarativePropertyChanges *pc = rect->findChild<QDeclarativePropertyChanges*>("pc1");
1182 QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
1183 QVERIFY(state != 0);
1184 qmlExecuteDeferred(state);
1185 QCOMPARE(state->operationCount(), 1);
1187 rectPrivate->setState("blue");
1188 QCOMPARE(rect->color(),QColor("red"));
1189 QCOMPARE(rect->radius(),qreal(5));
1194 void tst_qdeclarativestates::deletingState()
1196 QDeclarativeEngine engine;
1198 QDeclarativeComponent rectComponent(&engine, testFileUrl("deletingState.qml"));
1199 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1202 QDeclarativeStateGroup *sg = rect->findChild<QDeclarativeStateGroup*>();
1204 QVERIFY(sg->findState("blue") != 0);
1206 sg->setState("blue");
1207 QCOMPARE(rect->color(),QColor("blue"));
1210 QCOMPARE(rect->color(),QColor("red"));
1212 QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
1213 QVERIFY(state != 0);
1216 QVERIFY(sg->findState("blue") == 0);
1218 //### should we warn that state doesn't exist
1219 sg->setState("blue");
1220 QCOMPARE(rect->color(),QColor("red"));
1225 void tst_qdeclarativestates::tempState()
1227 QDeclarativeEngine engine;
1229 QDeclarativeComponent rectComponent(&engine, testFileUrl("legalTempState.qml"));
1230 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1232 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1233 QTest::ignoreMessage(QtDebugMsg, "entering placed");
1234 QTest::ignoreMessage(QtDebugMsg, "entering idle");
1235 rectPrivate->setState("placed");
1236 QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
1239 void tst_qdeclarativestates::illegalTempState()
1241 QDeclarativeEngine engine;
1243 QDeclarativeComponent rectComponent(&engine, testFileUrl("illegalTempState.qml"));
1244 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1246 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1247 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
1248 rectPrivate->setState("placed");
1249 QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
1252 void tst_qdeclarativestates::nonExistantProperty()
1254 QDeclarativeEngine engine;
1256 QDeclarativeComponent rectComponent(&engine, testFileUrl("nonExistantProp.qml"));
1257 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
1259 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1260 QTest::ignoreMessage(QtWarningMsg, fullDataPath("nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1261 rectPrivate->setState("blue");
1262 QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
1265 void tst_qdeclarativestates::reset()
1267 QDeclarativeEngine engine;
1269 QDeclarativeComponent c(&engine, testFileUrl("reset.qml"));
1270 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1273 QQuickImage *image = rect->findChild<QQuickImage*>();
1274 QVERIFY(image != 0);
1275 QCOMPARE(image->width(), qreal(40.));
1276 QCOMPARE(image->height(), qreal(20.));
1278 QQuickItemPrivate::get(rect)->setState("state1");
1280 QCOMPARE(image->width(), 20.0);
1281 QCOMPARE(image->height(), qreal(20.));
1286 void tst_qdeclarativestates::illegalObjectCreation()
1288 QDeclarativeEngine engine;
1290 QDeclarativeComponent component(&engine, testFileUrl("illegalObj.qml"));
1291 QList<QDeclarativeError> errors = component.errors();
1292 QVERIFY(errors.count() == 1);
1293 const QDeclarativeError &error = errors.at(0);
1294 QCOMPARE(error.line(), 9);
1295 QCOMPARE(error.column(), 23);
1296 QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
1299 void tst_qdeclarativestates::whenOrdering()
1301 QDeclarativeEngine engine;
1303 QDeclarativeComponent c(&engine, testFileUrl("whenOrdering.qml"));
1304 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1306 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1308 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1309 rect->setProperty("condition2", true);
1310 QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
1311 rect->setProperty("condition1", true);
1312 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1313 rect->setProperty("condition2", false);
1314 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1315 rect->setProperty("condition2", true);
1316 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1317 rect->setProperty("condition1", false);
1318 rect->setProperty("condition2", false);
1319 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1322 void tst_qdeclarativestates::urlResolution()
1324 QDeclarativeEngine engine;
1326 QDeclarativeComponent c(&engine, testFileUrl("urlResolution.qml"));
1327 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1330 QQuickItem *myType = rect->findChild<QQuickItem*>("MyType");
1331 QQuickImage *image1 = rect->findChild<QQuickImage*>("image1");
1332 QQuickImage *image2 = rect->findChild<QQuickImage*>("image2");
1333 QQuickImage *image3 = rect->findChild<QQuickImage*>("image3");
1334 QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
1336 QQuickItemPrivate::get(myType)->setState("SetImageState");
1337 QUrl resolved = testFileUrl("Implementation/images/qt-logo.png");
1338 QCOMPARE(image1->source(), resolved);
1339 QCOMPARE(image2->source(), resolved);
1340 QCOMPARE(image3->source(), resolved);
1345 void tst_qdeclarativestates::unnamedWhen()
1347 QDeclarativeEngine engine;
1349 QDeclarativeComponent c(&engine, testFileUrl("unnamedWhen.qml"));
1350 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1352 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1354 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1355 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1356 rect->setProperty("triggerState", true);
1357 QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1358 QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1359 rect->setProperty("triggerState", false);
1360 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1361 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1364 void tst_qdeclarativestates::returnToBase()
1366 QDeclarativeEngine engine;
1368 QDeclarativeComponent c(&engine, testFileUrl("returnToBase.qml"));
1369 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1371 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1373 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1374 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1375 rect->setProperty("triggerState", true);
1376 QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1377 QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1378 rect->setProperty("triggerState", false);
1379 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1380 QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
1384 void tst_qdeclarativestates::extendsBug()
1386 QDeclarativeEngine engine;
1388 QDeclarativeComponent c(&engine, testFileUrl("extendsBug.qml"));
1389 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1391 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1392 QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
1394 rectPrivate->setState("b");
1395 QCOMPARE(greenRect->x(), qreal(100));
1396 QCOMPARE(greenRect->y(), qreal(100));
1399 void tst_qdeclarativestates::editProperties()
1401 QDeclarativeEngine engine;
1403 QDeclarativeComponent c(&engine, testFileUrl("editProperties.qml"));
1404 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1407 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1409 QDeclarativeStateGroup *stateGroup = rectPrivate->_states();
1410 QVERIFY(stateGroup != 0);
1411 qmlExecuteDeferred(stateGroup);
1413 QDeclarativeState *blueState = stateGroup->findState("blue");
1414 QVERIFY(blueState != 0);
1415 qmlExecuteDeferred(blueState);
1417 QDeclarativePropertyChanges *propertyChangesBlue = qobject_cast<QDeclarativePropertyChanges*>(blueState->operationAt(0));
1418 QVERIFY(propertyChangesBlue != 0);
1420 QDeclarativeState *greenState = stateGroup->findState("green");
1421 QVERIFY(greenState != 0);
1422 qmlExecuteDeferred(greenState);
1424 QDeclarativePropertyChanges *propertyChangesGreen = qobject_cast<QDeclarativePropertyChanges*>(greenState->operationAt(0));
1425 QVERIFY(propertyChangesGreen != 0);
1427 QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
1428 QVERIFY(childRect != 0);
1429 QCOMPARE(childRect->width(), qreal(402));
1430 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1431 QCOMPARE(childRect->height(), qreal(200));
1433 rectPrivate->setState("blue");
1434 QCOMPARE(childRect->width(), qreal(50));
1435 QCOMPARE(childRect->height(), qreal(40));
1436 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1437 QVERIFY(blueState->bindingInRevertList(childRect, "width"));
1440 rectPrivate->setState("green");
1441 QCOMPARE(childRect->width(), qreal(200));
1442 QCOMPARE(childRect->height(), qreal(100));
1443 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1446 rectPrivate->setState("");
1449 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1450 QVERIFY(propertyChangesBlue->containsValue("width"));
1451 QVERIFY(!propertyChangesBlue->containsProperty("x"));
1452 QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1453 QVERIFY(!propertyChangesBlue->value("x").isValid());
1455 propertyChangesBlue->changeValue("width", 60);
1456 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1457 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1460 propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1461 QVERIFY(!propertyChangesBlue->containsValue("width"));
1462 QVERIFY(propertyChangesBlue->containsExpression("width"));
1463 QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1464 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1466 propertyChangesBlue->changeValue("width", 50);
1467 QVERIFY(propertyChangesBlue->containsValue("width"));
1468 QVERIFY(!propertyChangesBlue->containsExpression("width"));
1469 QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1470 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1472 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1473 rectPrivate->setState("blue");
1474 QCOMPARE(childRect->width(), qreal(50));
1475 QCOMPARE(childRect->height(), qreal(40));
1477 propertyChangesBlue->changeValue("width", 60);
1478 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1479 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1480 QCOMPARE(childRect->width(), qreal(60));
1481 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1483 propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1484 QVERIFY(!propertyChangesBlue->containsValue("width"));
1485 QVERIFY(propertyChangesBlue->containsExpression("width"));
1486 QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1487 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1488 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1489 QCOMPARE(childRect->width(), qreal(200));
1491 propertyChangesBlue->changeValue("width", 50);
1492 QCOMPARE(childRect->width(), qreal(50));
1494 rectPrivate->setState("");
1495 QCOMPARE(childRect->width(), qreal(402));
1496 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1498 QCOMPARE(propertyChangesGreen->actions().length(), 2);
1499 rectPrivate->setState("green");
1500 QCOMPARE(childRect->width(), qreal(200));
1501 QCOMPARE(childRect->height(), qreal(100));
1502 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1503 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1504 QCOMPARE(propertyChangesGreen->actions().length(), 2);
1507 propertyChangesGreen->removeProperty("height");
1508 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "height")));
1509 QCOMPARE(childRect->height(), qreal(200));
1511 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1512 QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
1513 propertyChangesGreen->removeProperty("width");
1514 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1515 QCOMPARE(childRect->width(), qreal(402));
1516 QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
1517 QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
1519 propertyChangesBlue->removeProperty("width");
1520 QCOMPARE(childRect->width(), qreal(402));
1522 rectPrivate->setState("blue");
1523 QCOMPARE(childRect->width(), qreal(402));
1524 QCOMPARE(childRect->height(), qreal(40));
1527 void tst_qdeclarativestates::QTBUG_14830()
1529 QDeclarativeEngine engine;
1531 QDeclarativeComponent c(&engine, testFileUrl("QTBUG-14830.qml"));
1532 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1534 QQuickItem *item = rect->findChild<QQuickItem*>("area");
1536 QCOMPARE(item->width(), qreal(171));
1539 void tst_qdeclarativestates::avoidFastForward()
1541 QDeclarativeEngine engine;
1543 //shouldn't fast forward if there isn't a transition
1544 QDeclarativeComponent c(&engine, testFileUrl("avoidFastForward.qml"));
1545 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1548 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1549 rectPrivate->setState("a");
1550 QCOMPARE(rect->property("updateCount").toInt(), 1);
1554 void tst_qdeclarativestates::revertListBug()
1556 QDeclarativeEngine engine;
1558 QDeclarativeComponent c(&engine, testFileUrl("revertListBug.qml"));
1559 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
1562 QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
1563 QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
1564 QQuickItem *origParent1 = rect->findChild<QQuickItem*>("originalParent1");
1565 QQuickItem *origParent2 = rect->findChild<QQuickItem*>("originalParent2");
1566 QQuickItem *newParent = rect->findChild<QQuickItem*>("newParent");
1568 QCOMPARE(rect1->parentItem(), origParent1);
1569 QCOMPARE(rect2->parentItem(), origParent2);
1571 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1572 rectPrivate->setState("reparented");
1574 QCOMPARE(rect1->parentItem(), newParent);
1575 QCOMPARE(rect2->parentItem(), origParent2);
1577 rectPrivate->setState("");
1579 QCOMPARE(rect1->parentItem(), origParent1);
1580 QCOMPARE(rect2->parentItem(), origParent2);
1582 QMetaObject::invokeMethod(rect, "switchTargetItem");
1584 rectPrivate->setState("reparented");
1586 QCOMPARE(rect1->parentItem(), origParent1);
1587 QCOMPARE(rect2->parentItem(), newParent);
1589 rectPrivate->setState("");
1591 QCOMPARE(rect1->parentItem(), origParent1);
1592 QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
1595 QTEST_MAIN(tst_qdeclarativestates)
1597 #include "tst_qdeclarativestates.moc"