diff options
author | Arno Rehn <a.rehn@menlosystems.com> | 2019-01-14 15:31:57 +0100 |
---|---|---|
committer | Arno Rehn <a.rehn@menlosystems.com> | 2019-01-31 08:19:11 +0000 |
commit | 38f097ba76fe5b26ccc15a5599e312336200e564 (patch) | |
tree | 45cca5f4d81fcce5b1f41c09330f7f17605f57ed /src | |
parent | c80cbce7ac3b38a45a38b57795c7eb19e5177a17 (diff) | |
download | qtwebchannel-38f097ba76fe5b26ccc15a5599e312336200e564.tar.gz |
Correctly convert enums and QFlags from and to JSON
Previously, enums declared with Q_ENUM were stringified in the
conversion to JSON and QFlags did not work at all. The conversion of
QJsonValue(int) to enum worked fine, however. This patch implements
some extra logic for detecting enums and QFlags, thus correctly
converting to and from integers.
[ChangeLog] Enum values and QFlags are now correctly converted to and
from integers in the JS interface
Fixes: QTBUG-72924
Change-Id: I23d4a1120b805201c8d450edbd990aad5ad258a2
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index 9e08453..6ea3480 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Copyright (C) 2019 Menlo Systems GmbH, author Arno Rehn <a.rehn@menlosystems.com> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebChannel module of the Qt Toolkit. @@ -56,6 +57,32 @@ QT_BEGIN_NAMESPACE namespace { +// FIXME: QFlags don't have the QMetaType::IsEnumeration flag set, although they have a QMetaEnum entry in the QMetaObject. +// They only way to detect registered QFlags types is to find the named entry in the QMetaObject's enumerator list. +// Ideally, this would be fixed in QMetaType. +bool isQFlagsType(uint id) +{ + QMetaType type(id); + + // Short-circuit to avoid more expensive operations + QMetaType::TypeFlags flags = type.flags(); + if (flags.testFlag(QMetaType::PointerToQObject) || flags.testFlag(QMetaType::IsEnumeration) + || flags.testFlag(QMetaType::SharedPointerToQObject) || flags.testFlag(QMetaType::WeakPointerToQObject) + || flags.testFlag(QMetaType::TrackingPointerToQObject) || flags.testFlag(QMetaType::IsGadget)) + { + return false; + } + + const QMetaObject *mo = type.metaObject(); + if (!mo) { + return false; + } + + QByteArray name = QMetaType::typeName(id); + name = name.mid(name.lastIndexOf(":") + 1); + return mo->indexOfEnumerator(name.constData()) > -1; +} + MessageType toType(const QJsonValue &value) { int i = value.toInt(-1); @@ -487,6 +514,9 @@ QVariant QMetaObjectPublisher::toVariant(const QJsonValue &value, int targetType if (unwrappedObject == Q_NULLPTR) qWarning() << "Cannot not convert non-object argument" << value << "to QObject*."; return QVariant::fromValue(unwrappedObject); + } else if (isQFlagsType(targetType)) { + int flagsValue = value.toInt(); + return QVariant(targetType, reinterpret_cast<const void*>(&flagsValue)); } // this converts QJsonObjects to QVariantMaps, which is not desired when @@ -570,6 +600,10 @@ QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelA objectInfo[KEY_DATA] = classInfo; return objectInfo; + } else if (QMetaType::typeFlags(result.userType()).testFlag(QMetaType::IsEnumeration)) { + return result.toInt(); + } else if (isQFlagsType(result.userType())) { + return *reinterpret_cast<const int*>(result.constData()); #ifndef QT_NO_JSVALUE } else if (result.canConvert<QJSValue>()) { // Workaround for keeping QJSValues from QVariant. |