aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquickstates/tst_qquickstates.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/qquickstates/tst_qquickstates.cpp')
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp396
1 files changed, 340 insertions, 56 deletions
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index cbc36ad1b5..3bdbe29d1e 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -37,7 +12,8 @@
#include <QtQuick/private/qquickstategroup_p.h>
#include <private/qquickitem_p.h>
#include <private/qqmlproperty_p.h>
-#include "../../shared/util.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtTest/qsignalspy.h>
class MyAttached : public QObject
{
@@ -143,7 +119,12 @@ class tst_qquickstates : public QQmlDataTest
{
Q_OBJECT
public:
- tst_qquickstates() {}
+ tst_qquickstates() : QQmlDataTest(QT_QMLTEST_DATADIR)
+ {
+#ifdef QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
+ qputenv("QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES", "1");
+#endif
+ }
private:
QByteArray fullDataPath(const QString &path) const;
@@ -199,9 +180,18 @@ private slots:
void revertListMemoryLeak();
void duplicateStateName();
void trivialWhen();
+ void jsValueWhen_data();
+ void jsValueWhen();
+ void noStateOsciallation();
void parentChangeCorrectReversal();
void revertNullObjectBinding();
void bindableProperties();
+ void parentChangeInvolvingBindings();
+ void deferredProperties();
+ void rewindAnchorChange();
+ void rewindAnchorChangeSize();
+ void bindingProperlyRemovedWithTransition();
+ void doNotCrashOnBroken();
};
void tst_qquickstates::initTestCase()
@@ -1053,23 +1043,23 @@ void tst_qquickstates::anchorRewindBug()
QQuickItem * column = rect->findChild<QQuickItem*>("column");
QVERIFY(column != nullptr);
- QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
- QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
+ QVERIFY(!QQuickItemPrivate::get(column)->heightValid());
+ QVERIFY(!QQuickItemPrivate::get(column)->widthValid());
QCOMPARE(column->height(), 200.0);
QQuickItemPrivate::get(rect)->setState("reanchored");
// column height and width should stay implicit
// and column's implicit resizing should still work
- QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
- QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
+ QVERIFY(!QQuickItemPrivate::get(column)->heightValid());
+ QVERIFY(!QQuickItemPrivate::get(column)->widthValid());
QTRY_COMPARE(column->height(), 100.0);
QQuickItemPrivate::get(rect)->setState("");
// column height and width should stay implicit
// and column's implicit resizing should still work
- QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
- QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
+ QVERIFY(!QQuickItemPrivate::get(column)->heightValid());
+ QVERIFY(!QQuickItemPrivate::get(column)->widthValid());
QTRY_COMPARE(column->height(), 200.0);
}
@@ -1346,7 +1336,7 @@ void tst_qquickstates::illegalObjectCreation()
QQmlComponent component(&engine, testFileUrl("illegalObj.qml"));
QList<QQmlError> errors = component.errors();
- QCOMPARE(errors.count(), 1);
+ QCOMPARE(errors.size(), 1);
const QQmlError &error = errors.at(0);
QCOMPARE(error.line(), 9);
QCOMPARE(error.column(), 23);
@@ -1482,7 +1472,7 @@ void tst_qquickstates::editProperties()
QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
QVERIFY(childRect != nullptr);
QCOMPARE(childRect->width(), qreal(402));
- QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QVERIFY(QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
QCOMPARE(childRect->height(), qreal(200));
rectPrivate->setState("blue");
@@ -1501,7 +1491,7 @@ void tst_qquickstates::editProperties()
rectPrivate->setState("");
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QCOMPARE(propertyChangesBlue->actions().size(), 2);
QVERIFY(propertyChangesBlue->containsValue("width"));
QVERIFY(!propertyChangesBlue->containsProperty("x"));
QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
@@ -1509,38 +1499,38 @@ void tst_qquickstates::editProperties()
propertyChangesBlue->changeValue("width", 60);
QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QCOMPARE(propertyChangesBlue->actions().size(), 2);
propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
QVERIFY(!propertyChangesBlue->containsValue("width"));
QVERIFY(propertyChangesBlue->containsExpression("width"));
QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QCOMPARE(propertyChangesBlue->actions().size(), 2);
propertyChangesBlue->changeValue("width", 50);
QVERIFY(propertyChangesBlue->containsValue("width"));
QVERIFY(!propertyChangesBlue->containsExpression("width"));
QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QCOMPARE(propertyChangesBlue->actions().size(), 2);
- QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QVERIFY(QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
rectPrivate->setState("blue");
QCOMPARE(childRect->width(), qreal(50));
QCOMPARE(childRect->height(), qreal(40));
propertyChangesBlue->changeValue("width", 60);
QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QCOMPARE(propertyChangesBlue->actions().size(), 2);
QCOMPARE(childRect->width(), qreal(60));
- QVERIFY(!QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QVERIFY(!QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
QVERIFY(!propertyChangesBlue->containsValue("width"));
QVERIFY(propertyChangesBlue->containsExpression("width"));
QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
- QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QCOMPARE(propertyChangesBlue->actions().size(), 2);
+ QVERIFY(QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
QCOMPARE(childRect->width(), qreal(200));
propertyChangesBlue->changeValue("width", 50);
@@ -1548,25 +1538,25 @@ void tst_qquickstates::editProperties()
rectPrivate->setState("");
QCOMPARE(childRect->width(), qreal(402));
- QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QVERIFY(QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
- QCOMPARE(propertyChangesGreen->actions().length(), 2);
+ QCOMPARE(propertyChangesGreen->actions().size(), 2);
rectPrivate->setState("green");
QCOMPARE(childRect->width(), qreal(200));
QCOMPARE(childRect->height(), qreal(100));
- QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QVERIFY(QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
QVERIFY(greenState->bindingInRevertList(childRect, "width"));
- QCOMPARE(propertyChangesGreen->actions().length(), 2);
+ QCOMPARE(propertyChangesGreen->actions().size(), 2);
propertyChangesGreen->removeProperty("height");
- QVERIFY(!QQmlPropertyPrivate::binding(QQmlProperty(childRect, "height")));
+ QVERIFY(!QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "height")));
QCOMPARE(childRect->height(), qreal(200));
QVERIFY(greenState->bindingInRevertList(childRect, "width"));
QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
propertyChangesGreen->removeProperty("width");
- QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
+ QVERIFY(QQmlAnyBinding::ofProperty(QQmlProperty(childRect, "width")));
QCOMPARE(childRect->width(), qreal(402));
QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
@@ -1660,9 +1650,20 @@ void tst_qquickstates::QTBUG_38492()
QCOMPARE(item->property("text").toString(), QString("Test"));
}
+static int getRefCount(const QQmlAnyBinding &binding)
+{
+ if (binding.isAbstractPropertyBinding()) {
+ return binding.asAbstractBinding()->ref;
+ } else {
+ // this temporarily adds a refcount because we construc a new untypedpropertybinding
+ // thus -1
+ return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->refCount() - 1;
+ }
+}
+
void tst_qquickstates::revertListMemoryLeak()
{
- QQmlAbstractBinding::Ptr bindingPtr;
+ QQmlAnyBinding bindingPtr;
{
QQmlEngine engine;
@@ -1674,12 +1675,12 @@ void tst_qquickstates::revertListMemoryLeak()
item->setState("testState");
- QQmlAbstractBinding *binding = state->bindingInRevertList(item.get(), "height").asAbstractBinding();
+ auto binding = state->bindingInRevertList(item.get(), "height");
QVERIFY(binding);
bindingPtr = binding;
- QVERIFY(bindingPtr->ref > 1);
+ QVERIFY(getRefCount(bindingPtr) > 1);
}
- QVERIFY(bindingPtr->ref == 1);
+ QVERIFY(getRefCount(bindingPtr) == 1);
}
void tst_qquickstates::duplicateStateName()
@@ -1702,6 +1703,39 @@ void tst_qquickstates::trivialWhen()
QVERIFY(root);
}
+
+void tst_qquickstates::jsValueWhen_data()
+{
+ QTest::addColumn<QByteArray>("fileName");
+ QTest::addRow("jsObject") << QByteArray("jsValueWhen.qml");
+ QTest::addRow("qmlObject") << QByteArray("jsValueWhen2.qml");
+}
+
+void tst_qquickstates::jsValueWhen()
+{
+ QFETCH(QByteArray, fileName);
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl(fileName.constData()));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+ QVERIFY(root->property("works").toBool());
+}
+
+void tst_qquickstates::noStateOsciallation()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("noStateOsciallation.qml"));
+ QScopedPointer<QObject> root {component.create()};
+ QVERIFY(root);
+ // set to 1 on initial transition from "" to "n2"
+ QCOMPARE(root->property("stateChangeCounter").toInt(), 1);
+ root->setProperty("number", 1);
+ // setting number to 1 changes directly from "n2" to "n1"
+ // without any intermediate transition to ""
+ QCOMPARE(root->property("stateChangeCounter").toInt(), 2);
+}
+
void tst_qquickstates::parentChangeCorrectReversal()
{
QQmlEngine engine;
@@ -1768,6 +1802,256 @@ void tst_qquickstates::bindableProperties()
}
}
+struct Listener : QQuickItemChangeListener
+{
+ // We want to get notified about all the states.
+ constexpr static const QRectF expectations[] = {
+ QRectF(40, 40, 400, 400),
+ QRectF(40, 0, 400, 400),
+ QRectF(0, 0, 400, 400),
+ QRectF(0, 0, 800, 400),
+ QRectF(0, 0, 800, 200),
+ QRectF(0, 0, 400, 200),
+ QRectF(0, 20, 400, 200),
+ QRectF(40, 20, 400, 200),
+ QRectF(84, 42, 400, 200),
+ QRectF(84, 42, 86, 43),
+ QRectF(40, 40, 86, 43),
+ QRectF(40, 40, 400, 400),
+ QRectF(40, 20, 400, 400),
+ QRectF(40, 20, 400, 200),
+ QRectF(20, 20, 400, 200),
+ QRectF(20, 20, 200, 200),
+ QRectF(20, 20, 200, 300),
+ QRectF(20, 20, 300, 300),
+ QRectF(20, 30, 300, 300),
+ QRectF(30, 30, 300, 300),
+ };
+
+ int position = 0;
+ bool ok = true;
+
+ void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &rect) override
+ {
+ if (rect != expectations[position]) {
+ qDebug() << position << rect;
+ ok = false;
+ }
+ ++position;
+ }
+};
+
+void tst_qquickstates::parentChangeInvolvingBindings()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("parentChangeInvolvingBindings.qml"));
+ Listener listener;
+ QScopedPointer<QQuickItem> root { qobject_cast<QQuickItem *>(c.create()) };
+ QVERIFY2(root, qPrintable(c.errorString()));
+
+ QObject *child = qmlContext(root.data())->objectForName(QStringLiteral("firstChild"));
+ QVERIFY(child);
+ QQuickItem *childItem = qobject_cast<QQuickItem *>(child);
+ QVERIFY(childItem);
+ QQuickItemPrivate::get(childItem)->addItemChangeListener(&listener, QQuickItemPrivate::Geometry);
+
+
+ QCOMPARE(root->property("childWidth").toInt(), 400);
+ QCOMPARE(root->property("childX").toInt(), 40);
+ QCOMPARE(root->property("childRotation").toInt(), 100);
+ root->setState("reparented");
+
+ QCOMPARE(root->property("childWidth").toInt(), 800);
+ QCOMPARE(root->property("childX").toInt(), 0); // x gets zeroed here, from unrelated place.
+ QCOMPARE(root->property("childRotation").toInt(), 200);
+
+ root->setProperty("myrotation2", 300);
+ root->setHeight(200);
+ root->setY(20);
+ QCOMPARE(root->property("childRotation").toInt(), 300);
+ QCOMPARE(root->property("childWidth").toInt(), 400);
+ QCOMPARE(root->property("childX").toInt(), 40);
+
+ QObject *inner = qmlContext(root.data())->objectForName(QStringLiteral("inner"));
+ QVERIFY(inner);
+ QQuickItem *innerItem = qobject_cast<QQuickItem *>(inner);
+ QVERIFY(innerItem);
+
+ QCOMPARE(innerItem->size(), childItem->size());
+
+ // Does not break bindings and does not survive the state change.
+ // However, since the binding between x and y stays intact, we don't know
+ // whether x is set another time from the new y. We pass a pair of numbers that
+ // matches the binding.
+ childItem->setPosition(QPointF(84, 42));
+ QCOMPARE(root->property("childX").toInt(), 84);
+ QVERIFY(listener.ok);
+ childItem->setSize(QSizeF(86, 43));
+ QCOMPARE(root->property("childWidth").toInt(), 86);
+ QVERIFY(listener.ok);
+
+ QCOMPARE(innerItem->size(), childItem->size());
+
+ QSignalSpy xSpy(childItem, SIGNAL(xChanged()));
+ QSignalSpy widthSpy(childItem, SIGNAL(widthChanged()));
+
+ root->setState("");
+
+ QVERIFY(listener.ok);
+ QCOMPARE(root->property("childRotation").toInt(), 100);
+
+ // First change to 40 via reverse(), then to 20 via binding.
+ QCOMPARE(xSpy.size(), 2);
+
+ // First change to 400 via reverse(), then to 200 via binding.
+ QCOMPARE(widthSpy.size(), 2);
+
+ QCOMPARE(root->property("childX").toInt(), 20);
+ QCOMPARE(root->property("childWidth").toInt(), 200);
+
+ QCOMPARE(innerItem->size(), childItem->size());
+
+ root->setProperty("myrotation", 50);
+ root->setHeight(300);
+ QVERIFY(listener.ok);
+ root->setY(30);
+ QVERIFY(listener.ok);
+ QCOMPARE(root->property("childWidth").toInt(), 300);
+ QCOMPARE(root->property("childX").toInt(), 30);
+ QCOMPARE(root->property("childRotation").toInt(), 50);
+
+ QCOMPARE(innerItem->size(), childItem->size());
+}
+
+void tst_qquickstates::deferredProperties()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("cleanPropertyChange.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QQuickRectangle> root(qobject_cast<QQuickRectangle *>(c.create()));
+ QVERIFY(root);
+
+ QCOMPARE(root->color(), QColor(Qt::red));
+ QCOMPARE(qvariant_cast<QColor>(root->property("extendedColor")), QColor(Qt::cyan));
+ QCOMPARE(root->width(), 100.0);
+ QCOMPARE(root->height(), 100.0);
+
+ QCOMPARE(root->state(), QString());
+ root->setState(QStringLiteral("green"));
+
+ QCOMPARE(root->color(), QColor(Qt::yellow));
+ QCOMPARE(qvariant_cast<QColor>(root->property("extendedColor")), QColor(Qt::blue));
+ QCOMPARE(root->width(), 90.0);
+ QCOMPARE(root->height(), 90.0);
+
+ QMetaObject::invokeMethod(root.get(), "didSomething");
+ const QColor green = qRgb(0x00, 0x80, 0x00);
+ QCOMPARE(root->color(), green);
+ QCOMPARE(qvariant_cast<QColor>(root->property("extendedColor")), green);
+ QCOMPARE(root->width(), 90.0);
+ QCOMPARE(root->height(), 90.0);
+
+ root->setState(QString());
+
+ QCOMPARE(root->color(), QColor(Qt::red));
+ QCOMPARE(qvariant_cast<QColor>(root->property("extendedColor")), QColor(Qt::cyan));
+ QCOMPARE(root->width(), 100.0);
+ QCOMPARE(root->height(), 100.0);
+}
+
+void tst_qquickstates::rewindAnchorChange()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("anchorRewind.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+
+ QQmlContext *context = qmlContext(root.data());
+ QVERIFY(context);
+
+ QObject *inner = context->objectForName(QStringLiteral("inner"));
+ QVERIFY(inner);
+
+ QQuickItem *innerRect = qobject_cast<QQuickItem *>(inner);
+ QVERIFY(innerRect);
+
+ QTRY_COMPARE(innerRect->x(), 0);
+ QTRY_COMPARE(innerRect->y(), 0);
+ QTRY_COMPARE(innerRect->width(), 200);
+ QTRY_COMPARE(innerRect->height(), 200);
+}
+
+void tst_qquickstates::rewindAnchorChangeSize()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("anchorRewindSize.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> root(c.create());
+ QVERIFY(root);
+
+ QQmlContext *context = qmlContext(root.get());
+ QVERIFY(context);
+
+ QObject *inner = context->objectForName(QStringLiteral("inner"));
+ QVERIFY(inner);
+
+ QQuickItem *innerRect = qobject_cast<QQuickItem *>(inner);
+ QVERIFY(innerRect);
+
+ QCOMPARE(innerRect->x(), 0);
+ QCOMPARE(innerRect->y(), 0);
+ QCOMPARE(innerRect->width(), 100);
+ QCOMPARE(innerRect->height(), 100);
+
+ root->setProperty("changeState", true);
+ QCOMPARE(innerRect->x(), 0);
+ QCOMPARE(innerRect->y(), 0);
+ QCOMPARE(innerRect->width(), 400);
+ QCOMPARE(innerRect->height(), 400);
+
+ root->setProperty("changeState", false);
+ QCOMPARE(innerRect->x(), 0);
+ QCOMPARE(innerRect->y(), 0);
+ QCOMPARE(innerRect->width(), 100);
+ QCOMPARE(innerRect->height(), 100);
+}
+
+void tst_qquickstates::bindingProperlyRemovedWithTransition()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("removeBindingWithTransition.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+ QQuickItem *item = qobject_cast<QQuickItem *>(root.get());
+ QVERIFY(item);
+
+ item->setProperty("toggle", false);
+ QTRY_COMPARE(item->width(), 300);
+
+ item->setProperty("state1Width", 100);
+ QCOMPARE(item->width(), 300);
+
+ item->setProperty("toggle", true);
+ QTRY_COMPARE(item->width(), 100);
+}
+
+void tst_qquickstates::doNotCrashOnBroken()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("broken.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+ QQuickItem *item = qobject_cast<QQuickItem *>(root.get());
+ QVERIFY(item);
+
+ QQmlListReference states(item, "states");
+ QCOMPARE(states.size(), 1);
+ QCOMPARE(states.at(0), nullptr);
+}
+
QTEST_MAIN(tst_qquickstates)
#include "tst_qquickstates.moc"