diff options
author | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-03-19 16:39:50 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-03-24 11:37:36 +0000 |
commit | 7b9c9af588e2f6e40534fe6ca01f9eade3cc36c2 (patch) | |
tree | 5d058eda1a2fa5e7cd1b3d89a9617ef28af7b9d8 | |
parent | 1a6011d23e5ac37e5ded891b56a3fa5f3789ab3d (diff) | |
download | qtactiveqt-7b9c9af588e2f6e40534fe6ca01f9eade3cc36c2.tar.gz |
Add more types to QVariant->VARIANT conversion.
Introduce a macro for POD type conversion and add char, short
and float.
Remove the type coercion branch which is dead in Qt 5 since
QVariant::nameToType() always returns a valid type for char,
short and float.
Add autotest.
Task-number: QTBUG-45057
Change-Id: If3684d229a653c51b67015a7ef0c4631ead64a94
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
-rw-r--r-- | src/activeqt/shared/qaxtypes.cpp | 157 | ||||
-rw-r--r-- | tests/auto/auto.pro | 1 | ||||
-rw-r--r-- | tests/auto/conversion/conversion.pro | 3 | ||||
-rw-r--r-- | tests/auto/conversion/tst_conversion.cpp | 204 |
4 files changed, 264 insertions, 101 deletions
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 7d9d882..ba11ac2 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -233,17 +233,27 @@ static QByteArray msgOutParameterNotSupported(const QByteArray &type) Also called recoursively for lists. */ + +// Convenience macro for function QVariantToVARIANT() +// storing a POD QVariant value in the VARIANT arg. +#define QVARIANT_TO_VARIANT_POD(type, value, out, varType, varMember, varPointerMember) \ + if (out && arg.vt == ((varType) | VT_BYREF)) { \ + *arg.varPointerMember = value; /* pre-allocated out-parameter */ \ + } else { \ + if (out) { \ + arg.vt = (varType) | VT_BYREF; \ + arg.varPointerMember = new type(value); \ + } else { \ + arg.vt = (varType); \ + arg.varMember = value; \ + } \ + } + bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out) { QVariant qvar = var; // "type" is the expected type, so coerce if necessary - QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName); - if ((proptype == QVariant::UserType || proptype == int(QMetaType::QVariant)) && !typeName.isEmpty()) { - if (typeName == "short" || typeName == "char") - proptype = QVariant::Int; - else if (typeName == "float") - proptype = QVariant::Double; - } + const QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName); if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != int(QMetaType::QVariant) @@ -283,128 +293,71 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; + case QMetaType::Char: + QVARIANT_TO_VARIANT_POD(char, char(qvar.toInt()), out, VT_I1, cVal, pcVal) + break; + + case QMetaType::UChar: + QVARIANT_TO_VARIANT_POD(BYTE, uchar(qvar.toUInt()), out, VT_UI1, bVal, pbVal) + break; + + case QMetaType::Short: + QVARIANT_TO_VARIANT_POD(short, qvariant_cast<short>(qvar), out, VT_I2, iVal, piVal) + break; + + case QMetaType::UShort: + QVARIANT_TO_VARIANT_POD(ushort, qvariant_cast<ushort>(qvar), out, VT_UI2, uiVal, puiVal) + break; + case QVariant::Int: - if (out && arg.vt == (VT_I4|VT_BYREF)) { - *arg.plVal = qvar.toInt(); - } else { - arg.vt = VT_I4; - arg.lVal = qvar.toInt(); - if (out) { - if (typeName == "short") { - arg.vt = VT_I2; - arg.piVal = new short(arg.lVal); - } else if (typeName == "char") { - arg.vt = VT_I1; - arg.pcVal= new char(arg.lVal); - } else { - arg.plVal = new long(arg.lVal); - } - arg.vt |= VT_BYREF; - } - } + QVARIANT_TO_VARIANT_POD(long, qvar.toInt(), out, VT_I4, lVal, plVal) break; case QVariant::UInt: - if (out && (arg.vt == (VT_UINT|VT_BYREF) || arg.vt == (VT_I4|VT_BYREF))) { - *arg.puintVal = qvar.toUInt(); - } else { - arg.vt = VT_UINT; - arg.uintVal = qvar.toUInt(); - if (out) { - arg.puintVal = new uint(arg.uintVal); - arg.vt |= VT_BYREF; - } - } + QVARIANT_TO_VARIANT_POD(uint, qvar.toUInt(), out, VT_UI4, uintVal, puintVal) break; case QVariant::LongLong: - if (out && arg.vt == (VT_CY|VT_BYREF)) { + if (out && arg.vt == (VT_CY|VT_BYREF)) { // VT_CY: Currency arg.pcyVal->int64 = qvar.toLongLong(); - } else if (out && arg.vt == (VT_I8|VT_BYREF)) { - *arg.pllVal = qvar.toLongLong(); } else { - arg.vt = VT_I8; - arg.llVal = qvar.toLongLong(); - if (out) { - arg.pllVal = new LONGLONG(arg.llVal); - arg.vt |= VT_BYREF; - } + QVARIANT_TO_VARIANT_POD(LONGLONG, qvar.toLongLong(), out, VT_I8, llVal, pllVal) } break; case QVariant::ULongLong: - if (out && arg.vt == (VT_CY|VT_BYREF)) { + if (out && arg.vt == (VT_CY|VT_BYREF)) { // VT_CY: Currency arg.pcyVal->int64 = qvar.toULongLong(); - } else if (out && arg.vt == (VT_UI8|VT_BYREF)) { - *arg.pullVal = qvar.toULongLong(); } else { - arg.vt = VT_UI8; - arg.ullVal = qvar.toULongLong(); - if (out) { - arg.pullVal = new ULONGLONG(arg.ullVal); - arg.vt |= VT_BYREF; - } + QVARIANT_TO_VARIANT_POD(ULONGLONG, qvar.toULongLong(), out, VT_UI8, ullVal, pullVal) } break; case QVariant::Bool: - if (out && arg.vt == (VT_BOOL|VT_BYREF)) { - *arg.pboolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE; - } else { - arg.vt = VT_BOOL; - arg.boolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE; - if (out) { - arg.pboolVal = new short(arg.boolVal); - arg.vt |= VT_BYREF; - } - } + QVARIANT_TO_VARIANT_POD(short, short(qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE), + out, VT_BOOL, boolVal, pboolVal) break; + case QMetaType::Float: - case QVariant::Double: - if (out && arg.vt == (VT_R8|VT_BYREF)) { - *arg.pdblVal = qvar.toDouble(); - } else { - arg.vt = VT_R8; - arg.dblVal = qvar.toDouble(); - if (out) { - if (typeName == "float") { - arg.vt = VT_R4; - arg.pfltVal = new float(arg.dblVal); - } else { - arg.pdblVal = new double(arg.dblVal); - } - arg.vt |= VT_BYREF; - } - } + QVARIANT_TO_VARIANT_POD(float, float(qvar.toDouble()), out, VT_R4, fltVal, pfltVal) break; - case QVariant::Color: - if (out && arg.vt == (VT_COLOR|VT_BYREF)) { - *arg.plVal = QColorToOLEColor(qvariant_cast<QColor>(qvar)); - } else { - arg.vt = VT_COLOR; - arg.lVal = QColorToOLEColor(qvariant_cast<QColor>(qvar)); - if (out) { - arg.plVal = new long(arg.lVal); - arg.vt |= VT_BYREF; - } - } + case QMetaType::Double: + QVARIANT_TO_VARIANT_POD(double, qvar.toDouble(), out, VT_R8, dblVal, pdblVal) + break; + + case QVariant::Color: + QVARIANT_TO_VARIANT_POD(long, QColorToOLEColor(qvariant_cast<QColor>(qvar)), + out, VT_COLOR, lVal, plVal) break; case QVariant::Date: case QVariant::Time: - case QVariant::DateTime: - if (out && arg.vt == (VT_DATE|VT_BYREF)) { - *arg.pdate = QDateTimeToDATE(qvar.toDateTime()); - } else { - arg.vt = VT_DATE; - arg.date = QDateTimeToDATE(qvar.toDateTime()); - if (out) { - arg.pdate = new DATE(arg.date); - arg.vt |= VT_BYREF; - } - } + case QVariant::DateTime: // DATE = double + QVARIANT_TO_VARIANT_POD(DATE, QDateTimeToDATE(qvar.toDateTime()), + out, VT_DATE, date, pdate) break; + case QVariant::Font: if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { if (*arg.ppdispVal) @@ -775,6 +728,8 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type return true; } +#undef QVARIANT_TO_VARIANT_POD + /*! Returns \a arg as a QVariant of type \a type. diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 593ed3f..0b43b0d 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -1,5 +1,6 @@ TEMPLATE = subdirs SUBDIRS += \ + conversion \ qaxobject \ qaxscript \ dumpcpp \ diff --git a/tests/auto/conversion/conversion.pro b/tests/auto/conversion/conversion.pro new file mode 100644 index 0000000..47f0699 --- /dev/null +++ b/tests/auto/conversion/conversion.pro @@ -0,0 +1,3 @@ +CONFIG += testcase +QT += axcontainer testlib +SOURCES += tst_conversion.cpp diff --git a/tests/auto/conversion/tst_conversion.cpp b/tests/auto/conversion/tst_conversion.cpp new file mode 100644 index 0000000..8cf3c4d --- /dev/null +++ b/tests/auto/conversion/tst_conversion.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QtCore/QVariant> +#include <QtCore/QDateTime> +#include <QtCore/QMetaType> + +#include <qt_windows.h> + +QT_BEGIN_NAMESPACE + +// Conversion functions from statically linked library (axtypes.h) +bool QVariantToVARIANT_container(const QVariant &var, VARIANT &arg, + const QByteArray &typeName = QByteArray(), + bool out = false); + +QVariant VARIANTToQVariant_container(const VARIANT &arg, const QByteArray &typeName, + uint type = 0); + +QT_END_NAMESPACE + +class tst_Conversion : public QObject +{ + Q_OBJECT + +private slots: + void conversion_data(); + void conversion(); +}; + +enum Mode { + ByValue, + ByReference, // Allocate new value + OutParameter // Pre-allocated out-parameter by reference (test works only for types < qint64) +}; + +Q_DECLARE_METATYPE(Mode) + +void tst_Conversion::conversion_data() +{ + QTest::addColumn<QVariant>("value"); + QTest::addColumn<uint>("expectedType"); + QTest::addColumn<QByteArray>("typeName"); + QTest::addColumn<Mode>("mode"); + + QVariant qvar; + QByteArray typeName; + + qvar = QVariant('a'); + typeName = QByteArrayLiteral("char"); + QTest::newRow("char") + << qvar << uint(VT_I1) << typeName << ByValue; + QTest::newRow("char-ref") + << qvar << uint(VT_I1 | VT_BYREF) << typeName << ByReference; + QTest::newRow("char-out") + << qvar << uint(VT_I1 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(uchar(197)); + typeName = QByteArrayLiteral("uchar"); + QTest::newRow("uchar") + << qvar << uint(VT_UI1) << typeName << ByValue; + QTest::newRow("uchar-ref") + << qvar << uint(VT_UI1 | VT_BYREF) << typeName << ByReference; + QTest::newRow("uchar-out") + << qvar << uint(VT_UI1 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(ushort(42)); + typeName = QByteArrayLiteral("ushort"); + QTest::newRow("ushort") + << qvar << uint(VT_UI2) << typeName << ByValue; + QTest::newRow("ushort-ref") + << qvar << uint(VT_UI2 | VT_BYREF) << typeName << ByReference; + QTest::newRow("ushort-out") + << qvar << uint(VT_UI2 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(short(42)); + typeName = QByteArrayLiteral("short"); + QTest::newRow("short") + << qvar << uint(VT_I2) << typeName << ByValue; + QTest::newRow("short-ref") + << qvar << uint(VT_I2 | VT_BYREF) << typeName << ByReference; + QTest::newRow("short-out") + << qvar << uint(VT_I2 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(42); + typeName.clear(); + QTest::newRow("int") + << qvar << uint(VT_I4) << typeName << ByValue; + QTest::newRow("int-ref") + << qvar << uint(VT_I4 | VT_BYREF) << typeName << ByReference; + QTest::newRow("int-out") + << qvar << uint(VT_I4 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(42u); + typeName.clear(); + QTest::newRow("uint") + << qvar << uint(VT_UI4) << typeName << ByValue; + QTest::newRow("uint-ref") + << qvar << uint(VT_UI4 | VT_BYREF) << typeName << ByReference; + QTest::newRow("uint-out") + << qvar << uint(VT_UI4 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(qint64(42)); + typeName.clear(); + QTest::newRow("int64") + << qvar << uint(VT_I8) << typeName << ByValue; + QTest::newRow("int64-ref") + << qvar << uint(VT_I8 | VT_BYREF) << typeName << ByReference; + QTest::newRow("int64-out") + << qvar << uint(VT_I8 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(quint64(42u)); + typeName.clear(); + QTest::newRow("uint64") + << qvar << uint(VT_UI8) << typeName << ByValue; + QTest::newRow("uint64-ref") + << qvar << uint(VT_UI8 | VT_BYREF) << typeName << ByReference; + QTest::newRow("uint64-out") + << qvar << uint(VT_UI8 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(3.141f); + typeName = QByteArrayLiteral("float"); + QTest::newRow("float") + << qvar << uint(VT_R4) << typeName << ByValue; + QTest::newRow("float-ref") + << qvar << uint(VT_R4 | VT_BYREF) << typeName << ByReference; + QTest::newRow("float-out") + << qvar << uint(VT_R4 | VT_BYREF) << typeName << OutParameter; + + qvar = QVariant(3.141); + typeName.clear(); + QTest::newRow("double") + << qvar << uint(VT_R8) << typeName << ByValue; + QTest::newRow("double-ref") + << qvar << uint(VT_R8 | VT_BYREF) << typeName << ByReference; + QTest::newRow("double-out") + << qvar << uint(VT_R8 | VT_BYREF) << typeName << OutParameter; + + qvar = QDateTime(QDate(1968, 3, 9), QTime(10, 0)); + typeName.clear(); + QTest::newRow("datetime") + << qvar << uint(VT_DATE) << typeName << ByValue; + QTest::newRow("datetime-ref") + << qvar << uint(VT_DATE | VT_BYREF) << typeName << ByReference; + QTest::newRow("datetime-out") + << qvar << uint(VT_DATE | VT_BYREF) << typeName << OutParameter; +} + +void tst_Conversion::conversion() +{ + QFETCH(QVariant, value); + QFETCH(uint, expectedType); + QFETCH(QByteArray, typeName); + QFETCH(Mode, mode); + + VARIANT variant; + VariantInit(&variant); + if (mode == OutParameter) { + variant.vt = expectedType | VT_BYREF; + variant.pullVal = new ULONGLONG(0); + } + + QVERIFY(QVariantToVARIANT_container(value, variant, typeName, mode != ByValue)); + QCOMPARE(uint(variant.vt), expectedType); + const QVariant converted = VARIANTToQVariant_container(variant, QByteArray()); + QCOMPARE(converted, value); + + if (mode == OutParameter) + delete variant.pullVal; +} + +QTEST_MAIN(tst_Conversion) +#include "tst_conversion.moc" |