diff options
-rw-r--r-- | src/quick/items/qquickitemsmodule.cpp | 1 | ||||
-rw-r--r-- | src/quick/util/qquickpath.cpp | 108 | ||||
-rw-r--r-- | src/quick/util/qquickpath_p.h | 22 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/data/pathitem7.qml | 67 | ||||
-rw-r--r-- | tests/auto/quick/qquickshape/tst_qquickshape.cpp | 36 |
5 files changed, 228 insertions, 6 deletions
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 4649e33070..bc87b2c43f 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -227,6 +227,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickPathArc>("QtQuick",2,0,"PathArc"); qmlRegisterType<QQuickPathSvg>("QtQuick",2,0,"PathSvg"); qmlRegisterType<QQuickPath, 14>(uri, 2, 14, "Path"); + qmlRegisterType<QQuickPathPolyline>("QtQuick", 2, 14, "PathPolyline"); #endif #if QT_CONFIG(quick_pathview) qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView"); diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index a0f3749552..f0705d19bd 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE This type is the base for all path types. It cannot be instantiated. - \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic, PathArc, + \sa Path, PathAttribute, PathPercent, PathLine, PathPolyline, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg */ @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE \ingroup qtquick-animation-paths \brief Defines a path for use by \l PathView and \l Shape. - A Path is composed of one or more path segments - PathLine, PathQuad, + A Path is composed of one or more path segments - PathLine, PathPolyline, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg. The spacing of the items along the Path can be adjusted via a @@ -104,6 +104,12 @@ QT_BEGIN_NAMESPACE \li Yes \li Yes \row + \li PathPolyline + \li Yes + \li Yes + \li Yes + \li Yes + \row \li PathQuad \li Yes \li Yes @@ -156,7 +162,7 @@ QT_BEGIN_NAMESPACE \note Path is a non-visual type; it does not display anything on its own. To draw a path, use \l Shape. - \sa PathView, Shape, PathAttribute, PathPercent, PathLine, PathMove, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg + \sa PathView, Shape, PathAttribute, PathPercent, PathLine, PathPolyline, PathMove, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg */ QQuickPath::QQuickPath(QObject *parent) : QObject(*(new QQuickPathPrivate), parent) @@ -240,6 +246,7 @@ bool QQuickPath::isClosed() const A path can contain the following path objects: \list \li \l PathLine - a straight line to a given position. + \li \l PathPolyline - a polyline specified as a list of normalized coordinates. \li \l PathQuad - a quadratic Bezier curve to a given position with a control point. \li \l PathCubic - a cubic Bezier curve to a given position with two control points. \li \l PathArc - an arc to a given position with a radius. @@ -1168,7 +1175,7 @@ void QQuickPathAttribute::setValue(qreal value) } \endqml - \sa Path, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove + \sa Path, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove, PathPolyline */ /*! @@ -2327,6 +2334,99 @@ void QQuickPathPercent::setValue(qreal value) emit changed(); } } + +/*! + \qmltype PathPolyline + \instantiates QQuickPathPolyline + \inqmlmodule QtQuick + \ingroup qtquick-animation-paths + \brief Defines a polyline through a list of coordinates. + \since QtQuick 2.14 + + The example below creates a triangular path consisting of four vertices + on the edge of the containing Shape's bounding box. + Through the containing shape's \l scale property, the path will be + rescaled together with its containing shape. + + \qml + PathPolyline { + id: ppl + path: [ Qt.point(0.0, 0.0), + Qt.point(1.0, 0.0), + Qt.point(0.5, 1.0), + Qt.point(0.0, 0.0) + ] + } + \endqml + + \sa Path, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove, PathPolyline +*/ + +/*! + \qmlproperty point QtQuick::PathPolyline::start + + This read-only property contains the beginning of the polyline. +*/ + +/*! + \qmlproperty list<point> QtQuick::PathPolyline::path + + This property defines the vertices of the polyline. +*/ + +QQuickPathPolyline::QQuickPathPolyline(QObject *parent) : QQuickCurve(parent) +{ +} + +QVariantList QQuickPathPolyline::path() const +{ + QVariantList res; + for (int i = 0; i < m_path.length(); ++i) { + const QPointF &c = m_path.at(i); + res.append(QVariant::fromValue(c)); + } + + return res; +} + +void QQuickPathPolyline::setPath(const QVariantList &path) +{ + QVector<QPointF> pathList; + for (int i = 0; i < path.length(); ++i) { + const QPointF c = path.at(i).toPointF(); + pathList.append(c); + } + + if (m_path != pathList) { + const QPointF &oldStart = start(); + m_path = pathList; + const QPointF &newStart = start(); + emit pathChanged(); + if (oldStart != newStart) + emit startChanged(); + emit changed(); + } +} + +QPointF QQuickPathPolyline::start() const +{ + if (m_path.size()) { + const QPointF &p = m_path.first(); + return p; + } + return QPointF(); +} + +void QQuickPathPolyline::addToPath(QPainterPath &path, const QQuickPathData &/*data*/) +{ + if (m_path.size() < 2) + return; + + path.moveTo(m_path.first()); + for (int i = 1; i < m_path.size(); ++i) + path.lineTo(m_path.at(i)); +} + QT_END_NAMESPACE #include "moc_qquickpath_p.cpp" diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index 01f60c34d2..5a939f49cb 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -424,6 +424,27 @@ private: qreal _value = 0; }; +class Q_QUICK_PRIVATE_EXPORT QQuickPathPolyline : public QQuickCurve +{ + Q_OBJECT + Q_PROPERTY(QPointF start READ start NOTIFY startChanged) + Q_PROPERTY(QVariantList path READ path WRITE setPath NOTIFY pathChanged) +public: + QQuickPathPolyline(QObject *parent=nullptr); + + QVariantList path() const; + void setPath(const QVariantList &path); + QPointF start() const; + void addToPath(QPainterPath &path, const QQuickPathData &data) override; + +Q_SIGNALS: + void pathChanged(); + void startChanged(); + +private: + QVector<QPointF> m_path; +}; + struct QQuickCachedBezier { QQuickCachedBezier() {} @@ -545,6 +566,7 @@ QML_DECLARE_TYPE(QQuickPathArc) QML_DECLARE_TYPE(QQuickPathAngleArc) QML_DECLARE_TYPE(QQuickPathSvg) QML_DECLARE_TYPE(QQuickPathPercent) +QML_DECLARE_TYPE(QQuickPathPolyline) QML_DECLARE_TYPE(QQuickPath) #endif // QQUICKPATH_H 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/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp index eb98f849f8..174ada65a5 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" @@ -57,6 +58,7 @@ private slots: void renderWithMultipleSp(); void radialGrad(); void conicalGrad(); + void renderPolyline(); }; tst_QQuickShape::tst_QQuickShape() @@ -71,6 +73,7 @@ tst_QQuickShape::tst_QQuickShape() qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient"); qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient"); qmlRegisterType<QQuickShapeConicalGradient>(uri, 1, 0, "ConicalGradient"); + qmlRegisterType<QQuickPathPolyline>(uri, 1, 0, "PathPolyline"); } void tst_QQuickShape::initValues() @@ -311,6 +314,35 @@ 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)); +} + QTEST_MAIN(tst_QQuickShape) #include "tst_qquickshape.moc" |