diff options
Diffstat (limited to 'tests/auto/quick/qquickshape')
-rw-r--r-- | tests/auto/quick/qquickshape/BLACKLIST | 8 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/data/multiline.png | bin | 0 -> 1244 bytes | |||
-rw-r--r-- | tests/auto/quick/qquickshape/data/multiline.qml | 52 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml | 59 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/data/pathitem7.qml | 67 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/data/pathitem8.png | bin | 0 -> 7323 bytes | |||
-rw-r--r-- | tests/auto/quick/qquickshape/data/pathitem8.qml | 88 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/data/polyline.png | bin | 0 -> 757 bytes | |||
-rw-r--r-- | tests/auto/quick/qquickshape/data/polyline.qml | 52 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/qquickshape.pro | 1 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/tst_qquickshape.cpp | 402 |
11 files changed, 718 insertions, 11 deletions
diff --git a/tests/auto/quick/qquickshape/BLACKLIST b/tests/auto/quick/qquickshape/BLACKLIST deleted file mode 100644 index d0ebc2f505..0000000000 --- a/tests/auto/quick/qquickshape/BLACKLIST +++ /dev/null @@ -1,8 +0,0 @@ -[render] -osx ci -[renderWithMultipleSp] -osx ci -[radialGrad] -osx ci -[conicalGrad] -osx ci diff --git a/tests/auto/quick/qquickshape/data/multiline.png b/tests/auto/quick/qquickshape/data/multiline.png Binary files differnew file mode 100644 index 0000000000..ae25d111df --- /dev/null +++ b/tests/auto/quick/qquickshape/data/multiline.png diff --git a/tests/auto/quick/qquickshape/data/multiline.qml b/tests/auto/quick/qquickshape/data/multiline.qml new file mode 100644 index 0000000000..ad07506972 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/multiline.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 + +Shape { + width: 200 + height: 150 + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + property alias paths: multiline.paths + property point vertexBeingChecked; + + function checkVertexAt(i, j) { + vertexBeingChecked = multiline.paths[i][j] + } + + ShapePath { + strokeWidth: 4 + strokeColor: "green" + PathMultiline { + id: multiline + } + } +} diff --git a/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml b/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml new file mode 100644 index 0000000000..46d650e053 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 +import Qt.test 1.0 + +Shape { + width: 200 + height: 150 + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + property alias paths: multiline.paths + property point vertexBeingChecked; + + function checkVertexAt(i, j) { + vertexBeingChecked = multiline.paths[i][j] + } + + PolygonProvider { + id: provider + objectName: "provider" + } + + ShapePath { + strokeWidth: 4 + strokeColor: "green" + PathMultiline { + id: multiline + paths: provider.paths + } + } +} diff --git a/tests/auto/quick/qquickshape/data/pathitem7.qml b/tests/auto/quick/qquickshape/data/pathitem7.qml new file mode 100644 index 0000000000..b3ef47a4dd --- /dev/null +++ b/tests/auto/quick/qquickshape/data/pathitem7.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import tst_qquickpathitem 1.0 + +Item { + id: item + width: 200 + height: 150 + + Shape { + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + anchors.fill: parent + + ShapePath { + strokeWidth: 4 + strokeColor: "red" + scale: Qt.size(shape.width - 1, shape.height - 1) + fillGradient: LinearGradient { + x1: 20; y1: 20 + x2: 180; y2: 130 + GradientStop { position: 0; color: "blue" } + GradientStop { position: 0.2; color: "green" } + GradientStop { position: 0.4; color: "red" } + GradientStop { position: 0.6; color: "yellow" } + GradientStop { position: 1; color: "cyan" } + } + strokeStyle: ShapePath.DashLine + dashPattern: [ 1, 4 ] + startX: 20; startY: 20 // unnecessary, PathPolyline moves to the first vertex. + PathPolyline { + path: [ Qt.point(20.0 / (item.width - 1.0), 20.0 / (item.height - 1.0)), + Qt.point(180.0 / (item.width - 1.0), 130.0 / (item.height - 1.0)), + Qt.point(20.0 / (item.width - 1.0), 130.0 / (item.height - 1.0)), + Qt.point(20.0 / (item.width - 1.0), 20.0 / (item.height - 1.0)) ] + } + } + } +} diff --git a/tests/auto/quick/qquickshape/data/pathitem8.png b/tests/auto/quick/qquickshape/data/pathitem8.png Binary files differnew file mode 100644 index 0000000000..ee585958ec --- /dev/null +++ b/tests/auto/quick/qquickshape/data/pathitem8.png diff --git a/tests/auto/quick/qquickshape/data/pathitem8.qml b/tests/auto/quick/qquickshape/data/pathitem8.qml new file mode 100644 index 0000000000..9789ff90e0 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/pathitem8.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 + +Item { + id: item + width: 200 + height: 150 + + Shape { + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + anchors.fill: parent + + ShapePath { + strokeWidth: 4 + strokeColor: "red" + scale: Qt.size(shape.width - 1, shape.height - 1) + fillGradient: LinearGradient { + x1: 20; y1: 20 + x2: 180; y2: 130 + GradientStop { position: 0; color: "blue" } + GradientStop { position: 0.2; color: "green" } + GradientStop { position: 0.4; color: "red" } + GradientStop { position: 0.6; color: "yellow" } + GradientStop { position: 1; color: "cyan" } + } + strokeStyle: ShapePath.DashLine + dashPattern: [ 1, 4 ] + PathMultiline { + paths: [[Qt.point(20.0 / (item.width - 1.0), 20.0 / (item.height - 1.0)), + Qt.point(180.0 / (item.width - 1.0), 130.0 / (item.height - 1.0)), + Qt.point(20.0 / (item.width - 1.0), 130.0 / (item.height - 1.0)), + Qt.point(20.0 / (item.width - 1.0), 20.0 / (item.height - 1.0)) ], + [Qt.point( 0.45 , 0.67 ), + Qt.point( 0.414906666468 , 0.573581858547 ), + Qt.point( 0.32604722665 , 0.522278837048 ), + Qt.point( 0.225 , 0.540096189432 ), + Qt.point( 0.159046106882 , 0.618696978501 ), + Qt.point( 0.159046106882 , 0.721303021499 ), + Qt.point( 0.225 , 0.799903810568 ), + Qt.point( 0.32604722665 , 0.817721162952 ), + Qt.point( 0.414906666468 , 0.766418141453 ), + Qt.point( 0.45 , 0.67 ), + ], + [Qt.point( 0.69 , 0.75 ), + Qt.point( 0.668943999881 , 0.692149115128 ), + Qt.point( 0.61562833599 , 0.661367302229 ), + Qt.point( 0.555 , 0.672057713659 ), + Qt.point( 0.515427664129 , 0.719218187101 ), + Qt.point( 0.515427664129 , 0.780781812899 ), + Qt.point( 0.555 , 0.827942286341 ), + Qt.point( 0.61562833599 , 0.838632697771 ), + Qt.point( 0.668943999881 , 0.807850884872 ), + Qt.point( 0.69 , 0.75 ), + ]] + } + } + } +} diff --git a/tests/auto/quick/qquickshape/data/polyline.png b/tests/auto/quick/qquickshape/data/polyline.png Binary files differnew file mode 100644 index 0000000000..00123fba44 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/polyline.png diff --git a/tests/auto/quick/qquickshape/data/polyline.qml b/tests/auto/quick/qquickshape/data/polyline.qml new file mode 100644 index 0000000000..e62d952ae7 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/polyline.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 + +Shape { + width: 200 + height: 150 + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + property alias path: polyline.path + property point vertexBeingChecked; + + function checkVertexAt(i) { + vertexBeingChecked = polyline.path[i] + } + + ShapePath { + strokeWidth: 4 + strokeColor: "green" + PathPolyline { + id: polyline + } + } +} diff --git a/tests/auto/quick/qquickshape/qquickshape.pro b/tests/auto/quick/qquickshape/qquickshape.pro index a0e5c002e0..3cf79426c5 100644 --- a/tests/auto/quick/qquickshape/qquickshape.pro +++ b/tests/auto/quick/qquickshape/qquickshape.pro @@ -8,6 +8,7 @@ include (../../shared/util.pri) include (../shared/util.pri) TESTDATA = data/* +DISTFILES = data/* QT += core-private gui-private qml-private quick-private testlib quickshapes-private qtHaveModule(widgets): QT += widgets diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp index 61fb260612..851475e2cd 100644 --- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp +++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp @@ -1,6 +1,6 @@ -/**************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -34,6 +34,7 @@ #include <QtQml/qqmlexpression.h> #include <QtQml/qqmlincubator.h> #include <QtQuickShapes/private/qquickshape_p.h> +#include <QStandardPaths> #include "../../shared/util.h" #include "../shared/viewtestutil.h" @@ -42,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 @@ -57,6 +80,16 @@ private slots: void renderWithMultipleSp(); void radialGrad(); 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() @@ -66,11 +99,36 @@ tst_QQuickShape::tst_QQuickShape() const char *uri = "tst_qquickpathitem"; qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape"); - qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath"); + qmlRegisterType<QQuickShapePath, 14>(uri, 1, 0, "ShapePath"); qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class")); qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient"); 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() @@ -311,6 +369,344 @@ void tst_QQuickShape::conicalGrad() qPrintable(errorMessage)); } +void tst_QQuickShape::renderPolyline() +{ + QScopedPointer<QQuickView> window(createView()); + + window->setSource(testFileUrl("pathitem7.qml")); + 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("pathitem3.png").toLocalFile()); // It's a recreation of pathitem3 using PathPolyline + 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("/pathitem7.png")); + } + QVERIFY2(res, qPrintable(errorMessage)); +} + +void tst_QQuickShape::renderMultiline() +{ + QScopedPointer<QQuickView> window(createView()); + + window->setSource(testFileUrl("pathitem8.qml")); + 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("pathitem8.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("/pathitem8.png")); + } + 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" |