aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquickshape/tst_qquickshape.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/qquickshape/tst_qquickshape.cpp')
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp334
1 files changed, 334 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index b3b8d2d148..851475e2cd 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -43,6 +43,28 @@
using namespace QQuickViewTestUtil;
using namespace QQuickVisualTestUtil;
+class PolygonProvider : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector<QPolygonF> paths READ paths WRITE setPaths NOTIFY pathsChanged)
+
+public:
+ QVector<QPolygonF> paths() const { return m_paths; }
+ void setPaths(QVector<QPolygonF> paths)
+ {
+ if (m_paths == paths)
+ return;
+ m_paths = paths;
+ emit pathsChanged();
+ }
+
+signals:
+ void pathsChanged();
+
+private:
+ QVector<QPolygonF> m_paths;
+};
+
class tst_QQuickShape : public QQmlDataTest
{
Q_OBJECT
@@ -60,6 +82,14 @@ private slots:
void conicalGrad();
void renderPolyline();
void renderMultiline();
+ void polylineDataTypes_data();
+ void polylineDataTypes();
+ void multilineDataTypes_data();
+ void multilineDataTypes();
+ void multilineStronglyTyped();
+
+private:
+ QVector<QPolygonF> m_lowPolyLogo;
};
tst_QQuickShape::tst_QQuickShape()
@@ -75,6 +105,30 @@ tst_QQuickShape::tst_QQuickShape()
qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient");
qmlRegisterType<QQuickShapeConicalGradient>(uri, 1, 0, "ConicalGradient");
qmlRegisterType<QQuickPathPolyline>(uri, 1, 0, "PathPolyline");
+ qmlRegisterType<PolygonProvider>("Qt.test", 1, 0, "PolygonProvider");
+
+ m_lowPolyLogo << (QPolygonF() <<
+ QPointF(20, 0) <<
+ QPointF(140, 0) <<
+ QPointF(140, 80) <<
+ QPointF(120, 100) <<
+ QPointF(0, 100) <<
+ QPointF(0, 20) <<
+ QPointF(20, 0) )
+ << (QPolygonF() << QPointF(20, 80) <<
+ QPointF(60, 80) <<
+ QPointF(80, 60) <<
+ QPointF(80, 20) <<
+ QPointF(40, 20) <<
+ QPointF(20, 40) <<
+ QPointF(20, 80) )
+ << (QPolygonF() << QPointF(80, 80) <<
+ QPointF(70, 70) )
+ << (QPolygonF() << QPointF(120, 80) <<
+ QPointF(100, 60) <<
+ QPointF(100, 20) )
+ << (QPolygonF() << QPointF(100, 40) <<
+ QPointF(120, 40) );
}
void tst_QQuickShape::initValues()
@@ -373,6 +427,286 @@ void tst_QQuickShape::renderMultiline()
QVERIFY2(res, qPrintable(errorMessage));
}
+void tst_QQuickShape::polylineDataTypes_data()
+{
+ QTest::addColumn<QVariant>("path");
+
+ QTest::newRow("polygon") << QVariant::fromValue(m_lowPolyLogo.first());
+ {
+ QVector<QPointF> points;
+ points << m_lowPolyLogo.first();
+ QTest::newRow("vector of points") << QVariant::fromValue(points);
+ }
+ {
+ QList<QPointF> points;
+ for (const auto &point : m_lowPolyLogo.first())
+ points << point;
+ QTest::newRow("list of points") << QVariant::fromValue(points);
+ }
+ {
+ QVariantList points;
+ for (const auto &point : m_lowPolyLogo.first())
+ points << point;
+ QTest::newRow("QVariantList of points") << QVariant::fromValue(points);
+ }
+ {
+ QVector<QPoint> points;
+ for (const auto &point : m_lowPolyLogo.first())
+ points << point.toPoint();
+ QTest::newRow("vector of QPoint (integer points)") << QVariant::fromValue(points);
+ }
+ // Oddly, QPolygon is not supported, even though it's really QVector<QPoint>.
+ // We don't want to have a special case for it in QQuickPathPolyline::setPath(),
+ // but it could potentially be supported by fixing one of the QVariant conversions.
+}
+
+void tst_QQuickShape::polylineDataTypes()
+{
+ QFETCH(QVariant, path);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("polyline.qml"));
+ QQuickShape *shape = qobject_cast<QQuickShape *>(window->rootObject());
+ QVERIFY(shape);
+ shape->setProperty("path", path);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("polyline.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage);
+ if (!res) { // For visual inspection purposes.
+ QTest::qWait(5000);
+ const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+ actualImg.save(tempLocation + QLatin1String("/polyline.png"));
+ }
+ QVERIFY2(res, qPrintable(errorMessage));
+
+ QCOMPARE(shape->property("path").value<QVector<QPointF>>(), m_lowPolyLogo.first());
+ // Verify that QML sees it as an array of points
+ int i = 0;
+ for (QPointF p : m_lowPolyLogo.first()) {
+ QMetaObject::invokeMethod(shape, "checkVertexAt", Q_ARG(QVariant, QVariant::fromValue<int>(i++)));
+ QCOMPARE(shape->property("vertexBeingChecked").toPointF(), p);
+ }
+}
+
+void tst_QQuickShape::multilineDataTypes_data()
+{
+ QTest::addColumn<QVariant>("paths");
+
+ QTest::newRow("vector of polygons") << QVariant::fromValue(m_lowPolyLogo);
+ {
+ QVector<QVector<QPointF>> paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QVector<QPointF> points;
+ points << poly;
+ paths << points;
+ }
+ QTest::newRow("vector of point vectors") << QVariant::fromValue(paths);
+ }
+ {
+ QList<QVector<QPointF>> paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QVector<QPointF> points;
+ points << poly;
+ paths << points;
+ }
+ QTest::newRow("list of point vectors") << QVariant::fromValue(paths);
+ }
+ {
+ QList<QList<QPointF>> paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QList<QPointF> points;
+ for (const auto &point : poly)
+ points << point;
+ paths << points;
+ }
+ QTest::newRow("list of point lists") << QVariant::fromValue(paths);
+ }
+ {
+ QVariantList paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QVector<QPointF> points;
+ points << poly;
+ paths << QVariant::fromValue(points);
+ }
+ QTest::newRow("QVariantList of point vectors") << QVariant::fromValue(paths);
+ }
+ {
+ QVariantList paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QList<QPointF> points;
+ for (const auto &point : poly)
+ points << point;
+ paths << QVariant::fromValue(points);
+ }
+ QTest::newRow("QVariantList of point lists") << QVariant::fromValue(paths);
+ }
+ {
+ QVariantList paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QVariantList points;
+ for (const auto &point : poly)
+ points << point;
+ paths << QVariant::fromValue(points);
+ }
+ QTest::newRow("QVariantList of QVariantLists") << QVariant::fromValue(paths);
+ }
+ /* These could be supported if QVariant knew how to convert lists and vectors of QPolygon to QPolygonF.
+ But they are omitted for now because we don't want to have special cases for them
+ in QQuickPathMultiline::setPaths(). Floating point is preferred for geometry in Qt Quick.
+ {
+ QList<QPolygon> paths;
+ for (const auto &poly : m_lowPolyLogo)
+ paths << poly.toPolygon();
+ QTest::newRow("list of QPolygon (integer points)") << QVariant::fromValue(paths);
+ }
+ {
+ QVector<QPolygon> paths;
+ for (const auto &poly : m_lowPolyLogo)
+ paths << poly.toPolygon();
+ QTest::newRow("vector of QPolygon (integer points)") << QVariant::fromValue(paths);
+ }
+ */
+ {
+ QList<QList<QPoint>> paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QList<QPoint> points;
+ for (const auto &point : poly)
+ points << point.toPoint();
+ paths << points;
+ }
+ QTest::newRow("list of integer point lists") << QVariant::fromValue(paths);
+ }
+ {
+ QVector<QList<QPoint>> paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QList<QPoint> points;
+ for (const auto &point : poly)
+ points << point.toPoint();
+ paths << points;
+ }
+ QTest::newRow("vector of integer point lists") << QVariant::fromValue(paths);
+ }
+ {
+ QList<QVector<QPoint>> paths;
+ for (const auto &poly : m_lowPolyLogo) {
+ QVector<QPoint> points;
+ for (const auto &point : poly)
+ points << point.toPoint();
+ paths << points;
+ }
+ QTest::newRow("list of integer point vectors") << QVariant::fromValue(paths);
+ }
+}
+
+void tst_QQuickShape::multilineDataTypes()
+{
+ QFETCH(QVariant, paths);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("multiline.qml"));
+ QQuickShape *shape = qobject_cast<QQuickShape *>(window->rootObject());
+ QVERIFY(shape);
+ shape->setProperty("paths", paths);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("multiline.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage);
+ if (!res) { // For visual inspection purposes.
+ QTest::qWait(5000);
+ const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+ actualImg.save(tempLocation + QLatin1String("/multiline.png"));
+ }
+ QVERIFY2(res, qPrintable(errorMessage));
+
+ QVector<QVector<QPointF>> pointVectors;
+ for (auto v : m_lowPolyLogo)
+ pointVectors << v;
+ QCOMPARE(shape->property("paths").value<QVector<QVector<QPointF>>>(), pointVectors);
+ // Verify that QML sees it as an array of arrays of points
+ int i = 0;
+ for (auto pv : m_lowPolyLogo) {
+ int j = 0;
+ for (QPointF p : pv) {
+ QMetaObject::invokeMethod(shape, "checkVertexAt", Q_ARG(QVariant, QVariant::fromValue<int>(i)), Q_ARG(QVariant, QVariant::fromValue<int>(j++)));
+ QCOMPARE(shape->property("vertexBeingChecked").toPointF(), p);
+ }
+ ++i;
+ }
+}
+
+void tst_QQuickShape::multilineStronglyTyped()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("multilineStronglyTyped.qml"));
+ QQuickShape *shape = qobject_cast<QQuickShape *>(window->rootObject());
+ QVERIFY(shape);
+ PolygonProvider *provider = shape->findChild<PolygonProvider*>("provider");
+ QVERIFY(provider);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ provider->setPaths(m_lowPolyLogo);
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("multiline.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage);
+ if (!res) { // For visual inspection purposes.
+ QTest::qWait(5000);
+ const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+ actualImg.save(tempLocation + QLatin1String("/multilineStronglyTyped.png"));
+ }
+ QVERIFY2(res, qPrintable(errorMessage));
+
+ QVector<QVector<QPointF>> pointVectors;
+ for (auto v : m_lowPolyLogo)
+ pointVectors << v;
+ QCOMPARE(shape->property("paths").value<QVector<QVector<QPointF>>>(), pointVectors);
+ // Verify that QML sees it as an array of arrays of points
+ int i = 0;
+ for (auto pv : m_lowPolyLogo) {
+ int j = 0;
+ for (QPointF p : pv) {
+ QMetaObject::invokeMethod(shape, "checkVertexAt", Q_ARG(QVariant, QVariant::fromValue<int>(i)), Q_ARG(QVariant, QVariant::fromValue<int>(j++)));
+ QCOMPARE(shape->property("vertexBeingChecked").toPointF(), p);
+ }
+ ++i;
+ }
+}
+
QTEST_MAIN(tst_QQuickShape)
#include "tst_qquickshape.moc"