1 /****************************************************************************
3 ** Copyright (C) 2011 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 <QtDeclarative/qsgview.h>
45 #include <private/qsgstateoperations_p.h>
46 #include <private/qsganchors_p_p.h>
47 #include <private/qsgrectangle_p.h>
48 #include <private/qsgimage_p.h>
49 #include <private/qdeclarativepropertychanges_p.h>
50 #include <private/qdeclarativestategroup_p.h>
51 #include <private/qsgitem_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 QSGRectangle
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 QObject
99 tst_qdeclarativestates() {}
102 static QByteArray fullDataPath(const QString &path);
108 void attachedPropertyChanges();
109 void basicExtension();
111 void signalOverride();
112 void signalOverrideCrash();
113 void signalOverrideCrash2();
115 void parentChangeErrors();
116 void anchorChanges();
117 void anchorChanges2();
118 void anchorChanges3();
119 void anchorChanges4();
120 void anchorChanges5();
121 void anchorChangesRTL();
122 void anchorChangesRTL2();
123 void anchorChangesRTL3();
124 void anchorChangesCrash();
125 void anchorRewindBug();
126 void anchorRewindBug2();
128 void restoreEntryValues();
129 void explicitChanges();
130 void propertyErrors();
131 void incorrectRestoreBug();
132 void autoStateAtStartupRestoreBug();
133 void deletingChange();
134 void deletingState();
136 void illegalTempState();
137 void nonExistantProperty();
139 void illegalObjectCreation();
141 void urlResolution();
145 void editProperties();
147 void avoidFastForward();
150 void tst_qdeclarativestates::initTestCase()
152 qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
155 QByteArray tst_qdeclarativestates::fullDataPath(const QString &path)
157 return QUrl::fromLocalFile(SRCDIR + path).toString().toUtf8();
160 void tst_qdeclarativestates::basicChanges()
162 QDeclarativeEngine engine;
165 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges.qml");
166 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
167 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
170 QCOMPARE(rect->color(),QColor("red"));
172 rectPrivate->setState("blue");
173 QCOMPARE(rect->color(),QColor("blue"));
175 rectPrivate->setState("");
176 QCOMPARE(rect->color(),QColor("red"));
180 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges2.qml");
181 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
182 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
185 QCOMPARE(rect->color(),QColor("red"));
187 rectPrivate->setState("blue");
188 QCOMPARE(rect->color(),QColor("blue"));
190 rectPrivate->setState("green");
191 QCOMPARE(rect->color(),QColor("green"));
193 rectPrivate->setState("");
194 QCOMPARE(rect->color(),QColor("red"));
196 rectPrivate->setState("green");
197 QCOMPARE(rect->color(),QColor("green"));
201 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges3.qml");
202 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
203 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
206 QCOMPARE(rect->color(),QColor("red"));
207 QCOMPARE(rect->border()->width(),1.0);
209 rectPrivate->setState("blue");
210 QCOMPARE(rect->color(),QColor("blue"));
211 QCOMPARE(rect->border()->width(),1.0);
213 rectPrivate->setState("bordered");
214 QCOMPARE(rect->color(),QColor("red"));
215 QCOMPARE(rect->border()->width(),2.0);
217 rectPrivate->setState("");
218 QCOMPARE(rect->color(),QColor("red"));
219 QCOMPARE(rect->border()->width(),1.0);
220 //### we should be checking that this is an implicit rather than explicit 1 (which currently fails)
222 rectPrivate->setState("bordered");
223 QCOMPARE(rect->color(),QColor("red"));
224 QCOMPARE(rect->border()->width(),2.0);
226 rectPrivate->setState("blue");
227 QCOMPARE(rect->color(),QColor("blue"));
228 QCOMPARE(rect->border()->width(),1.0);
233 // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
234 // signal using 'onPropertyWithNotifyChanged' even though the signal name is
235 // actually 'oddlyNamedNotifySignal'
237 QDeclarativeComponent component(&engine, SRCDIR "/data/basicChanges4.qml");
238 QVERIFY(component.isReady());
240 MyRect *rect = qobject_cast<MyRect*>(component.create());
243 QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
244 QVERIFY(prop.hasNotifySignal());
245 QString notifySignal = QByteArray(prop.notifySignal().signature());
246 QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
248 QCOMPARE(rect->color(), QColor(Qt::red));
250 rect->setPropertyWithNotify(100);
251 QCOMPARE(rect->color(), QColor(Qt::blue));
255 void tst_qdeclarativestates::attachedPropertyChanges()
257 QDeclarativeEngine engine;
259 QDeclarativeComponent component(&engine, SRCDIR "/data/attachedPropertyChanges.qml");
260 QVERIFY(component.isReady());
262 QSGItem *item = qobject_cast<QSGItem*>(component.create());
264 QCOMPARE(item->width(), 50.0);
266 // Ensure attached property has been changed
267 QObject *attObj = qmlAttachedPropertiesObject<MyRect>(item, false);
270 MyAttached *att = qobject_cast<MyAttached*>(attObj);
273 QCOMPARE(att->foo(), 1);
276 void tst_qdeclarativestates::basicExtension()
278 QDeclarativeEngine engine;
281 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicExtension.qml");
282 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
283 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
286 QCOMPARE(rect->color(),QColor("red"));
287 QCOMPARE(rect->border()->width(),1.0);
289 rectPrivate->setState("blue");
290 QCOMPARE(rect->color(),QColor("blue"));
291 QCOMPARE(rect->border()->width(),1.0);
293 rectPrivate->setState("bordered");
294 QCOMPARE(rect->color(),QColor("blue"));
295 QCOMPARE(rect->border()->width(),2.0);
297 rectPrivate->setState("blue");
298 QCOMPARE(rect->color(),QColor("blue"));
299 QCOMPARE(rect->border()->width(),1.0);
301 rectPrivate->setState("");
302 QCOMPARE(rect->color(),QColor("red"));
303 QCOMPARE(rect->border()->width(),1.0);
305 rectPrivate->setState("bordered");
306 QCOMPARE(rect->color(),QColor("blue"));
307 QCOMPARE(rect->border()->width(),2.0);
309 rectPrivate->setState("");
310 QCOMPARE(rect->color(),QColor("red"));
311 QCOMPARE(rect->border()->width(),1.0);
315 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/fakeExtension.qml");
316 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
317 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
320 QCOMPARE(rect->color(),QColor("red"));
322 rectPrivate->setState("blue");
323 QCOMPARE(rect->color(),QColor("blue"));
325 rectPrivate->setState("green");
326 QCOMPARE(rect->color(),QColor("green"));
328 rectPrivate->setState("blue");
329 QCOMPARE(rect->color(),QColor("blue"));
331 rectPrivate->setState("green");
332 QCOMPARE(rect->color(),QColor("green"));
334 rectPrivate->setState("");
335 QCOMPARE(rect->color(),QColor("red"));
337 rectPrivate->setState("green");
338 QCOMPARE(rect->color(),QColor("green"));
342 void tst_qdeclarativestates::basicBinding()
344 QDeclarativeEngine engine;
347 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding.qml");
348 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
349 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
352 QCOMPARE(rect->color(),QColor("red"));
354 rectPrivate->setState("blue");
355 QCOMPARE(rect->color(),QColor("blue"));
357 rectPrivate->setState("");
358 QCOMPARE(rect->color(),QColor("red"));
360 rectPrivate->setState("blue");
361 QCOMPARE(rect->color(),QColor("blue"));
362 rect->setProperty("sourceColor", QColor("green"));
363 QCOMPARE(rect->color(),QColor("green"));
365 rectPrivate->setState("");
366 QCOMPARE(rect->color(),QColor("red"));
367 rect->setProperty("sourceColor", QColor("yellow"));
368 QCOMPARE(rect->color(),QColor("red"));
370 rectPrivate->setState("blue");
371 QCOMPARE(rect->color(),QColor("yellow"));
375 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding2.qml");
376 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
377 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
380 QCOMPARE(rect->color(),QColor("red"));
382 rectPrivate->setState("blue");
383 QCOMPARE(rect->color(),QColor("blue"));
385 rectPrivate->setState("");
386 QCOMPARE(rect->color(),QColor("red"));
388 rectPrivate->setState("blue");
389 QCOMPARE(rect->color(),QColor("blue"));
390 rect->setProperty("sourceColor", QColor("green"));
391 QCOMPARE(rect->color(),QColor("blue"));
393 rectPrivate->setState("");
394 QCOMPARE(rect->color(),QColor("green"));
395 rect->setProperty("sourceColor", QColor("yellow"));
396 QCOMPARE(rect->color(),QColor("yellow"));
398 rectPrivate->setState("blue");
399 QCOMPARE(rect->color(),QColor("blue"));
401 rectPrivate->setState("");
402 QCOMPARE(rect->color(),QColor("yellow"));
406 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding3.qml");
407 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
408 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
411 QCOMPARE(rect->color(),QColor("red"));
412 rect->setProperty("sourceColor", QColor("green"));
413 QCOMPARE(rect->color(),QColor("green"));
415 rectPrivate->setState("blue");
416 QCOMPARE(rect->color(),QColor("blue"));
417 rect->setProperty("sourceColor", QColor("red"));
418 QCOMPARE(rect->color(),QColor("blue"));
419 rect->setProperty("sourceColor2", QColor("yellow"));
420 QCOMPARE(rect->color(),QColor("yellow"));
422 rectPrivate->setState("");
423 QCOMPARE(rect->color(),QColor("red"));
424 rect->setProperty("sourceColor2", QColor("green"));
425 QCOMPARE(rect->color(),QColor("red"));
426 rect->setProperty("sourceColor", QColor("yellow"));
427 QCOMPARE(rect->color(),QColor("yellow"));
431 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicBinding4.qml");
432 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
433 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
436 QCOMPARE(rect->color(),QColor("red"));
438 rectPrivate->setState("blue");
439 QCOMPARE(rect->color(),QColor("blue"));
440 rect->setProperty("sourceColor", QColor("yellow"));
441 QCOMPARE(rect->color(),QColor("yellow"));
443 rectPrivate->setState("green");
444 QCOMPARE(rect->color(),QColor("green"));
445 rect->setProperty("sourceColor", QColor("purple"));
446 QCOMPARE(rect->color(),QColor("green"));
448 rectPrivate->setState("blue");
449 QCOMPARE(rect->color(),QColor("purple"));
451 rectPrivate->setState("green");
452 QCOMPARE(rect->color(),QColor("green"));
454 rectPrivate->setState("");
455 QCOMPARE(rect->color(),QColor("red"));
459 void tst_qdeclarativestates::signalOverride()
461 QDeclarativeEngine engine;
464 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverride.qml");
465 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
468 QCOMPARE(rect->color(),QColor("red"));
470 QCOMPARE(rect->color(),QColor("blue"));
472 QSGItemPrivate::get(rect)->setState("green");
474 QCOMPARE(rect->color(),QColor("green"));
478 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverride2.qml");
479 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
482 QCOMPARE(rect->color(),QColor("white"));
484 QCOMPARE(rect->color(),QColor("blue"));
486 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("extendedRect"));
487 QSGItemPrivate::get(innerRect)->setState("green");
489 QCOMPARE(rect->color(),QColor("blue"));
490 QCOMPARE(innerRect->color(),QColor("green"));
491 QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
495 void tst_qdeclarativestates::signalOverrideCrash()
497 QDeclarativeEngine engine;
499 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverrideCrash.qml");
500 MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
503 QSGItemPrivate::get(rect)->setState("overridden");
507 void tst_qdeclarativestates::signalOverrideCrash2()
509 QDeclarativeEngine engine;
511 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/signalOverrideCrash2.qml");
512 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
515 QSGItemPrivate::get(rect)->setState("state1");
516 QSGItemPrivate::get(rect)->setState("state2");
517 QSGItemPrivate::get(rect)->setState("state1");
522 void tst_qdeclarativestates::parentChange()
524 QDeclarativeEngine engine;
527 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange1.qml");
528 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
531 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
532 QVERIFY(innerRect != 0);
534 QDeclarativeListReference list(rect, "states");
535 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
538 qmlExecuteDeferred(state);
539 QSGParentChange *pChange = qobject_cast<QSGParentChange*>(state->operationAt(0));
540 QVERIFY(pChange != 0);
541 QSGItem *nParent = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("NewParent"));
542 QVERIFY(nParent != 0);
544 QCOMPARE(pChange->parent(), nParent);
546 QSGItemPrivate::get(rect)->setState("reparented");
547 QCOMPARE(innerRect->rotation(), qreal(0));
548 QCOMPARE(innerRect->scale(), qreal(1));
549 QCOMPARE(innerRect->x(), qreal(-133));
550 QCOMPARE(innerRect->y(), qreal(-300));
554 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange2.qml");
555 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
557 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
558 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
559 QVERIFY(innerRect != 0);
561 rectPrivate->setState("reparented");
562 QCOMPARE(innerRect->rotation(), qreal(15));
563 QCOMPARE(innerRect->scale(), qreal(.5));
564 QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-19.9075));
565 QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-8.73433));
569 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange3.qml");
570 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
572 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
573 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
574 QVERIFY(innerRect != 0);
576 rectPrivate->setState("reparented");
577 QCOMPARE(innerRect->rotation(), qreal(-37));
578 QCOMPARE(innerRect->scale(), qreal(.25));
579 QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-217.305));
580 QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-164.413));
582 rectPrivate->setState("");
583 QCOMPARE(innerRect->rotation(), qreal(0));
584 QCOMPARE(innerRect->scale(), qreal(1));
585 QCOMPARE(innerRect->x(), qreal(5));
586 //do a non-qFuzzyCompare fuzzy compare
587 QVERIFY(innerRect->y() < qreal(0.00001) && innerRect->y() > qreal(-0.00001));
591 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange6.qml");
592 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
595 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
596 QVERIFY(innerRect != 0);
598 QSGItemPrivate::get(rect)->setState("reparented");
599 QCOMPARE(innerRect->rotation(), qreal(180));
600 QCOMPARE(innerRect->scale(), qreal(1));
601 QCOMPARE(innerRect->x(), qreal(-105));
602 QCOMPARE(innerRect->y(), qreal(-105));
606 void tst_qdeclarativestates::parentChangeErrors()
608 QDeclarativeEngine engine;
611 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange4.qml");
612 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
615 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
616 QVERIFY(innerRect != 0);
618 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/parentChange4.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under non-uniform scale");
619 QSGItemPrivate::get(rect)->setState("reparented");
620 QCOMPARE(innerRect->rotation(), qreal(0));
621 QCOMPARE(innerRect->scale(), qreal(1));
622 QCOMPARE(innerRect->x(), qreal(5));
623 QCOMPARE(innerRect->y(), qreal(5));
627 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/parentChange5.qml");
628 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
631 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
632 QVERIFY(innerRect != 0);
634 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/parentChange5.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under complex transform");
635 QSGItemPrivate::get(rect)->setState("reparented");
636 QCOMPARE(innerRect->rotation(), qreal(0));
637 QCOMPARE(innerRect->scale(), qreal(1));
638 QCOMPARE(innerRect->x(), qreal(5));
639 QCOMPARE(innerRect->y(), qreal(5));
643 void tst_qdeclarativestates::anchorChanges()
645 QDeclarativeEngine engine;
647 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges1.qml");
648 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
650 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
652 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
653 QVERIFY(innerRect != 0);
655 QDeclarativeListReference list(rect, "states");
656 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
659 qmlExecuteDeferred(state);
660 QSGAnchorChanges *aChanges = qobject_cast<QSGAnchorChanges*>(state->operationAt(0));
661 QVERIFY(aChanges != 0);
663 rectPrivate->setState("right");
664 QCOMPARE(innerRect->x(), qreal(150));
665 QCOMPARE(aChanges->object(), qobject_cast<QSGItem*>(innerRect));
666 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QSGAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
667 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
668 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
670 rectPrivate->setState("");
671 QCOMPARE(innerRect->x(), qreal(5));
676 void tst_qdeclarativestates::anchorChanges2()
678 QDeclarativeEngine engine;
680 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges2.qml");
681 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
683 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
685 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
686 QVERIFY(innerRect != 0);
688 rectPrivate->setState("right");
689 QCOMPARE(innerRect->x(), qreal(150));
691 rectPrivate->setState("");
692 QCOMPARE(innerRect->x(), qreal(5));
697 void tst_qdeclarativestates::anchorChanges3()
699 QDeclarativeEngine engine;
701 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges3.qml");
702 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
704 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
706 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
707 QVERIFY(innerRect != 0);
709 QSGItem *leftGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("LeftGuideline"));
710 QVERIFY(leftGuideline != 0);
712 QSGItem *bottomGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("BottomGuideline"));
713 QVERIFY(bottomGuideline != 0);
715 QDeclarativeListReference list(rect, "states");
716 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
719 qmlExecuteDeferred(state);
720 QSGAnchorChanges *aChanges = qobject_cast<QSGAnchorChanges*>(state->operationAt(0));
721 QVERIFY(aChanges != 0);
723 rectPrivate->setState("reanchored");
724 QCOMPARE(aChanges->object(), qobject_cast<QSGItem*>(innerRect));
725 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->left().item, QSGItemPrivate::get(leftGuideline)->left().item);
726 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QSGItemPrivate::get(leftGuideline)->left().anchorLine);
727 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
728 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
729 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
730 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
731 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->bottom().item, QSGItemPrivate::get(bottomGuideline)->bottom().item);
732 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QSGItemPrivate::get(bottomGuideline)->bottom().anchorLine);
734 QCOMPARE(innerRect->x(), qreal(10));
735 QCOMPARE(innerRect->y(), qreal(0));
736 QCOMPARE(innerRect->width(), qreal(190));
737 QCOMPARE(innerRect->height(), qreal(150));
739 rectPrivate->setState("");
740 QCOMPARE(innerRect->x(), qreal(0));
741 QCOMPARE(innerRect->y(), qreal(10));
742 QCOMPARE(innerRect->width(), qreal(150));
743 QCOMPARE(innerRect->height(), qreal(190));
748 void tst_qdeclarativestates::anchorChanges4()
750 QDeclarativeEngine engine;
752 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges4.qml");
753 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
756 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
757 QVERIFY(innerRect != 0);
759 QSGItem *leftGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("LeftGuideline"));
760 QVERIFY(leftGuideline != 0);
762 QSGItem *bottomGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("BottomGuideline"));
763 QVERIFY(bottomGuideline != 0);
765 QDeclarativeListReference list(rect, "states");
766 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
769 qmlExecuteDeferred(state);
770 QSGAnchorChanges *aChanges = qobject_cast<QSGAnchorChanges*>(state->operationAt(0));
771 QVERIFY(aChanges != 0);
773 QSGItemPrivate::get(rect)->setState("reanchored");
774 QCOMPARE(aChanges->object(), qobject_cast<QSGItem*>(innerRect));
775 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QSGItemPrivate::get(bottomGuideline)->horizontalCenter().item);
776 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QSGItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
777 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QSGItemPrivate::get(leftGuideline)->verticalCenter().item);
778 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QSGItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
783 void tst_qdeclarativestates::anchorChanges5()
785 QDeclarativeEngine engine;
787 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges5.qml");
788 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
791 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
792 QVERIFY(innerRect != 0);
794 QSGItem *leftGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("LeftGuideline"));
795 QVERIFY(leftGuideline != 0);
797 QSGItem *bottomGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("BottomGuideline"));
798 QVERIFY(bottomGuideline != 0);
800 QDeclarativeListReference list(rect, "states");
801 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
804 qmlExecuteDeferred(state);
805 QSGAnchorChanges *aChanges = qobject_cast<QSGAnchorChanges*>(state->operationAt(0));
806 QVERIFY(aChanges != 0);
808 QSGItemPrivate::get(rect)->setState("reanchored");
809 QCOMPARE(aChanges->object(), qobject_cast<QSGItem*>(innerRect));
810 //QCOMPARE(aChanges->anchors()->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
811 //QCOMPARE(aChanges->anchors()->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
812 //QCOMPARE(aChanges->anchors()->baseline().item, leftGuideline->baseline().item);
813 //QCOMPARE(aChanges->anchors()->baseline().anchorLine, leftGuideline->baseline().anchorLine);
818 void mirrorAnchors(QSGItem *item) {
819 QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
820 itemPrivate->setLayoutMirror(true);
823 qreal offsetRTL(QSGItem *anchorItem, QSGItem *item) {
824 return anchorItem->width()+2*anchorItem->x()-item->width();
827 void tst_qdeclarativestates::anchorChangesRTL()
829 QDeclarativeEngine engine;
831 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges1.qml");
832 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
834 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
836 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
837 QVERIFY(innerRect != 0);
838 mirrorAnchors(innerRect);
840 QDeclarativeListReference list(rect, "states");
841 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
844 qmlExecuteDeferred(state);
845 QSGAnchorChanges *aChanges = qobject_cast<QSGAnchorChanges*>(state->operationAt(0));
846 QVERIFY(aChanges != 0);
848 rectPrivate->setState("right");
849 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
850 QCOMPARE(aChanges->object(), qobject_cast<QSGItem*>(innerRect));
851 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QSGAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
852 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
853 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
855 rectPrivate->setState("");
856 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
861 void tst_qdeclarativestates::anchorChangesRTL2()
863 QDeclarativeEngine engine;
865 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges2.qml");
866 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
868 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
870 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
871 QVERIFY(innerRect != 0);
872 mirrorAnchors(innerRect);
874 rectPrivate->setState("right");
875 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
877 rectPrivate->setState("");
878 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
883 void tst_qdeclarativestates::anchorChangesRTL3()
885 QDeclarativeEngine engine;
887 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges3.qml");
888 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
890 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
892 QSGRectangle *innerRect = qobject_cast<QSGRectangle*>(rect->findChild<QSGRectangle*>("MyRect"));
893 QVERIFY(innerRect != 0);
894 mirrorAnchors(innerRect);
896 QSGItem *leftGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("LeftGuideline"));
897 QVERIFY(leftGuideline != 0);
899 QSGItem *bottomGuideline = qobject_cast<QSGItem*>(rect->findChild<QSGItem*>("BottomGuideline"));
900 QVERIFY(bottomGuideline != 0);
902 QDeclarativeListReference list(rect, "states");
903 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
906 qmlExecuteDeferred(state);
907 QSGAnchorChanges *aChanges = qobject_cast<QSGAnchorChanges*>(state->operationAt(0));
908 QVERIFY(aChanges != 0);
910 rectPrivate->setState("reanchored");
911 QCOMPARE(aChanges->object(), qobject_cast<QSGItem*>(innerRect));
912 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->left().item, QSGItemPrivate::get(leftGuideline)->left().item);
913 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QSGItemPrivate::get(leftGuideline)->left().anchorLine);
914 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
915 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
916 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
917 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
918 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->bottom().item, QSGItemPrivate::get(bottomGuideline)->bottom().item);
919 QCOMPARE(QSGItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QSGItemPrivate::get(bottomGuideline)->bottom().anchorLine);
921 QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
922 QCOMPARE(innerRect->y(), qreal(0));
923 // between left side of parent and leftGuideline.x: 10, which has width 0
924 QCOMPARE(innerRect->width(), qreal(10));
925 QCOMPARE(innerRect->height(), qreal(150));
927 rectPrivate->setState("");
928 QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
929 QCOMPARE(innerRect->y(), qreal(10));
930 // between right side of parent and left side of rightGuideline.x: 150, which has width 0
931 QCOMPARE(innerRect->width(), qreal(50));
932 QCOMPARE(innerRect->height(), qreal(190));
938 void tst_qdeclarativestates::anchorChangesCrash()
940 QDeclarativeEngine engine;
942 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChangesCrash.qml");
943 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
946 QSGItemPrivate::get(rect)->setState("reanchored");
952 void tst_qdeclarativestates::anchorRewindBug()
954 QSGView *view = new QSGView;
955 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/anchorRewindBug.qml"));
958 view->requestActivateWindow();
960 QTest::qWaitForWindowShown(view);
962 QSGRectangle *rect = qobject_cast<QSGRectangle*>(view->rootObject());
965 QSGItem * column = rect->findChild<QSGItem*>("column");
967 QVERIFY(column != 0);
968 QVERIFY(!QSGItemPrivate::get(column)->heightValid);
969 QVERIFY(!QSGItemPrivate::get(column)->widthValid);
970 QCOMPARE(column->height(), 200.0);
971 QSGItemPrivate::get(rect)->setState("reanchored");
973 // column height and width should stay implicit
974 // and column's implicit resizing should still work
975 QVERIFY(!QSGItemPrivate::get(column)->heightValid);
976 QVERIFY(!QSGItemPrivate::get(column)->widthValid);
977 QTRY_COMPARE(column->height(), 100.0);
979 QSGItemPrivate::get(rect)->setState("");
981 // column height and width should stay implicit
982 // and column's implicit resizing should still work
983 QVERIFY(!QSGItemPrivate::get(column)->heightValid);
984 QVERIFY(!QSGItemPrivate::get(column)->widthValid);
985 QTRY_COMPARE(column->height(), 200.0);
991 void tst_qdeclarativestates::anchorRewindBug2()
993 QDeclarativeEngine engine;
995 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorRewindBug2.qml");
996 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
999 QSGRectangle *mover = rect->findChild<QSGRectangle*>("mover");
1001 QVERIFY(mover != 0);
1002 QCOMPARE(mover->y(), qreal(0.0));
1003 QCOMPARE(mover->width(), qreal(50.0));
1005 QSGItemPrivate::get(rect)->setState("anchored");
1006 QCOMPARE(mover->y(), qreal(250.0));
1007 QCOMPARE(mover->width(), qreal(200.0));
1009 QSGItemPrivate::get(rect)->setState("");
1010 QCOMPARE(mover->y(), qreal(0.0));
1011 QCOMPARE(mover->width(), qreal(50.0));
1016 void tst_qdeclarativestates::script()
1018 QDeclarativeEngine engine;
1021 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/script.qml");
1022 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1024 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1025 QCOMPARE(rect->color(),QColor("red"));
1027 rectPrivate->setState("blue");
1028 QCOMPARE(rect->color(),QColor("blue"));
1030 rectPrivate->setState("");
1031 QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
1035 void tst_qdeclarativestates::restoreEntryValues()
1037 QDeclarativeEngine engine;
1039 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/restoreEntryValues.qml");
1040 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1042 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1043 QCOMPARE(rect->color(),QColor("red"));
1045 rectPrivate->setState("blue");
1046 QCOMPARE(rect->color(),QColor("blue"));
1048 rectPrivate->setState("");
1049 QCOMPARE(rect->color(),QColor("blue"));
1052 void tst_qdeclarativestates::explicitChanges()
1054 QDeclarativeEngine engine;
1056 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/explicit.qml");
1057 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1059 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1060 QDeclarativeListReference list(rect, "states");
1061 QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
1062 QVERIFY(state != 0);
1064 qmlExecuteDeferred(state);
1065 QDeclarativePropertyChanges *changes = qobject_cast<QDeclarativePropertyChanges*>(rect->findChild<QDeclarativePropertyChanges*>("changes"));
1066 QVERIFY(changes != 0);
1067 QVERIFY(changes->isExplicit());
1069 QCOMPARE(rect->color(),QColor("red"));
1071 rectPrivate->setState("blue");
1072 QCOMPARE(rect->color(),QColor("blue"));
1074 rect->setProperty("sourceColor", QColor("green"));
1075 QCOMPARE(rect->color(),QColor("blue"));
1077 rectPrivate->setState("");
1078 QCOMPARE(rect->color(),QColor("red"));
1079 rect->setProperty("sourceColor", QColor("yellow"));
1080 QCOMPARE(rect->color(),QColor("red"));
1082 rectPrivate->setState("blue");
1083 QCOMPARE(rect->color(),QColor("yellow"));
1086 void tst_qdeclarativestates::propertyErrors()
1088 QDeclarativeEngine engine;
1089 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/propertyErrors.qml");
1090 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1093 QCOMPARE(rect->color(),QColor("red"));
1095 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1096 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
1097 QSGItemPrivate::get(rect)->setState("blue");
1100 void tst_qdeclarativestates::incorrectRestoreBug()
1102 QDeclarativeEngine engine;
1104 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/basicChanges.qml");
1105 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1107 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1108 QCOMPARE(rect->color(),QColor("red"));
1110 rectPrivate->setState("blue");
1111 QCOMPARE(rect->color(),QColor("blue"));
1113 rectPrivate->setState("");
1114 QCOMPARE(rect->color(),QColor("red"));
1116 // make sure if we change the base state value, we then restore to it correctly
1117 rect->setColor(QColor("green"));
1119 rectPrivate->setState("blue");
1120 QCOMPARE(rect->color(),QColor("blue"));
1122 rectPrivate->setState("");
1123 QCOMPARE(rect->color(),QColor("green"));
1126 void tst_qdeclarativestates::autoStateAtStartupRestoreBug()
1128 QDeclarativeEngine engine;
1130 QDeclarativeComponent component(&engine, SRCDIR "/data/autoStateAtStartupRestoreBug.qml");
1131 QObject *obj = component.create();
1134 QCOMPARE(obj->property("test").toInt(), 3);
1136 obj->setProperty("input", 2);
1138 QCOMPARE(obj->property("test").toInt(), 9);
1143 void tst_qdeclarativestates::deletingChange()
1145 QDeclarativeEngine engine;
1147 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/deleting.qml");
1148 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1150 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1151 rectPrivate->setState("blue");
1152 QCOMPARE(rect->color(),QColor("blue"));
1153 QCOMPARE(rect->radius(),qreal(5));
1155 rectPrivate->setState("");
1156 QCOMPARE(rect->color(),QColor("red"));
1157 QCOMPARE(rect->radius(),qreal(0));
1159 QDeclarativePropertyChanges *pc = rect->findChild<QDeclarativePropertyChanges*>("pc1");
1163 QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
1164 QVERIFY(state != 0);
1165 qmlExecuteDeferred(state);
1166 QCOMPARE(state->operationCount(), 1);
1168 rectPrivate->setState("blue");
1169 QCOMPARE(rect->color(),QColor("red"));
1170 QCOMPARE(rect->radius(),qreal(5));
1175 void tst_qdeclarativestates::deletingState()
1177 QDeclarativeEngine engine;
1179 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/deletingState.qml");
1180 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1183 QDeclarativeStateGroup *sg = rect->findChild<QDeclarativeStateGroup*>();
1185 QVERIFY(sg->findState("blue") != 0);
1187 sg->setState("blue");
1188 QCOMPARE(rect->color(),QColor("blue"));
1191 QCOMPARE(rect->color(),QColor("red"));
1193 QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
1194 QVERIFY(state != 0);
1197 QVERIFY(sg->findState("blue") == 0);
1199 //### should we warn that state doesn't exist
1200 sg->setState("blue");
1201 QCOMPARE(rect->color(),QColor("red"));
1206 void tst_qdeclarativestates::tempState()
1208 QDeclarativeEngine engine;
1210 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/legalTempState.qml");
1211 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1213 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1214 QTest::ignoreMessage(QtDebugMsg, "entering placed");
1215 QTest::ignoreMessage(QtDebugMsg, "entering idle");
1216 rectPrivate->setState("placed");
1217 QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
1220 void tst_qdeclarativestates::illegalTempState()
1222 QDeclarativeEngine engine;
1224 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/illegalTempState.qml");
1225 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1227 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1228 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
1229 rectPrivate->setState("placed");
1230 QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
1233 void tst_qdeclarativestates::nonExistantProperty()
1235 QDeclarativeEngine engine;
1237 QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/nonExistantProp.qml");
1238 QSGRectangle *rect = qobject_cast<QSGRectangle*>(rectComponent.create());
1240 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1241 QTest::ignoreMessage(QtWarningMsg, fullDataPath("/data/nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
1242 rectPrivate->setState("blue");
1243 QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
1246 void tst_qdeclarativestates::reset()
1248 QDeclarativeEngine engine;
1250 QDeclarativeComponent c(&engine, SRCDIR "/data/reset.qml");
1251 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1254 QSGImage *image = rect->findChild<QSGImage*>();
1255 QVERIFY(image != 0);
1256 QCOMPARE(image->width(), qreal(40.));
1257 QCOMPARE(image->height(), qreal(20.));
1259 QSGItemPrivate::get(rect)->setState("state1");
1261 QCOMPARE(image->width(), 20.0);
1262 QCOMPARE(image->height(), qreal(20.));
1265 void tst_qdeclarativestates::illegalObjectCreation()
1267 QDeclarativeEngine engine;
1269 QDeclarativeComponent component(&engine, SRCDIR "/data/illegalObj.qml");
1270 QList<QDeclarativeError> errors = component.errors();
1271 QVERIFY(errors.count() == 1);
1272 const QDeclarativeError &error = errors.at(0);
1273 QCOMPARE(error.line(), 9);
1274 QCOMPARE(error.column(), 23);
1275 QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
1278 void tst_qdeclarativestates::whenOrdering()
1280 QDeclarativeEngine engine;
1282 QDeclarativeComponent c(&engine, SRCDIR "/data/whenOrdering.qml");
1283 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1285 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1287 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1288 rect->setProperty("condition2", true);
1289 QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
1290 rect->setProperty("condition1", true);
1291 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1292 rect->setProperty("condition2", false);
1293 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1294 rect->setProperty("condition2", true);
1295 QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
1296 rect->setProperty("condition1", false);
1297 rect->setProperty("condition2", false);
1298 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1301 void tst_qdeclarativestates::urlResolution()
1303 QDeclarativeEngine engine;
1305 QDeclarativeComponent c(&engine, SRCDIR "/data/urlResolution.qml");
1306 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1309 QSGItem *myType = rect->findChild<QSGItem*>("MyType");
1310 QSGImage *image1 = rect->findChild<QSGImage*>("image1");
1311 QSGImage *image2 = rect->findChild<QSGImage*>("image2");
1312 QSGImage *image3 = rect->findChild<QSGImage*>("image3");
1313 QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
1315 QSGItemPrivate::get(myType)->setState("SetImageState");
1316 QUrl resolved = QUrl::fromLocalFile(SRCDIR "/data/Implementation/images/qt-logo.png");
1317 QCOMPARE(image1->source(), resolved);
1318 QCOMPARE(image2->source(), resolved);
1319 QCOMPARE(image3->source(), resolved);
1322 void tst_qdeclarativestates::unnamedWhen()
1324 QDeclarativeEngine engine;
1326 QDeclarativeComponent c(&engine, SRCDIR "/data/unnamedWhen.qml");
1327 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1329 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1331 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1332 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1333 rect->setProperty("triggerState", true);
1334 QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1335 QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1336 rect->setProperty("triggerState", false);
1337 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1338 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1341 void tst_qdeclarativestates::returnToBase()
1343 QDeclarativeEngine engine;
1345 QDeclarativeComponent c(&engine, SRCDIR "/data/returnToBase.qml");
1346 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1348 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1350 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1351 QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
1352 rect->setProperty("triggerState", true);
1353 QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
1354 QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
1355 rect->setProperty("triggerState", false);
1356 QCOMPARE(rectPrivate->state(), QLatin1String(""));
1357 QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
1361 void tst_qdeclarativestates::extendsBug()
1363 QDeclarativeEngine engine;
1365 QDeclarativeComponent c(&engine, SRCDIR "/data/extendsBug.qml");
1366 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1368 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1369 QSGRectangle *greenRect = rect->findChild<QSGRectangle*>("greenRect");
1371 rectPrivate->setState("b");
1372 QCOMPARE(greenRect->x(), qreal(100));
1373 QCOMPARE(greenRect->y(), qreal(100));
1376 void tst_qdeclarativestates::editProperties()
1378 QDeclarativeEngine engine;
1380 QDeclarativeComponent c(&engine, SRCDIR "/data/editProperties.qml");
1381 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1384 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1386 QDeclarativeStateGroup *stateGroup = rectPrivate->_states();
1387 QVERIFY(stateGroup != 0);
1388 qmlExecuteDeferred(stateGroup);
1390 QDeclarativeState *blueState = stateGroup->findState("blue");
1391 QVERIFY(blueState != 0);
1392 qmlExecuteDeferred(blueState);
1394 QDeclarativePropertyChanges *propertyChangesBlue = qobject_cast<QDeclarativePropertyChanges*>(blueState->operationAt(0));
1395 QVERIFY(propertyChangesBlue != 0);
1397 QDeclarativeState *greenState = stateGroup->findState("green");
1398 QVERIFY(greenState != 0);
1399 qmlExecuteDeferred(greenState);
1401 QDeclarativePropertyChanges *propertyChangesGreen = qobject_cast<QDeclarativePropertyChanges*>(greenState->operationAt(0));
1402 QVERIFY(propertyChangesGreen != 0);
1404 QSGRectangle *childRect = rect->findChild<QSGRectangle*>("rect2");
1405 QVERIFY(childRect != 0);
1406 QCOMPARE(childRect->width(), qreal(402));
1407 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1408 QCOMPARE(childRect->height(), qreal(200));
1410 rectPrivate->setState("blue");
1411 QCOMPARE(childRect->width(), qreal(50));
1412 QCOMPARE(childRect->height(), qreal(40));
1413 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1414 QVERIFY(blueState->bindingInRevertList(childRect, "width"));
1417 rectPrivate->setState("green");
1418 QCOMPARE(childRect->width(), qreal(200));
1419 QCOMPARE(childRect->height(), qreal(100));
1420 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1423 rectPrivate->setState("");
1426 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1427 QVERIFY(propertyChangesBlue->containsValue("width"));
1428 QVERIFY(!propertyChangesBlue->containsProperty("x"));
1429 QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1430 QVERIFY(!propertyChangesBlue->value("x").isValid());
1432 propertyChangesBlue->changeValue("width", 60);
1433 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1434 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1437 propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
1438 QVERIFY(!propertyChangesBlue->containsValue("width"));
1439 QVERIFY(propertyChangesBlue->containsExpression("width"));
1440 QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
1441 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1443 propertyChangesBlue->changeValue("width", 50);
1444 QVERIFY(propertyChangesBlue->containsValue("width"));
1445 QVERIFY(!propertyChangesBlue->containsExpression("width"));
1446 QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
1447 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1449 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1450 rectPrivate->setState("blue");
1451 QCOMPARE(childRect->width(), qreal(50));
1452 QCOMPARE(childRect->height(), qreal(40));
1454 propertyChangesBlue->changeValue("width", 60);
1455 QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
1456 QCOMPARE(propertyChangesBlue->actions().length(), 2);
1457 QCOMPARE(childRect->width(), qreal(60));
1458 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
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);
1465 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1466 QCOMPARE(childRect->width(), qreal(200));
1468 propertyChangesBlue->changeValue("width", 50);
1469 QCOMPARE(childRect->width(), qreal(50));
1471 rectPrivate->setState("");
1472 QCOMPARE(childRect->width(), qreal(402));
1473 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1475 QCOMPARE(propertyChangesGreen->actions().length(), 2);
1476 rectPrivate->setState("green");
1477 QCOMPARE(childRect->width(), qreal(200));
1478 QCOMPARE(childRect->height(), qreal(100));
1479 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1480 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1481 QCOMPARE(propertyChangesGreen->actions().length(), 2);
1484 propertyChangesGreen->removeProperty("height");
1485 QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "height")));
1486 QCOMPARE(childRect->height(), qreal(200));
1488 QVERIFY(greenState->bindingInRevertList(childRect, "width"));
1489 QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
1490 propertyChangesGreen->removeProperty("width");
1491 QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
1492 QCOMPARE(childRect->width(), qreal(402));
1493 QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
1494 QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
1496 propertyChangesBlue->removeProperty("width");
1497 QCOMPARE(childRect->width(), qreal(402));
1499 rectPrivate->setState("blue");
1500 QCOMPARE(childRect->width(), qreal(402));
1501 QCOMPARE(childRect->height(), qreal(40));
1504 void tst_qdeclarativestates::QTBUG_14830()
1506 QDeclarativeEngine engine;
1508 QDeclarativeComponent c(&engine, SRCDIR "/data/QTBUG-14830.qml");
1509 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1511 QSGItem *item = rect->findChild<QSGItem*>("area");
1513 QCOMPARE(item->width(), qreal(171));
1516 void tst_qdeclarativestates::avoidFastForward()
1518 QDeclarativeEngine engine;
1520 //shouldn't fast forward if there isn't a transition
1521 QDeclarativeComponent c(&engine, SRCDIR "/data/avoidFastForward.qml");
1522 QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
1525 QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
1526 rectPrivate->setState("a");
1527 QCOMPARE(rect->property("updateCount").toInt(), 1);
1530 QTEST_MAIN(tst_qdeclarativestates)
1532 #include "tst_qdeclarativestates.moc"