diff options
Diffstat (limited to 'src/activeqt/shared/qaxtypes.cpp')
-rw-r--r-- | src/activeqt/shared/qaxtypes.cpp | 411 |
1 files changed, 210 insertions, 201 deletions
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 40f5e0a..d9175ea 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -1,54 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the ActiveQt framework of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#define NOMINMAX +// Copyright (C) 2015 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include <ocidl.h> #include <olectl.h> @@ -60,6 +11,7 @@ #include <qcursor.h> #include <qpixmap.h> #include <qpainter.h> +#include <private/qpixmap_win_p.h> #include <qobject.h> #include <qdebug.h> #ifdef QAX_SERVER @@ -139,9 +91,6 @@ static QFont IFontToQFont(IFont *f) return font; } -Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); -Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0); - static IPictureDisp *QPixmapToIPicture(const QPixmap &pixmap) { IPictureDisp *pic = nullptr; @@ -263,26 +212,42 @@ static QByteArray msgOutParameterNotSupported(const QByteArray &type) } \ } +static qsizetype columnCount2D(const QVariantList &list) +{ + if (!list.isEmpty()) { + const auto &firstElement = list.at(0); + const auto type = firstElement.typeId(); + if (type != QMetaType::QString && type != QMetaType::QByteArray + && firstElement.canConvert<QVariantList>()) { + return firstElement.toList().size(); + } + } + return 0; +} + bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out) { QVariant qvar = var; // "type" is the expected type, so coerce if necessary - const QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName); - if (proptype != QVariant::Invalid - && proptype != QVariant::UserType - && proptype != int(QMetaType::QVariant) - && proptype != qvar.type()) { - if (qvar.canConvert(proptype)) - qvar.convert(proptype); + const int proptype = typeName.isEmpty() + ? QMetaType::UnknownType + : QMetaType::fromName(typeName).id(); + if (proptype != QMetaType::UnknownType + && proptype != QMetaType::User + && proptype != QMetaType::QVariant + && proptype != qvar.metaType().id()) { + const QMetaType metaType(proptype); + if (qvar.canConvert(metaType)) + qvar.convert(metaType); else - qvar = QVariant(proptype); + qvar = QVariant(metaType); } if (out && arg.vt == (VT_VARIANT|VT_BYREF) && arg.pvarVal) { return QVariantToVARIANT(var, *arg.pvarVal, typeName, false); } - if (out && proptype == QVariant::UserType && typeName == "QVariant") { + if (out && proptype == QMetaType::QVariant) { VARIANT *pVariant = new VARIANT; QVariantToVARIANT(var, *pVariant, QByteArray(), false); arg.vt = VT_VARIANT|VT_BYREF; @@ -290,8 +255,8 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type return true; } - switch ((int)qvar.type()) { - case QVariant::String: + switch (qvar.metaType().id()) { + case QMetaType::QString: if (out && arg.vt == (VT_BSTR|VT_BYREF)) { if (*arg.pbstrVal) SysFreeString(*arg.pbstrVal); @@ -323,15 +288,15 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type QVARIANT_TO_VARIANT_POD(ushort, qvariant_cast<ushort>(qvar), out, VT_UI2, uiVal, puiVal) break; - case QVariant::Int: + case QMetaType::Int: QVARIANT_TO_VARIANT_POD(long, qvar.toInt(), out, VT_I4, lVal, plVal) break; - case QVariant::UInt: + case QMetaType::UInt: QVARIANT_TO_VARIANT_POD(uint, qvar.toUInt(), out, VT_UI4, uintVal, puintVal) break; - case QVariant::LongLong: + case QMetaType::LongLong: if (out && arg.vt == (VT_CY|VT_BYREF)) { // VT_CY: Currency arg.pcyVal->int64 = qvar.toLongLong(); } else { @@ -339,7 +304,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::ULongLong: + case QMetaType::ULongLong: if (out && arg.vt == (VT_CY|VT_BYREF)) { // VT_CY: Currency arg.pcyVal->int64 = qvar.toULongLong(); } else { @@ -347,7 +312,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::Bool: + case QMetaType::Bool: QVARIANT_TO_VARIANT_POD(short, short(qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE), out, VT_BOOL, boolVal, pboolVal) break; @@ -360,19 +325,19 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type QVARIANT_TO_VARIANT_POD(double, qvar.toDouble(), out, VT_R8, dblVal, pdblVal) break; - case QVariant::Color: + case QMetaType::QColor: 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: // DATE = double + case QMetaType::QDate: + case QMetaType::QTime: + case QMetaType::QDateTime: // DATE = double QVARIANT_TO_VARIANT_POD(DATE, QDateTimeToDATE(qvar.toDateTime()), out, VT_DATE, date, pdate) break; - case QVariant::Font: + case QMetaType::QFont: if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { if (*arg.ppdispVal) (*arg.ppdispVal)->Release(); @@ -387,7 +352,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::Pixmap: + case QMetaType::QPixmap: if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { if (*arg.ppdispVal) (*arg.ppdispVal)->Release(); @@ -402,7 +367,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::Cursor: + case QMetaType::QCursor: { #ifndef QT_NO_CURSOR int shape = qvariant_cast<QCursor>(qvar).shape(); @@ -439,37 +404,37 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::List: + case QMetaType::QVariantList: { const auto list = qvar.toList(); - const int count = list.count(); + const qsizetype count = list.size(); VARTYPE vt = VT_VARIANT; - QVariant::Type listType = QVariant::Type(QMetaType::QVariant); + int listType = QMetaType::QVariant; if (!typeName.isEmpty() && typeName.startsWith("QList<")) { const QByteArray listTypeName = typeName.mid(6, typeName.length() - 7); // QList<int> -> int - listType = QVariant::nameToType(listTypeName); + listType = QMetaType::fromName(listTypeName).id(); } VARIANT variant; void *pElement = &variant; switch(listType) { - case QVariant::Int: + case QMetaType::Int: vt = VT_I4; pElement = &variant.lVal; break; - case QVariant::Double: + case QMetaType::Double: vt = VT_R8; pElement = &variant.dblVal; break; - case QVariant::DateTime: + case QMetaType::QDateTime: vt = VT_DATE; pElement = &variant.date; break; - case QVariant::Bool: + case QMetaType::Bool: vt = VT_BOOL; pElement = &variant.boolVal; break; - case QVariant::LongLong: + case QMetaType::LongLong: vt = VT_I8; pElement = &variant.llVal; break; @@ -477,41 +442,33 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type break; } SAFEARRAY *array = nullptr; - bool is2D = false; // If the first element in the array is a list the whole list is // treated as a 2D array. The column count is taken from the 1st element. - if (count) { - QVariantList col = list.at(0).toList(); - int maxColumns = col.count(); - if (maxColumns) { - is2D = true; - SAFEARRAYBOUND rgsabound[2] = { {0, 0}, {0, 0} }; - rgsabound[0].cElements = count; - rgsabound[1].cElements = maxColumns; - array = SafeArrayCreate(VT_VARIANT, 2, rgsabound); - LONG rgIndices[2]; - for (LONG i = 0; i < count; ++i) { - rgIndices[0] = i; - QVariantList columns = list.at(i).toList(); - int columnCount = qMin(maxColumns, columns.count()); - for (LONG j = 0; j < columnCount; ++j) { - const QVariant &elem = columns.at(j); - VariantInit(&variant); - QVariantToVARIANT(elem, variant, elem.typeName()); - rgIndices[1] = j; - SafeArrayPutElement(array, rgIndices, pElement); - clearVARIANT(&variant); - } + if (qsizetype maxColumns = columnCount2D(list)) { + SAFEARRAYBOUND rgsabound[2] = { {0, 0}, {0, 0} }; + rgsabound[0].cElements = count; + rgsabound[1].cElements = maxColumns; + array = SafeArrayCreate(VT_VARIANT, 2, rgsabound); + LONG rgIndices[2]; + for (LONG i = 0; i < count; ++i) { + rgIndices[0] = i; + QVariantList columns = list.at(i).toList(); + qsizetype columnCount = qMin(maxColumns, columns.size()); + for (LONG j = 0; j < columnCount; ++j) { + const QVariant &elem = columns.at(j); + VariantInit(&variant); + QVariantToVARIANT(elem, variant, elem.typeName()); + rgIndices[1] = j; + SafeArrayPutElement(array, rgIndices, pElement); + clearVARIANT(&variant); } - } - } - if (!is2D) { + } else { array = SafeArrayCreateVector(vt, 0, count); for (LONG index = 0; index < count; ++index) { QVariant elem = list.at(index); - if (listType != QVariant::Type(QMetaType::QVariant)) - elem.convert(listType); + if (listType != QMetaType::QVariant) + elem.convert(QMetaType(listType)); VariantInit(&variant); QVariantToVARIANT(elem, variant, elem.typeName()); SafeArrayPutElement(array, &index, pElement); @@ -533,10 +490,10 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::StringList: + case QMetaType::QStringList: { const QStringList list = qvar.toStringList(); - const int count = list.count(); + const qsizetype count = list.size(); SAFEARRAY *array = SafeArrayCreateVector(VT_BSTR, 0, count); for (LONG index = 0; index < count; ++index) { QString elem = list.at(index); @@ -560,10 +517,10 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; - case QVariant::ByteArray: + case QMetaType::QByteArray: { const QByteArray bytes = qvar.toByteArray(); - const uint count = bytes.count(); + const uint count = static_cast<uint>(bytes.size()); SAFEARRAY *array = SafeArrayCreateVector(VT_UI1, 0, count); if (count) { const char *data = bytes.constData(); @@ -589,9 +546,9 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type break; #ifdef QAX_SERVER - case QVariant::Rect: - case QVariant::Size: - case QVariant::Point: + case QMetaType::QRect: + case QMetaType::QSize: + case QMetaType::QPoint: { typedef HRESULT(WINAPI* PGetRecordInfoFromTypeInfo)(ITypeInfo *, IRecordInfo **); static PGetRecordInfoFromTypeInfo pGetRecordInfoFromTypeInfo = 0; @@ -606,9 +563,10 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type ITypeInfo *typeInfo = 0; IRecordInfo *recordInfo = 0; - CLSID clsid = qvar.type() == QVariant::Rect ? CLSID_QRect - :qvar.type() == QVariant::Size ? CLSID_QSize - :CLSID_QPoint; + const int vType = qvar.metaType().id(); + CLSID clsid = vType == QMetaType::QRect + ? CLSID_QRect + : vType == QMetaType::QSize ? CLSID_QSize : CLSID_QPoint; qAxTypeLibrary->GetTypeInfoOfGuid(clsid, &typeInfo); if (!typeInfo) break; @@ -618,20 +576,20 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type break; void *record = 0; - switch (qvar.type()) { - case QVariant::Rect: + switch (qvar.metaType().id()) { + case QMetaType::QRect: { QRect qrect(qvar.toRect()); recordInfo->RecordCreateCopy(&qrect, &record); } break; - case QVariant::Size: + case QMetaType::QSize: { QSize qsize(qvar.toSize()); recordInfo->RecordCreateCopy(&qsize, &record); } break; - case QVariant::Point: + case QMetaType::QPoint: { QPoint qpoint(qvar.toPoint()); recordInfo->RecordCreateCopy(&qpoint, &record); @@ -653,8 +611,22 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } break; #endif // QAX_SERVER - case QVariant::UserType: - { + + case QMetaType::UnknownType: // default-parameters not set + if (out && arg.vt == (VT_ERROR|VT_BYREF)) { + *arg.plVal = DISP_E_PARAMNOTFOUND; + } else { + arg.vt = VT_ERROR; + arg.lVal = DISP_E_PARAMNOTFOUND; + if (out) { + arg.plVal = new long(arg.lVal); + arg.vt |= VT_BYREF; + } + } + break; + + default: + if (qvar.metaType().id() >= QMetaType::User) { QByteArray subType = qvar.typeName(); #ifdef QAX_SERVER if (subType.endsWith('*')) @@ -704,7 +676,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type qAxFactory()->createObjectWrapper(static_cast<QObject*>(user), &arg.pdispVal); } #else - } else if (QMetaType::type(subType)) { + } else if (QMetaType::fromName(subType).id() != QMetaType::UnknownType) { if (out) { qWarning().noquote() << msgOutParameterNotSupported("subtype"); arg.vt = VT_EMPTY; @@ -719,33 +691,42 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type } else { return false; } + } else { // >= User + return false; } break; - case QVariant::Invalid: // default-parameters not set - if (out && arg.vt == (VT_ERROR|VT_BYREF)) { - *arg.plVal = DISP_E_PARAMNOTFOUND; - } else { - arg.vt = VT_ERROR; - arg.lVal = DISP_E_PARAMNOTFOUND; - if (out) { - arg.plVal = new long(arg.lVal); - arg.vt |= VT_BYREF; - } - } - break; - - default: - return false; } Q_ASSERT(!out || (arg.vt & VT_BYREF)); return true; } +#ifdef QAX_SERVER +static QVariant axServer(IUnknown *unknown, const QByteArray &typeName) +{ + IAxServerBase *iface = nullptr; + if (unknown && typeName != "IDispatch*" && typeName != "IUnknown*") + unknown->QueryInterface(IID_IAxServerBase, reinterpret_cast<void**>(&iface)); + if (iface == nullptr) + return {}; + + auto *qObj = iface->qObject(); + iface->Release(); + QByteArray pointerType = qObj ? QByteArray(qObj->metaObject()->className()) + '*' : typeName; + QMetaType pointerMetaType = QMetaType::fromName(pointerType); + if (pointerMetaType.id() == QMetaType::UnknownType) + pointerMetaType = QMetaType(qRegisterMetaType<QObject *>(pointerType)); + return QVariant(pointerMetaType, &qObj); +} +#endif // QAX_SERVER + #undef QVARIANT_TO_VARIANT_POD /* - Returns \a arg as a QVariant of type \a type. + Returns \a arg as a QVariant of type \a typeName or \a type. + + NOTE: If a \a typeName is specified, value type is assumed. to + get/create a pointer type, provide the type id in the \a type argument. Used by @@ -762,8 +743,16 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type - QAxBase::dynamicCall(return value) - IPropertyBag::Write (QtPropertyBag) */ -QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint type) +QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, int type) { + int nameTypeId = QMetaType::UnknownType; + if (type == QMetaType::UnknownType && !typeName.isEmpty()) { + auto name = typeName.endsWith('*') + ? QByteArrayView{typeName.constData(), typeName.size() - 1} + : QByteArrayView{typeName}; + nameTypeId = QMetaType::fromName(name).id(); + } + QVariant var; switch(arg.vt) { case VT_BSTR: @@ -781,38 +770,38 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint case VT_I1: var = arg.cVal; if (typeName == "char") - type = QVariant::Int; + type = QMetaType::Int; break; case VT_I1|VT_BYREF: var = *arg.pcVal; if (typeName == "char") - type = QVariant::Int; + type = QMetaType::Int; break; case VT_I2: var = arg.iVal; if (typeName == "short") - type = QVariant::Int; + type = QMetaType::Int; break; case VT_I2|VT_BYREF: var = *arg.piVal; if (typeName == "short") - type = QVariant::Int; + type = QMetaType::Int; break; case VT_I4: - if (type == QVariant::Color || (!type && typeName == "QColor")) + if (type == QMetaType::QColor || nameTypeId == QMetaType::QColor) var = QVariant::fromValue(OLEColorToQColor(arg.lVal)); #ifndef QT_NO_CURSOR - else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) + else if (type == QMetaType::QCursor || nameTypeId == QMetaType::QCursor) var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); #endif else var = (int)arg.lVal; break; case VT_I4|VT_BYREF: - if (type == QVariant::Color || (!type && typeName == "QColor")) + if (type == QMetaType::QColor || nameTypeId == QMetaType::QColor) var = QVariant::fromValue(OLEColorToQColor((int)*arg.plVal)); #ifndef QT_NO_CURSOR - else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) + else if (type == QMetaType::QCursor || nameTypeId == QMetaType::QCursor) var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); #endif else @@ -837,20 +826,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint var = *arg.puiVal; break; case VT_UI4: - if (type == QVariant::Color || (!type && typeName == "QColor")) + if (type == QMetaType::QColor || nameTypeId == QMetaType::QColor) var = QVariant::fromValue(OLEColorToQColor(arg.ulVal)); #ifndef QT_NO_CURSOR - else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) + else if (type == QMetaType::QCursor || nameTypeId == QMetaType::QCursor) var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); #endif else var = (int)arg.ulVal; break; case VT_UI4|VT_BYREF: - if (type == QVariant::Color || (!type && typeName == "QColor")) + if (type == QMetaType::QColor || nameTypeId == QMetaType::QColor) var = QVariant::fromValue(OLEColorToQColor((uint)*arg.pulVal)); #ifndef QT_NO_CURSOR - else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) + else if (type == QMetaType::QCursor || nameTypeId == QMetaType::QCursor) var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); #endif else @@ -894,18 +883,18 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_DATE: var = DATEToQDateTime(arg.date); - if (type == QVariant::Date || (!type && (typeName == "QDate" || typeName == "QDate*"))) { - var.convert(QVariant::Date); - } else if (type == QVariant::Time || (!type && (typeName == "QTime" || typeName == "QTime*"))) { - var.convert(QVariant::Time); + if (type == QMetaType::QDate || nameTypeId == QMetaType::QDate) { + var.convert(QMetaType(QMetaType::QDate)); + } else if (type == QMetaType::QTime || nameTypeId == QMetaType::QTime) { + var.convert(QMetaType(QMetaType::QTime)); } break; case VT_DATE|VT_BYREF: var = DATEToQDateTime(*arg.pdate); - if (type == QVariant::Date || (!type && (typeName == "QDate" || typeName == "QDate*"))) { - var.convert(QVariant::Date); - } else if (type == QVariant::Time || (!type && (typeName == "QTime" || typeName == "QTime*"))) { - var.convert(QVariant::Time); + if (type == QMetaType::QDate || nameTypeId == QMetaType::QDate) { + var.convert(QMetaType(QMetaType::QDate)); + } else if (type == QMetaType::QTime || nameTypeId == QMetaType::QTime) { + var.convert(QMetaType(QMetaType::QTime)); } break; case VT_VARIANT: @@ -923,7 +912,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint disp = *arg.ppdispVal; else disp = arg.pdispVal; - if (type == QVariant::Font || (!type && (typeName == "QFont" || typeName == "QFont*"))) { + if (type == QMetaType::QFont || nameTypeId == QMetaType::QFont) { IFont *ifont = nullptr; if (disp) disp->QueryInterface(IID_IFont, reinterpret_cast<void**>(&ifont)); @@ -933,7 +922,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint } else { var = QVariant::fromValue(QFont()); } - } else if (type == QVariant::Pixmap || (!type && (typeName == "QPixmap" || typeName == "QPixmap*"))) { + } else if (type == QMetaType::QPixmap || nameTypeId == QMetaType::QPixmap) { IPicture *ipic = nullptr; if (disp) disp->QueryInterface(IID_IPicture, reinterpret_cast<void**>(&ipic)); @@ -945,40 +934,55 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint } } else { #ifdef QAX_SERVER - IAxServerBase *iface = 0; - if (disp && typeName != "IDispatch*") - disp->QueryInterface(IID_IAxServerBase, reinterpret_cast<void**>(&iface)); - if (iface) { - QObject *qObj = iface->qObject(); - iface->Release(); - QByteArray pointerType = qObj ? QByteArray(qObj->metaObject()->className()) + '*' : typeName; - int pointerTypeId = QMetaType::type(pointerType); - if (!pointerTypeId) - pointerTypeId = qRegisterMetaType<QObject *>(pointerType); - var = QVariant(pointerTypeId, &qObj); + if (auto axs = axServer(disp, typeName); axs.isValid()) { + var = axs; } else #endif { if (!typeName.isEmpty()) { if (arg.vt & VT_BYREF) { - var = QVariant(qRegisterMetaType<IDispatch**>("IDispatch**"), &arg.ppdispVal); + // When the dispinterface is a return value, just assign it to a QVariant + static const int dispatchId = qRegisterMetaType<IDispatch**>("IDispatch**"); + var = QVariant(QMetaType(dispatchId), &arg.ppdispVal); } else { #ifndef QAX_SERVER if (typeName == "QVariant") { + // If a QVariant is requested, wrap the dispinterface in a QAxObject QAxObject *object = new QAxObject(disp); var = QVariant::fromValue<QAxObject*>(object); - } else if (typeName != "IDispatch*" && QMetaType::type(typeName)) { - QByteArray typeNameStr = QByteArray(typeName); + } else if (typeName != "IDispatch*" && QMetaType::fromName(typeName).id() != QMetaType::UnknownType) { + // Conversion from IDispatch* to a wrapper type is requested. Here, the requested + // wrapper type is constructed around the dispinterface, and then returned as + // a QVariant containing a pointer to the wrapper type. + + // Calculate the value type from a potential pointer type + QByteArray valueTypeStr = QByteArray(typeName); int pIndex = typeName.lastIndexOf('*'); if (pIndex != -1) - typeNameStr = typeName.left(pIndex); - int metaType = QMetaType::type(typeNameStr); - Q_ASSERT(metaType != 0); - auto object = static_cast<QAxObject*>(qax_createObjectWrapper(metaType, disp)); - var = QVariant(QMetaType::type(typeName), &object); - } else + valueTypeStr = typeName.left(pIndex); + + const QMetaType metaValueType = QMetaType::fromName(valueTypeStr); + Q_ASSERT(metaValueType.id() != QMetaType::UnknownType); + + auto object = static_cast<QAxObject*>(qax_createObjectWrapper(metaValueType.id(), disp)); + + // Return object as the original type + const QMetaType returnType = QMetaType::fromName(typeName); + Q_ASSERT(metaValueType.id() != QMetaType::UnknownType); + + var = QVariant(returnType, &object); + + // The result must be a pointer to an instance derived from QObject + Q_ASSERT((var.metaType().flags() & QMetaType::PointerToQObject) != 0); + } else { +#endif + // An IDispatch pointer is requested, no conversion required, just return as QVariant + // containing the pointer. + static const int dispatchId = qRegisterMetaType<IDispatch*>(typeName.constData()); + var = QVariant(QMetaType(dispatchId), &disp); +#ifndef QAX_SERVER + } #endif - var = QVariant(qRegisterMetaType<IDispatch*>(typeName), &disp); } } } @@ -994,6 +998,10 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint else unkn = arg.punkVal; var.setValue(unkn); +#ifdef QAX_SERVER + if (auto axs = axServer(unkn, typeName); axs.isValid()) + var = axs; +#endif } break; case VT_ARRAY|VT_VARIANT: @@ -1219,22 +1227,23 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; } - QVariant::Type proptype = (QVariant::Type)type; - if (proptype == QVariant::Invalid && !typeName.isEmpty()) { - if (typeName != "QVariant") - proptype = QVariant::nameToType(typeName); - } - if (proptype != QVariant::Type(QMetaType::QVariant) && proptype != QVariant::LastType && proptype != QVariant::Invalid && var.type() != proptype) { - if (var.canConvert(proptype)) { + const int proptype = type != QMetaType::UnknownType || typeName.isEmpty() || typeName == "QVariant" + ? type : nameTypeId; + + if (proptype != QMetaType::QVariant && proptype != QMetaType::UnknownType + && var.metaType().id() != proptype) { + QMetaType propertyMetaType(proptype); + if (var.canConvert(propertyMetaType)) { QVariant oldvar = var; - if (oldvar.convert(proptype)) + if (oldvar.convert(propertyMetaType)) var = oldvar; - } else if (proptype == QVariant::StringList && var.type() == QVariant::List) { + } else if (proptype == QMetaType::QStringList + && var.metaType().id() == QMetaType::QVariantList) { bool allStrings = true; QStringList strings; const QVariantList list(var.toList()); for (const QVariant &variant : list) { - if (variant.canConvert(QVariant::String)) + if (variant.canConvert<QString>()) strings << variant.toString(); else allStrings = false; |