summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@theqtcompany.com>2015-03-19 16:39:50 +0100
committerFriedemann Kleint <Friedemann.Kleint@theqtcompany.com>2015-03-24 11:37:36 +0000
commit7b9c9af588e2f6e40534fe6ca01f9eade3cc36c2 (patch)
tree5d058eda1a2fa5e7cd1b3d89a9617ef28af7b9d8
parent1a6011d23e5ac37e5ded891b56a3fa5f3789ab3d (diff)
downloadqtactiveqt-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.cpp157
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/conversion/conversion.pro3
-rw-r--r--tests/auto/conversion/tst_conversion.cpp204
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"