diff options
author | Oleg Yadrov <oleg.yadrov@qt.io> | 2016-12-19 12:08:20 -0800 |
---|---|---|
committer | Oleg Yadrov <oleg.yadrov@qt.io> | 2017-01-20 00:13:24 +0000 |
commit | 7ee15ecdd960cde6d0202e9675f7f6bd31bbb927 (patch) | |
tree | 4d543697b552eada54971b7d0684e0495507e308 | |
parent | edffdcf9b45641708fb242449b77e8e53ee05d87 (diff) |
PathAnimation: fix bug when PathSvg or PathLine is the last item in Path
Both QQuickPathLine and QQuickPathSvg inherit QQuickCurve class which
has “x” and “y” properties that return qreal type, but internally they
are stored as QQmlNullableValue<qreal>. At the same time, if any of them
is not specified explicitly, its getter returns 0.
QQuickPath processes QQuickPath%Type% objects and produces a
QPainterPath which later used by QQuickPathAnimation.
QQuickPathAnimation only created a QAbstractAnimationJob if
QQuickPath::hasEnd returned true, and hasEnd returned true only if both
“x” and “y” were specified explicitly.
All that in conjunction led to the situation when if you had either
- a PathLine with unspecified “x” or “y”; or
- a PathSvg
which was the last (or the only) path element in your Path,
PathAnimation would not start.
This patch removes hasEnd check, it should be safe to do because
QPainterPath is always valid anyway due to the fact QQuickCurve::x()
and QQuickCurve::y() return 0 if they have not been not explicitly set.
Task-number: QTBUG-57666
Change-Id: Id320aaeb5aff0964d6493b7b80d5d9a7d36acce8
Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
-rw-r--r-- | src/quick/items/qquickitemanimation.cpp | 2 | ||||
-rw-r--r-- | src/quick/util/qquickpath.cpp | 14 | ||||
-rw-r--r-- | src/quick/util/qquickpath_p.h | 1 | ||||
-rw-r--r-- | tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml | 28 | ||||
-rw-r--r-- | tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml | 25 | ||||
-rw-r--r-- | tests/auto/quick/qquickanimations/tst_qquickanimations.cpp | 44 |
6 files changed, 98 insertions, 16 deletions
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp index b33705e75e..9873622f41 100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@ -869,7 +869,7 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio data->reverse = direction == Backward ? true : false; data->fromSourced = false; data->fromDefined = (d->path && d->path->hasStartX() && d->path->hasStartY()) ? true : false; - data->toDefined = d->path ? d->path->hasEnd() : false; + data->toDefined = d->path ? true : false; int origModifiedSize = modified.count(); for (int i = 0; i < actions.count(); ++i) { diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index 25a4433a9b..e31aed7b6d 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -149,20 +149,6 @@ bool QQuickPath::isClosed() const return d->closed; } -bool QQuickPath::hasEnd() const -{ - Q_D(const QQuickPath); - for (int i = d->_pathElements.count() - 1; i > -1; --i) { - if (QQuickCurve *curve = qobject_cast<QQuickCurve *>(d->_pathElements.at(i))) { - if ((!curve->hasX() && !curve->hasRelativeX()) || (!curve->hasY() && !curve->hasRelativeY())) - return false; - else - return true; - } - } - return hasStartX() && hasStartY(); -} - /*! \qmlproperty list<PathElement> QtQuick::Path::pathElements This property holds the objects composing the path. diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index 06ad389b49..c0a96cad4f 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -390,7 +390,6 @@ public: bool hasStartY() const; bool isClosed() const; - bool hasEnd() const; QPainterPath path() const; QStringList attributes() const; diff --git a/tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml b/tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml new file mode 100644 index 0000000000..426360bbcc --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml @@ -0,0 +1,28 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Rectangle { + id: redRect + color: "red" + width: 100; height: 100 + x: 50; y: 50 + } + + PathAnimation { + target: redRect + duration: 1000 + path: Path { + startX: 100; startY: 100 + + PathLine { + x: 200 + y: 200 + } + + PathLine {} + } + } +} diff --git a/tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml b/tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml new file mode 100644 index 0000000000..e409bb031f --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Rectangle { + id: redRect + color: "red" + width: 100; height: 100 + x: 50; y: 50 + } + + PathAnimation { + target: redRect + duration: 1000; + path: Path { + startX: 100; startY: 100 + + PathSvg { + path: "M 200 200" + } + } + } +} diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index 6e265503a1..fbd6c9c97e 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -101,6 +101,8 @@ private slots: void scriptActionCrash(); void animatorInvalidTargetCrash(); void defaultPropertyWarning(); + void pathSvgAnimation(); + void pathLineUnspecifiedXYBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -1523,6 +1525,48 @@ void tst_qquickanimations::defaultPropertyWarning() QVERIFY(warnings.isEmpty()); } +// QTBUG-57666 +void tst_qquickanimations::pathSvgAnimation() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("pathSvgAnimation.qml")); + QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(component.create())); + QVERIFY(rect); + + QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>(); + QVERIFY(redRect); + QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>(); + QVERIFY(pathAnim); + + QCOMPARE(redRect->x(), qreal(50)); + QCOMPARE(redRect->y(), qreal(50)); + + pathAnim->start(); + QTRY_COMPARE(redRect->x(), qreal(200)); + QCOMPARE(redRect->y(), qreal(200)); +} + +// QTBUG-57666 +void tst_qquickanimations::pathLineUnspecifiedXYBug() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("pathLineUnspecifiedXYBug.qml")); + QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(component.create())); + QVERIFY(rect); + + QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>(); + QVERIFY(redRect); + QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>(); + QVERIFY(pathAnim); + + QCOMPARE(redRect->x(), qreal(50)); + QCOMPARE(redRect->y(), qreal(50)); + + pathAnim->start(); + QTRY_COMPARE(redRect->x(), qreal(0)); + QCOMPARE(redRect->y(), qreal(0)); +} + QTEST_MAIN(tst_qquickanimations) #include "tst_qquickanimations.moc" |