diff options
-rw-r--r-- | src/quick/items/qquickitem.cpp | 74 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/data/mapCoordinates.qml | 10 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 8 |
3 files changed, 68 insertions, 24 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index b5932c6f80..59684d15a8 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4638,6 +4638,52 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const args->setReturnValue(rv.asReturnedValue()); } +static bool unwrapMapFromToFromGlobalArgs(QQmlV4Function *args, const QQuickItem *itemForWarning, const QString &functionNameForWarning, qreal *x, qreal *y) +{ + QV4::ExecutionEngine *v4 = args->v4engine(); + if (args->length() != 1 && args->length() != 2) { + v4->throwTypeError(); + return false; + } + + QV4::Scope scope(v4); + + if (args->length() == 1) { + QV4::ScopedValue sv(scope, (*args)[0]); + if (sv->isNull()) { + qmlWarning(itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow() + << "\" which is not a point"; + v4->throwTypeError(); + return false; + } + const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>()); + const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant(); + if (v.canConvert<QPointF>()) { + const QPointF p = v.toPointF(); + *x = p.x(); + *y = p.y(); + } else { + qmlWarning(itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow() + << "\" which is not a point"; + v4->throwTypeError(); + return false; + } + } else { + QV4::ScopedValue vx(scope, (*args)[0]); + QV4::ScopedValue vy(scope, (*args)[1]); + + if (!vx->isNumber() || !vy->isNumber()) { + v4->throwTypeError(); + return false; + } + + *x = vx->asDouble(); + *y = vy->asDouble(); + } + + return true; +} + /*! \since 5.7 \qmlmethod object QtQuick::Item::mapFromGlobal(real x, real y) @@ -4653,22 +4699,12 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const void QQuickItem::mapFromGlobal(QQmlV4Function *args) const { QV4::ExecutionEngine *v4 = args->v4engine(); - if (args->length() != 2) { - v4->throwTypeError(); - return; - } - QV4::Scope scope(v4); - QV4::ScopedValue vx(scope, (*args)[0]); - QV4::ScopedValue vy(scope, (*args)[1]); - if (!vx->isNumber() || !vy->isNumber()) { - v4->throwTypeError(); + qreal x, y; + if (!unwrapMapFromToFromGlobalArgs(args, this, QStringLiteral("mapFromGlobal()"), &x, &y)) return; - } - qreal x = vx->asDouble(); - qreal y = vy->asDouble(); QVariant result = mapFromGlobal(QPointF(x, y)); QV4::ScopedObject rv(scope, v4->fromVariant(result)); @@ -4690,22 +4726,12 @@ void QQuickItem::mapFromGlobal(QQmlV4Function *args) const void QQuickItem::mapToGlobal(QQmlV4Function *args) const { QV4::ExecutionEngine *v4 = args->v4engine(); - if (args->length() != 2) { - v4->throwTypeError(); - return; - } - QV4::Scope scope(v4); - QV4::ScopedValue vx(scope, (*args)[0]); - QV4::ScopedValue vy(scope, (*args)[1]); - if (!vx->isNumber() || !vy->isNumber()) { - v4->throwTypeError(); + qreal x, y; + if (!unwrapMapFromToFromGlobalArgs(args, this, QStringLiteral("mapFromGlobal()"), &x, &y)) return; - } - qreal x = vx->asDouble(); - qreal y = vy->asDouble(); QVariant result = mapToGlobal(QPointF(x, y)); QV4::ScopedObject rv(scope, v4->fromVariant(result)); diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml index 596dedab90..ce9e3348f5 100644 --- a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml +++ b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml @@ -69,11 +69,21 @@ Item { return Qt.point(pos.x, pos.y) } + function mapAToGlobalPoint(x, y) { + var pos = itemA.mapToGlobal(Qt.point(x, y)) + return Qt.point(pos.x, pos.y) + } + function mapAFromGlobal(x, y) { var pos = itemA.mapFromGlobal(x, y) return Qt.point(pos.x, pos.y) } + function mapAFromGlobalPoint(x, y) { + var pos = itemA.mapFromGlobal(Qt.point(x, y)) + return Qt.point(pos.x, pos.y) + } + function mapOrphanToGlobal(x, y) { var obj = itemComponent.createObject(null); var pos = obj.mapToGlobal(x, y) diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 607cf91bfe..0fe626f364 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -2407,10 +2407,18 @@ void tst_QQuickItem::mapCoordinates() Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToGlobal(QPointF(x, y))); + QVERIFY(QMetaObject::invokeMethod(root, "mapAToGlobalPoint", + Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); + QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToGlobal(QPointF(x, y))); + QVERIFY(QMetaObject::invokeMethod(root, "mapAFromGlobal", Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromGlobal(QPointF(x, y))); + QVERIFY(QMetaObject::invokeMethod(root, "mapAFromGlobalPoint", + Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); + QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromGlobal(QPointF(x, y))); + // for orphans we are primarily testing that we don't crash. // when orphaned the final position is the original position of the item translated by x,y QVERIFY(QMetaObject::invokeMethod(root, "mapOrphanToGlobal", |