1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtQuick1/private/qdeclarativeanchors_p_p.h>
45 #include <QtQuick1/private/qdeclarativerectangle_p.h>
46 #include <QtQuick1/private/qdeclarativeimage_p.h>
47 #include <QtQuick1/private/qdeclarativepropertychanges_p.h>
48 #include <QtQuick1/private/qdeclarativestategroup_p.h>
49 #include <QtQuick1/private/qdeclarativeitem_p.h>
50 #include <private/qdeclarativeproperty_p.h>
52 class MyAttached : public QObject
55 Q_PROPERTY(int foo READ foo WRITE setFoo)
57 MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
59 int foo() const { return m_foo; }
60 void setFoo(int f) { m_foo = f; }
66 class MyRect : public QDeclarative1Rectangle
69 Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
73 void doSomething() { emit didSomething(); }
75 int propertyWithNotify() const { return m_prop; }
76 void setPropertyWithNotify(int i) { m_prop = i; emit oddlyNamedNotifySignal(); }
78 static MyAttached *qmlAttachedProperties(QObject *o) {
79 return new MyAttached(o);
83 void oddlyNamedNotifySignal();
89 QML_DECLARE_TYPE(MyRect)
90 QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
92 class tst_qdeclarativestates : public QObject
96 tst_qdeclarativestates() {}
99 static QByteArray fullDataPath(const QString &path);
105 void attachedPropertyChanges();
106 void basicExtension();
108 void signalOverride();
109 void signalOverrideCrash();
110 void signalOverrideCrash2();
111 void signalOverrideCrash3();
113 void parentChangeErrors();
114 void anchorChanges();
115 void anchorChanges2();
116 void anchorChanges3();
117 void anchorChanges4();
118 void anchorChanges5();
119 void anchorChangesRTL();
120 void anchorChangesRTL2();
121 void anchorChangesRTL3();
122 void anchorChangesCrash();
123 void anchorRewindBug();
124 void anchorRewindBug2();
126 void restoreEntryValues();
127 void explicitChanges();
128 void propertyErrors();
129 void incorrectRestoreBug();
130 void autoStateAtStartupRestoreBug();
131 void deletingChange();
132 void deletingState();
134 void illegalTempState();
135 void nonExistantProperty();
137 void illegalObjectCreation();
139 void urlResolution();
143 void editProperties();
147 void tst_qdeclarativestates::initTestCase()
149 qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
152 QByteArray tst_qdeclarativestates::fullDataPath(const QString &path)
154 return QUrl::fromLocalFile(SRCDIR + path).toString().toUtf8();
157 void tst_qdeclarativestates::basicChanges()
159 QDeclarativeEngine engine;
162 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges.qml");
163 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
164 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
167 QCOMPARE(rect->color(),QColor("red"));
169 rectPrivate->setState("blue");
170 QCOMPARE(rect->color(),QColor("blue"));
172 rectPrivate->setState("");
173 QCOMPARE(rect->color(),QColor("red"));
177 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges2.qml");
178 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
179 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
182 QCOMPARE(rect->color(),QColor("red"));
184 rectPrivate->setState("blue");
185 QCOMPARE(rect->color(),QColor("blue"));
187 rectPrivate->setState("green");
188 QCOMPARE(rect->color(),QColor("green"));
190 rectPrivate->setState("");
191 QCOMPARE(rect->color(),QColor("red"));
193 rectPrivate->setState("green");
194 QCOMPARE(rect->color(),QColor("green"));
198 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges3.qml");
199 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
200 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
203 QCOMPARE(rect->color(),QColor("red"));
204 QCOMPARE(rect->border()->width(),1);
206 rectPrivate->setState("blue");
207 QCOMPARE(rect->color(),QColor("blue"));
208 QCOMPARE(rect->border()->width(),1);
210 rectPrivate->setState("bordered");
211 QCOMPARE(rect->color(),QColor("red"));
212 QCOMPARE(rect->border()->width(),2);
214 rectPrivate->setState("");
215 QCOMPARE(rect->color(),QColor("red"));
216 QCOMPARE(rect->border()->width(),1);
217 //### we should be checking that this is an implicit rather than explicit 1 (which currently fails)
219 rectPrivate->setState("bordered");
220 QCOMPARE(rect->color(),QColor("red"));
221 QCOMPARE(rect->border()->width(),2);
223 rectPrivate->setState("blue");
224 QCOMPARE(rect->color(),QColor("blue"));
225 QCOMPARE(rect->border()->width(),1);
230 // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
231 // signal using 'onPropertyWithNotifyChanged' even though the signal name is
232 // actually 'oddlyNamedNotifySignal'
234 QDeclarativeComponent component(&engine, SRCDIR "/data/basicChanges4.qml");
235 QVERIFY(component.isReady());
237 MyRect *rect = qobject_cast<MyRect*>(component.create());
240 QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
241 QVERIFY(prop.hasNotifySignal());
242 QString notifySignal = QByteArray(prop.notifySignal().signature());
243 QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
245 QCOMPARE(rect->color(), QColor(Qt::red));
247 rect->setPropertyWithNotify(100);
248 QCOMPARE(rect->color(), QColor(Qt::blue));
252 void tst_qdeclarativestates::attachedPropertyChanges()
254 QDeclarativeEngine engine;
256 QDeclarativeComponent component(&engine, SRCDIR "/data/attachedPropertyChanges.qml");
257 QVERIFY(component.isReady());
259 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(component.create());
261 QCOMPARE(item->width(), 50.0);
263 // Ensure attached property has been changed
264 QObject *attObj = qmlAttachedPropertiesObject<MyRect>(item, false);
267 MyAttached *att = qobject_cast<MyAttached*>(attObj);
270 QCOMPARE(att->foo(), 1);
273 void tst_qdeclarativestates::basicExtension()
275 QDeclarativeEngine engine;
278 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicExtension.qml");
279 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
280 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
283 QCOMPARE(rect->color(),QColor("red"));
284 QCOMPARE(rect->border()->width(),1);
286 rectPrivate->setState("blue");
287 QCOMPARE(rect->color(),QColor("blue"));
288 QCOMPARE(rect->border()->width(),1);
290 rectPrivate->setState("bordered");
291 QCOMPARE(rect->color(),QColor("blue"));
292 QCOMPARE(rect->border()->width(),2);
294 rectPrivate->setState("blue");
295 QCOMPARE(rect->color(),QColor("blue"));
296 QCOMPARE(rect->border()->width(),1);
298 rectPrivate->setState("");
299 QCOMPARE(rect->color(),QColor("red"));
300 QCOMPARE(rect->border()->width(),1);
302 rectPrivate->setState("bordered");
303 QCOMPARE(rect->color(),QColor("blue"));
304 QCOMPARE(rect->border()->width(),2);
306 rectPrivate->setState("");
307 QCOMPARE(rect->color(),QColor("red"));
308 QCOMPARE(rect->border()->width(),1);
312 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/fakeExtension.qml");
313 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
314 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
317 QCOMPARE(rect->color(),QColor("red"));
319 rectPrivate->setState("blue");
320 QCOMPARE(rect->color(),QColor("blue"));
322 rectPrivate->setState("green");
323 QCOMPARE(rect->color(),QColor("green"));
325 rectPrivate->setState("blue");
326 QCOMPARE(rect->color(),QColor("blue"));
328 rectPrivate->setState("green");
329 QCOMPARE(rect->color(),QColor("green"));
331 rectPrivate->setState("");
332 QCOMPARE(rect->color(),QColor("red"));
334 rectPrivate->setState("green");
335 QCOMPARE(rect->color(),QColor("green"));
339 void tst_qdeclarativestates::basicBinding()
341 QDeclarativeEngine engine;
344 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding.qml");
345 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
346 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
349 QCOMPARE(rect->color(),QColor("red"));
351 rectPrivate->setState("blue");
352 QCOMPARE(rect->color(),QColor("blue"));
354 rectPrivate->setState("");
355 QCOMPARE(rect->color(),QColor("red"));
357 rectPrivate->setState("blue");
358 QCOMPARE(rect->color(),QColor("blue"));
359 rect->setProperty("sourceColor", QColor("green"));
360 QCOMPARE(rect->color(),QColor("green"));
362 rectPrivate->setState("");
363 QCOMPARE(rect->color(),QColor("red"));
364 rect->setProperty("sourceColor", QColor("yellow"));
365 QCOMPARE(rect->color(),QColor("red"));
367 rectPrivate->setState("blue");
368 QCOMPARE(rect->color(),QColor("yellow"));
372 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding2.qml");
373 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
374 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
377 QCOMPARE(rect->color(),QColor("red"));
379 rectPrivate->setState("blue");
380 QCOMPARE(rect->color(),QColor("blue"));
382 rectPrivate->setState("");
383 QCOMPARE(rect->color(),QColor("red"));
385 rectPrivate->setState("blue");
386 QCOMPARE(rect->color(),QColor("blue"));
387 rect->setProperty("sourceColor", QColor("green"));
388 QCOMPARE(rect->color(),QColor("blue"));
390 rectPrivate->setState("");
391 QCOMPARE(rect->color(),QColor("green"));
392 rect->setProperty("sourceColor", QColor("yellow"));
393 QCOMPARE(rect->color(),QColor("yellow"));
395 rectPrivate->setState("blue");
396 QCOMPARE(rect->color(),QColor("blue"));
398 rectPrivate->setState("");
399 QCOMPARE(rect->color(),QColor("yellow"));
403 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding3.qml");
404 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
405 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
408 QCOMPARE(rect->color(),QColor("red"));
409 rect->setProperty("sourceColor", QColor("green"));
410 QCOMPARE(rect->color(),QColor("green"));
412 rectPrivate->setState("blue");
413 QCOMPARE(rect->color(),QColor("blue"));
414 rect->setProperty("sourceColor", QColor("red"));
415 QCOMPARE(rect->color(),QColor("blue"));
416 rect->setProperty("sourceColor2", QColor("yellow"));
417 QCOMPARE(rect->color(),QColor("yellow"));
419 rectPrivate->setState("");
420 QCOMPARE(rect->color(),QColor("red"));
421 rect->setProperty("sourceColor2", QColor("green"));
422 QCOMPARE(rect->color(),QColor("red"));
423 rect->setProperty("sourceColor", QColor("yellow"));
424 QCOMPARE(rect->color(),QColor("yellow"));
428 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding4.qml");
429 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
430 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
433 QCOMPARE(rect->color(),QColor("red"));
435 rectPrivate->setState("blue");
436 QCOMPARE(rect->color(),QColor("blue"));
437 rect->setProperty("sourceColor", QColor("yellow"));
438 QCOMPARE(rect->color(),QColor("yellow"));
440 rectPrivate->setState("green");
441 QCOMPARE(rect->color(),QColor("green"));
442 rect->setProperty("sourceColor", QColor("purple"));
443 QCOMPARE(rect->color(),QColor("green"));
445 rectPrivate->setState("blue");
446 QCOMPARE(rect->color(),QColor("purple"));
448 rectPrivate->setState("green");
449 QCOMPARE(rect->color(),QColor("green"));
451 rectPrivate->setState("");
452 QCOMPARE(rect->color(),QColor("red"));
456 void tst_qdeclarativestates::signalOverride()
458 QDeclarativeEngine engine;
461 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverride.qml");
462 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
465 QCOMPARE(rect->color(),QColor("red"));
467 QCOMPARE(rect->color(),QColor("blue"));
469 QDeclarativeItemPrivate::get(rect)->setState("green");
471 QCOMPARE(rect->color(),QColor("green"));
475 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverride2.qml");
476 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
479 QCOMPARE(rect->color(),QColor("white"));
481 QCOMPARE(rect->color(),QColor("blue"));
483 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("extendedRect"));
484 QDeclarativeItemPrivate::get(innerRect)->setState("green");
486 QCOMPARE(rect->color(),QColor("blue"));
487 QCOMPARE(innerRect->color(),QColor("green"));
488 QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
492 void tst_qdeclarativestates::signalOverrideCrash()
494 QDeclarativeEngine engine;
496 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverrideCrash.qml");
497 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
500 QDeclarativeItemPrivate::get(rect)->setState("overridden");
504 void tst_qdeclarativestates::signalOverrideCrash2()
506 QDeclarativeEngine engine;
508 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverrideCrash2.qml");
509 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
512 QDeclarativeItemPrivate::get(rect)->setState("state1");
513 QDeclarativeItemPrivate::get(rect)->setState("state2");
514 QDeclarativeItemPrivate::get(rect)->setState("state1");
519 void tst_qdeclarativestates::signalOverrideCrash3()
521 QDeclarativeEngine engine;
523 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverrideCrash3.qml");
524 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
527 QDeclarativeItemPrivate::get(rect)->setState("state1");
528 QDeclarativeItemPrivate::get(rect)->setState("");
529 QDeclarativeItemPrivate::get(rect)->setState("state2");
530 QDeclarativeItemPrivate::get(rect)->setState("");
535 void tst_qdeclarativestates::parentChange()
537 QDeclarativeEngine engine;
540 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange1.qml");
541 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
544 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
545 QVERIFY(innerRect != 0);
547 QDeclarativeListReference list(rect, "states");
548 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
551 qmlExecuteDeferred(state);
552 QDeclarative1ParentChange *pChange = qobject_cast<QDeclarative1ParentChange*>(state->operationAt(0));
553 QVERIFY(pChange != 0);
554 QDeclarativeItem *nParent = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("NewParent"));
555 QVERIFY(nParent != 0);
557 QCOMPARE(pChange->parent(), nParent);
559 QDeclarativeItemPrivate::get(rect)->setState("reparented");
560 QCOMPARE(innerRect->rotation(), qreal(0));
561 QCOMPARE(innerRect->scale(), qreal(1));
562 QCOMPARE(innerRect->x(), qreal(-133));
563 QCOMPARE(innerRect->y(), qreal(-300));
567 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange2.qml");
568 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
570 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
571 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
572 QVERIFY(innerRect != 0);
574 rectPrivate->setState("reparented");
575 QCOMPARE(innerRect->rotation(), qreal(15));
576 QCOMPARE(innerRect->scale(), qreal(.5));
577 QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-19.9075));
578 QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-8.73433));
582 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange3.qml");
583 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
585 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
586 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
587 QVERIFY(innerRect != 0);
589 rectPrivate->setState("reparented");
590 QCOMPARE(innerRect->rotation(), qreal(-37));
591 QCOMPARE(innerRect->scale(), qreal(.25));
592 QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-217.305));
593 QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-164.413));
595 rectPrivate->setState("");
596 QCOMPARE(innerRect->rotation(), qreal(0));
597 QCOMPARE(innerRect->scale(), qreal(1));
598 QCOMPARE(innerRect->x(), qreal(5));
599 //do a non-qFuzzyCompare fuzzy compare
600 QVERIFY(innerRect->y() < qreal(0.00001) && innerRect->y() > qreal(-0.00001));
604 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange6.qml");
605 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
608 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
609 QVERIFY(innerRect != 0);
611 QDeclarativeItemPrivate::get(rect)->setState("reparented");
612 QCOMPARE(innerRect->rotation(), qreal(180));
613 QCOMPARE(innerRect->scale(), qreal(1));
614 QCOMPARE(innerRect->x(), qreal(-105));
615 QCOMPARE(innerRect->y(), qreal(-105));
619 void tst_qdeclarativestates::parentChangeErrors()
621 QDeclarativeEngine engine;
624 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange4.qml");
625 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
628 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
629 QVERIFY(innerRect != 0);
631 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/parentChange4.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under non-uniform scale");
632 QDeclarativeItemPrivate::get(rect)->setState("reparented");
633 QCOMPARE(innerRect->rotation(), qreal(0));
634 QCOMPARE(innerRect->scale(), qreal(1));
635 QCOMPARE(innerRect->x(), qreal(5));
636 QCOMPARE(innerRect->y(), qreal(5));
640 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange5.qml");
641 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
644 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
645 QVERIFY(innerRect != 0);
647 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/parentChange5.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under complex transform");
648 QDeclarativeItemPrivate::get(rect)->setState("reparented");
649 QCOMPARE(innerRect->rotation(), qreal(0));
650 QCOMPARE(innerRect->scale(), qreal(1));
651 QCOMPARE(innerRect->x(), qreal(5));
652 QCOMPARE(innerRect->y(), qreal(5));
656 void tst_qdeclarativestates::anchorChanges()
658 QDeclarativeEngine engine;
660 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges1.qml");
661 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
663 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
665 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
666 QVERIFY(innerRect != 0);
668 QDeclarativeListReference list(rect, "states");
669 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
672 qmlExecuteDeferred(state);
673 QDeclarative1AnchorChanges *aChanges = qobject_cast<QDeclarative1AnchorChanges*>(state->operationAt(0));
674 QVERIFY(aChanges != 0);
676 rectPrivate->setState("right");
677 QCOMPARE(innerRect->x(), qreal(150));
678 QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect));
679 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QDeclarative1AnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
680 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
681 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
683 rectPrivate->setState("");
684 QCOMPARE(innerRect->x(), qreal(5));
689 void tst_qdeclarativestates::anchorChanges2()
691 QDeclarativeEngine engine;
693 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges2.qml");
694 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
696 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
698 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
699 QVERIFY(innerRect != 0);
701 rectPrivate->setState("right");
702 QCOMPARE(innerRect->x(), qreal(150));
704 rectPrivate->setState("");
705 QCOMPARE(innerRect->x(), qreal(5));
710 void tst_qdeclarativestates::anchorChanges3()
712 QDeclarativeEngine engine;
714 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges3.qml");
715 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
717 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
719 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
720 QVERIFY(innerRect != 0);
722 QDeclarativeItem *leftGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("LeftGuideline"));
723 QVERIFY(leftGuideline != 0);
725 QDeclarativeItem *bottomGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("BottomGuideline"));
726 QVERIFY(bottomGuideline != 0);
728 QDeclarativeListReference list(rect, "states");
729 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
732 qmlExecuteDeferred(state);
733 QDeclarative1AnchorChanges *aChanges = qobject_cast<QDeclarative1AnchorChanges*>(state->operationAt(0));
734 QVERIFY(aChanges != 0);
736 rectPrivate->setState("reanchored");
737 QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect));
738 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().item, QDeclarativeItemPrivate::get(leftGuideline)->left().item);
739 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QDeclarativeItemPrivate::get(leftGuideline)->left().anchorLine);
740 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
741 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
742 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
743 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
744 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->bottom().item, QDeclarativeItemPrivate::get(bottomGuideline)->bottom().item);
745 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QDeclarativeItemPrivate::get(bottomGuideline)->bottom().anchorLine);
747 QCOMPARE(innerRect->x(), qreal(10));
748 QCOMPARE(innerRect->y(), qreal(0));
749 QCOMPARE(innerRect->width(), qreal(190));
750 QCOMPARE(innerRect->height(), qreal(150));
752 rectPrivate->setState("");
753 QCOMPARE(innerRect->x(), qreal(0));
754 QCOMPARE(innerRect->y(), qreal(10));
755 QCOMPARE(innerRect->width(), qreal(150));
756 QCOMPARE(innerRect->height(), qreal(190));
761 void tst_qdeclarativestates::anchorChanges4()
763 QDeclarativeEngine engine;
765 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges4.qml");
766 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
769 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
770 QVERIFY(innerRect != 0);
772 QDeclarativeItem *leftGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("LeftGuideline"));
773 QVERIFY(leftGuideline != 0);
775 QDeclarativeItem *bottomGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("BottomGuideline"));
776 QVERIFY(bottomGuideline != 0);
778 QDeclarativeListReference list(rect, "states");
779 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
782 qmlExecuteDeferred(state);
783 QDeclarative1AnchorChanges *aChanges = qobject_cast<QDeclarative1AnchorChanges*>(state->operationAt(0));
784 QVERIFY(aChanges != 0);
786 QDeclarativeItemPrivate::get(rect)->setState("reanchored");
787 QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect));
788 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QDeclarativeItemPrivate::get(bottomGuideline)->horizontalCenter().item);
789 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QDeclarativeItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
790 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QDeclarativeItemPrivate::get(leftGuideline)->verticalCenter().item);
791 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QDeclarativeItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
796 void tst_qdeclarativestates::anchorChanges5()
798 QDeclarativeEngine engine;
800 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges5.qml");
801 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
804 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
805 QVERIFY(innerRect != 0);
807 QDeclarativeItem *leftGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("LeftGuideline"));
808 QVERIFY(leftGuideline != 0);
810 QDeclarativeItem *bottomGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("BottomGuideline"));
811 QVERIFY(bottomGuideline != 0);
813 QDeclarativeListReference list(rect, "states");
814 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
817 qmlExecuteDeferred(state);
818 QDeclarative1AnchorChanges *aChanges = qobject_cast<QDeclarative1AnchorChanges*>(state->operationAt(0));
819 QVERIFY(aChanges != 0);
821 QDeclarativeItemPrivate::get(rect)->setState("reanchored");
822 QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect));
823 //QCOMPARE(aChanges->anchors()->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
824 //QCOMPARE(aChanges->anchors()->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
825 //QCOMPARE(aChanges->anchors()->baseline().item, leftGuideline->baseline().item);
826 //QCOMPARE(aChanges->anchors()->baseline().anchorLine, leftGuideline->baseline().anchorLine);
831 void mirrorAnchors(QDeclarativeItem *item) {
832 QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
833 itemPrivate->setLayoutMirror(true);
836 qreal offsetRTL(QDeclarativeItem *anchorItem, QDeclarativeItem *item) {
837 return anchorItem->width()+2*anchorItem->x()-item->width();
840 void tst_qdeclarativestates::anchorChangesRTL()
842 QDeclarativeEngine engine;
844 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges1.qml");
845 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
847 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
849 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
850 QVERIFY(innerRect != 0);
851 mirrorAnchors(innerRect);
853 QDeclarativeListReference list(rect, "states");
854 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
857 qmlExecuteDeferred(state);
858 QDeclarative1AnchorChanges *aChanges = qobject_cast<QDeclarative1AnchorChanges*>(state->operationAt(0));
859 QVERIFY(aChanges != 0);
861 rectPrivate->setState("right");
862 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
863 QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect));
864 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QDeclarative1AnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
865 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
866 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
868 rectPrivate->setState("");
869 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
874 void tst_qdeclarativestates::anchorChangesRTL2()
876 QDeclarativeEngine engine;
878 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges2.qml");
879 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
881 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
883 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
884 QVERIFY(innerRect != 0);
885 mirrorAnchors(innerRect);
887 rectPrivate->setState("right");
888 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
890 rectPrivate->setState("");
891 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
896 void tst_qdeclarativestates::anchorChangesRTL3()
898 QDeclarativeEngine engine;
900 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges3.qml");
901 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
903 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
905 QDeclarative1Rectangle *innerRect = qobject_cast<QDeclarative1Rectangle*>(rect->findChild<QDeclarative1Rectangle*>("MyRect"));
906 QVERIFY(innerRect != 0);
907 mirrorAnchors(innerRect);
909 QDeclarativeItem *leftGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("LeftGuideline"));
910 QVERIFY(leftGuideline != 0);
912 QDeclarativeItem *bottomGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("BottomGuideline"));
913 QVERIFY(bottomGuideline != 0);
915 QDeclarativeListReference list(rect, "states");
916 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
919 qmlExecuteDeferred(state);
920 QDeclarative1AnchorChanges *aChanges = qobject_cast<QDeclarative1AnchorChanges*>(state->operationAt(0));
921 QVERIFY(aChanges != 0);
923 rectPrivate->setState("reanchored");
924 QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect));
925 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().item, QDeclarativeItemPrivate::get(leftGuideline)->left().item);
926 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QDeclarativeItemPrivate::get(leftGuideline)->left().anchorLine);
927 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
928 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
929 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
930 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
931 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->bottom().item, QDeclarativeItemPrivate::get(bottomGuideline)->bottom().item);
932 QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QDeclarativeItemPrivate::get(bottomGuideline)->bottom().anchorLine);
934 QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
935 QCOMPARE(innerRect->y(), qreal(0));
936 // between left side of parent and leftGuideline.x: 10, which has width 0
937 QCOMPARE(innerRect->width(), qreal(10));
938 QCOMPARE(innerRect->height(), qreal(150));
940 rectPrivate->setState("");
941 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
942 QCOMPARE(innerRect->y(), qreal(10));
943 // between right side of parent and left side of rightGuideline.x: 150, which has width 0
944 QCOMPARE(innerRect->width(), qreal(50));
945 QCOMPARE(innerRect->height(), qreal(190));
951 void tst_qdeclarativestates::anchorChangesCrash()
953 QDeclarativeEngine engine;
955 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChangesCrash.qml");
956 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
959 QDeclarativeItemPrivate::get(rect)->setState("reanchored");
965 void tst_qdeclarativestates::anchorRewindBug()
967 QDeclarativeEngine engine;
969 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorRewindBug.qml");
970 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
973 QDeclarativeItem * column = rect->findChild<QDeclarativeItem*>("column");
975 QVERIFY(column != 0);
976 QVERIFY(!QDeclarativeItemPrivate::get(column)->heightValid);
977 QVERIFY(!QDeclarativeItemPrivate::get(column)->widthValid);
978 QCOMPARE(column->height(), 200.0);
979 QDeclarativeItemPrivate::get(rect)->setState("reanchored");
981 // column height and width should stay implicit
982 // and column's implicit resizing should still work
983 QVERIFY(!QDeclarativeItemPrivate::get(column)->heightValid);
984 QVERIFY(!QDeclarativeItemPrivate::get(column)->widthValid);
985 QCOMPARE(column->height(), 100.0);
987 QDeclarativeItemPrivate::get(rect)->setState("");
989 // column height and width should stay implicit
990 // and column's implicit resizing should still work
991 QVERIFY(!QDeclarativeItemPrivate::get(column)->heightValid);
992 QVERIFY(!QDeclarativeItemPrivate::get(column)->widthValid);
993 QCOMPARE(column->height(), 200.0);
999 void tst_qdeclarativestates::anchorRewindBug2()
1001 QDeclarativeEngine engine;
1003 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorRewindBug2.qml");
1004 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1007 QDeclarative1Rectangle *mover = rect->findChild<QDeclarative1Rectangle*>("mover");
1009 QVERIFY(mover != 0);
1010 QCOMPARE(mover->y(), qreal(0.0));
1011 QCOMPARE(mover->width(), qreal(50.0));
1013 QDeclarativeItemPrivate::get(rect)->setState("anchored");
1014 QCOMPARE(mover->y(), qreal(250.0));
1015 QCOMPARE(mover->width(), qreal(200.0));
1017 QDeclarativeItemPrivate::get(rect)->setState("");
1018 QCOMPARE(mover->y(), qreal(0.0));
1019 QCOMPARE(mover->width(), qreal(50.0));
1024 void tst_qdeclarativestates::script()
1026 QDeclarativeEngine engine;
1029 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/script.qml");
1030 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1032 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1033 QCOMPARE(rect->color(),QColor("red"));
1035 rectPrivate->setState("blue");
1036 QCOMPARE(rect->color(),QColor("blue"));
1038 rectPrivate->setState("");
1039 QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
1043 void tst_qdeclarativestates::restoreEntryValues()
1045 QDeclarativeEngine engine;
1047 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/restoreEntryValues.qml");
1048 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1050 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1051 QCOMPARE(rect->color(),QColor("red"));
1053 rectPrivate->setState("blue");
1054 QCOMPARE(rect->color(),QColor("blue"));
1056 rectPrivate->setState("");
1057 QCOMPARE(rect->color(),QColor("blue"));
1060 void tst_qdeclarativestates::explicitChanges()
1062 QDeclarativeEngine engine;
1064 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/explicit.qml");
1065 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1067 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1068 QDeclarativeListReference list(rect, "states");
1069 QDeclarative1State *state = qobject_cast<QDeclarative1State*>(list.at(0));
1070 QVERIFY(state != 0);
1072 qmlExecuteDeferred(state);
1073 QDeclarative1PropertyChanges *changes = qobject_cast<QDeclarative1PropertyChanges*>(rect->findChild<QDeclarative1PropertyChanges*>("changes"));
1074 QVERIFY(changes != 0);
1075 QVERIFY(changes->isExplicit());
1077 QCOMPARE(rect->color(),QColor("red"));
1079 rectPrivate->setState("blue");
1080 QCOMPARE(rect->color(),QColor("blue"));
1082 rect->setProperty("sourceColor", QColor("green"));
1083 QCOMPARE(rect->color(),QColor("blue"));
1085 rectPrivate->setState("");
1086 QCOMPARE(rect->color(),QColor("red"));
1087 rect->setProperty("sourceColor", QColor("yellow"));
1088 QCOMPARE(rect->color(),QColor("red"));
1090 rectPrivate->setState("blue");
1091 QCOMPARE(rect->color(),QColor("yellow"));
1094 void tst_qdeclarativestates::propertyErrors()
1096 QDeclarativeEngine engine;
1097 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/propertyErrors.qml");
1098 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1101 QCOMPARE(rect->color(),QColor("red"));
1103 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1104 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
1105 QDeclarativeItemPrivate::get(rect)->setState("blue");
1108 void tst_qdeclarativestates::incorrectRestoreBug()
1110 QDeclarativeEngine engine;
1112 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges.qml");
1113 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1115 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1116 QCOMPARE(rect->color(),QColor("red"));
1118 rectPrivate->setState("blue");
1119 QCOMPARE(rect->color(),QColor("blue"));
1121 rectPrivate->setState("");
1122 QCOMPARE(rect->color(),QColor("red"));
1124 // make sure if we change the base state value, we then restore to it correctly
1125 rect->setColor(QColor("green"));
1127 rectPrivate->setState("blue");
1128 QCOMPARE(rect->color(),QColor("blue"));
1130 rectPrivate->setState("");
1131 QCOMPARE(rect->color(),QColor("green"));
1134 void tst_qdeclarativestates::autoStateAtStartupRestoreBug()
1136 QDeclarativeEngine engine;
1138 QDeclarativeComponent component(&engine, SRCDIR "/data/autoStateAtStartupRestoreBug.qml");
1139 QObject *obj = component.create();
1142 QCOMPARE(obj->property("test").toInt(), 3);
1144 obj->setProperty("input", 2);
1146 QCOMPARE(obj->property("test").toInt(), 9);
1151 void tst_qdeclarativestates::deletingChange()
1153 QDeclarativeEngine engine;
1155 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/deleting.qml");
1156 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1158 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1159 rectPrivate->setState("blue");
1160 QCOMPARE(rect->color(),QColor("blue"));
1161 QCOMPARE(rect->radius(),qreal(5));
1163 rectPrivate->setState("");
1164 QCOMPARE(rect->color(),QColor("red"));
1165 QCOMPARE(rect->radius(),qreal(0));
1167 QDeclarative1PropertyChanges *pc = rect->findChild<QDeclarative1PropertyChanges*>("pc1");
1171 QDeclarative1State *state = rect->findChild<QDeclarative1State*>();
1172 QVERIFY(state != 0);
1173 qmlExecuteDeferred(state);
1174 QCOMPARE(state->operationCount(), 1);
1176 rectPrivate->setState("blue");
1177 QCOMPARE(rect->color(),QColor("red"));
1178 QCOMPARE(rect->radius(),qreal(5));
1183 void tst_qdeclarativestates::deletingState()
1185 QDeclarativeEngine engine;
1187 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/deletingState.qml");
1188 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1191 QDeclarative1StateGroup *sg = rect->findChild<QDeclarative1StateGroup*>();
1193 QVERIFY(sg->findState("blue") != 0);
1195 sg->setState("blue");
1196 QCOMPARE(rect->color(),QColor("blue"));
1199 QCOMPARE(rect->color(),QColor("red"));
1201 QDeclarative1State *state = rect->findChild<QDeclarative1State*>();
1202 QVERIFY(state != 0);
1205 QVERIFY(sg->findState("blue") == 0);
1207 //### should we warn that state doesn't exist
1208 sg->setState("blue");
1209 QCOMPARE(rect->color(),QColor("red"));
1214 void tst_qdeclarativestates::tempState()
1216 QDeclarativeEngine engine;
1218 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/legalTempState.qml");
1219 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1221 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1222 QTest::ignoreMessage(QtDebugMsg, "entering placed");
1223 QTest::ignoreMessage(QtDebugMsg, "entering idle");
1224 rectPrivate->setState("placed");
1225 QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
1228 void tst_qdeclarativestates::illegalTempState()
1230 QDeclarativeEngine engine;
1232 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/illegalTempState.qml");
1233 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1235 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1236 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
1237 rectPrivate->setState("placed");
1238 QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
1241 void tst_qdeclarativestates::nonExistantProperty()
1243 QDeclarativeEngine engine;
1245 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/nonExistantProp.qml");
1246 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(rectComponent.create());
1248 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1249 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1250 rectPrivate->setState("blue");
1251 QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
1254 void tst_qdeclarativestates::reset()
1256 QDeclarativeEngine engine;
1258 QDeclarativeComponent c(&engine, SRCDIR "/data/reset.qml");
1259 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1262 QDeclarative1Image *image = rect->findChild<QDeclarative1Image*>();
1263 QVERIFY(image != 0);
1264 QCOMPARE(image->width(), qreal(40.));
1265 QCOMPARE(image->height(), qreal(20.));
1267 QDeclarativeItemPrivate::get(rect)->setState("state1");
1269 QCOMPARE(image->width(), 20.0);
1270 QCOMPARE(image->height(), qreal(20.));
1273 void tst_qdeclarativestates::illegalObjectCreation()
1275 QDeclarativeEngine engine;
1277 QDeclarativeComponent component(&engine, SRCDIR "/data/illegalObj.qml");
1278 QList<QDeclarativeError> errors = component.errors();
1279 QVERIFY(errors.count() == 1);
1280 const QDeclarativeError &error = errors.at(0);
1281 QCOMPARE(error.line(), 9);
1282 QCOMPARE(error.column(), 23);
1283 QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
1286 void tst_qdeclarativestates::whenOrdering()
1288 QDeclarativeEngine engine;
1290 QDeclarativeComponent c(&engine, SRCDIR "/data/whenOrdering.qml");
1291 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1293 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1295 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1296 rect->setProperty("condition2", true);
1297 QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
1298 rect->setProperty("condition1", true);
1299 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1300 rect->setProperty("condition2", false);
1301 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1302 rect->setProperty("condition2", true);
1303 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1304 rect->setProperty("condition1", false);
1305 rect->setProperty("condition2", false);
1306 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1309 void tst_qdeclarativestates::urlResolution()
1311 QDeclarativeEngine engine;
1313 QDeclarativeComponent c(&engine, SRCDIR "/data/urlResolution.qml");
1314 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1317 QDeclarativeItem *myType = rect->findChild<QDeclarativeItem*>("MyType");
1318 QDeclarative1Image *image1 = rect->findChild<QDeclarative1Image*>("image1");
1319 QDeclarative1Image *image2 = rect->findChild<QDeclarative1Image*>("image2");
1320 QDeclarative1Image *image3 = rect->findChild<QDeclarative1Image*>("image3");
1321 QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
1323 QDeclarativeItemPrivate::get(myType)->setState("SetImageState");
1324 QUrl resolved = QUrl::fromLocalFile(SRCDIR "/data/Implementation/images/qt-logo.png");
1325 QCOMPARE(image1->source(), resolved);
1326 QCOMPARE(image2->source(), resolved);
1327 QCOMPARE(image3->source(), resolved);
1330 void tst_qdeclarativestates::unnamedWhen()
1332 QDeclarativeEngine engine;
1334 QDeclarativeComponent c(&engine, SRCDIR "/data/unnamedWhen.qml");
1335 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1337 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1339 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1340 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1341 rect->setProperty("triggerState", true);
1342 QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1343 QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1344 rect->setProperty("triggerState", false);
1345 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1346 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1349 void tst_qdeclarativestates::returnToBase()
1351 QDeclarativeEngine engine;
1353 QDeclarativeComponent c(&engine, SRCDIR "/data/returnToBase.qml");
1354 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1356 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1358 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1359 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1360 rect->setProperty("triggerState", true);
1361 QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1362 QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1363 rect->setProperty("triggerState", false);
1364 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1365 QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
1369 void tst_qdeclarativestates::extendsBug()
1371 QDeclarativeEngine engine;
1373 QDeclarativeComponent c(&engine, SRCDIR "/data/extendsBug.qml");
1374 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1376 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1377 QDeclarative1Rectangle *greenRect = rect->findChild<QDeclarative1Rectangle*>("greenRect");
1379 rectPrivate->setState("b");
1380 QCOMPARE(greenRect->x(), qreal(100));
1381 QCOMPARE(greenRect->y(), qreal(100));
1384 void tst_qdeclarativestates::editProperties()
1386 QDeclarativeEngine engine;
1388 QDeclarativeComponent c(&engine, SRCDIR "/data/editProperties.qml");
1389 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1392 QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
1394 QDeclarative1StateGroup *stateGroup = rectPrivate->_states();
1395 QVERIFY(stateGroup != 0);
1396 qmlExecuteDeferred(stateGroup);
1398 QDeclarative1State *blueState = stateGroup->findState("blue");
1399 QVERIFY(blueState != 0);
1400 qmlExecuteDeferred(blueState);
1402 QDeclarative1PropertyChanges *propertyChangesBlue = qobject_cast<QDeclarative1PropertyChanges*>(blueState->operationAt(0));
1403 QVERIFY(propertyChangesBlue != 0);
1405 QDeclarative1State *greenState = stateGroup->findState("green");
1406 QVERIFY(greenState != 0);
1407 qmlExecuteDeferred(greenState);
1409 QDeclarative1PropertyChanges *propertyChangesGreen = qobject_cast<QDeclarative1PropertyChanges*>(greenState->operationAt(0));
1410 QVERIFY(propertyChangesGreen != 0);
1412 QDeclarative1Rectangle *childRect = rect->findChild<QDeclarative1Rectangle*>("rect2");
1413 QVERIFY(childRect != 0);
1414 QCOMPARE(childRect->width(), qreal(402));
1415 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1416 QCOMPARE(childRect->height(), qreal(200));
1418 rectPrivate->setState("blue");
1419 QCOMPARE(childRect->width(), qreal(50));
1420 QCOMPARE(childRect->height(), qreal(40));
1421 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1422 QVERIFY(blueState->bindingInRevertList(childRect, "width"));
1425 rectPrivate->setState("green");
1426 QCOMPARE(childRect->width(), qreal(200));
1427 QCOMPARE(childRect->height(), qreal(100));
1428 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1431 rectPrivate->setState("");
1434 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1435 QVERIFY(propertyChangesBlue->containsValue("width"));
1436 QVERIFY(!propertyChangesBlue->containsProperty("x"));
1437 QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1438 QVERIFY(!propertyChangesBlue->value("x").isValid());
1440 propertyChangesBlue->changeValue("width", 60);
1441 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1442 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1445 propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1446 QVERIFY(!propertyChangesBlue->containsValue("width"));
1447 QVERIFY(propertyChangesBlue->containsExpression("width"));
1448 QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1449 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1451 propertyChangesBlue->changeValue("width", 50);
1452 QVERIFY(propertyChangesBlue->containsValue("width"));
1453 QVERIFY(!propertyChangesBlue->containsExpression("width"));
1454 QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1455 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1457 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1458 rectPrivate->setState("blue");
1459 QCOMPARE(childRect->width(), qreal(50));
1460 QCOMPARE(childRect->height(), qreal(40));
1462 propertyChangesBlue->changeValue("width", 60);
1463 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1464 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1465 QCOMPARE(childRect->width(), qreal(60));
1466 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1468 propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1469 QVERIFY(!propertyChangesBlue->containsValue("width"));
1470 QVERIFY(propertyChangesBlue->containsExpression("width"));
1471 QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1472 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1473 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1474 QCOMPARE(childRect->width(), qreal(200));
1476 propertyChangesBlue->changeValue("width", 50);
1477 QCOMPARE(childRect->width(), qreal(50));
1479 rectPrivate->setState("");
1480 QCOMPARE(childRect->width(), qreal(402));
1481 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1483 QCOMPARE(propertyChangesGreen->actions().length(), 2);
1484 rectPrivate->setState("green");
1485 QCOMPARE(childRect->width(), qreal(200));
1486 QCOMPARE(childRect->height(), qreal(100));
1487 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1488 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1489 QCOMPARE(propertyChangesGreen->actions().length(), 2);
1492 propertyChangesGreen->removeProperty("height");
1493 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "height")));
1494 QCOMPARE(childRect->height(), qreal(200));
1496 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1497 QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
1498 propertyChangesGreen->removeProperty("width");
1499 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1500 QCOMPARE(childRect->width(), qreal(402));
1501 QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
1502 QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
1504 propertyChangesBlue->removeProperty("width");
1505 QCOMPARE(childRect->width(), qreal(402));
1507 rectPrivate->setState("blue");
1508 QCOMPARE(childRect->width(), qreal(402));
1509 QCOMPARE(childRect->height(), qreal(40));
1512 void tst_qdeclarativestates::QTBUG_14830()
1514 QDeclarativeEngine engine;
1516 QDeclarativeComponent c(&engine, SRCDIR "/data/QTBUG-14830.qml");
1517 QDeclarative1Rectangle *rect = qobject_cast<QDeclarative1Rectangle*>(c.create());
1519 QDeclarativeItem *item = rect->findChild<QDeclarativeItem*>("area");
1521 QCOMPARE(item->width(), qreal(171));
1524 QTEST_MAIN(tst_qdeclarativestates)
1526 #include "tst_qdeclarativestates.moc"