diff options
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 34 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.cpp | 43 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.h | 14 |
3 files changed, 91 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. diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index b62a596..6764204 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.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. @@ -341,8 +342,12 @@ void TestWebChannel::testInfoForObject() QJsonObject fooEnum; fooEnum["Asdf"] = TestObject::Asdf; fooEnum["Bar"] = TestObject::Bar; + QJsonObject testFlags; + testFlags["FirstFlag"] = static_cast<int>(TestObject::FirstFlag); + testFlags["SecondFlag"] = static_cast<int>(TestObject::SecondFlag); QJsonObject expected; expected["Foo"] = fooEnum; + expected["TestFlags"] = testFlags; QCOMPARE(info["enums"].toObject(), expected); } @@ -755,6 +760,44 @@ void TestWebChannel::testPassWrappedObjectBack() QCOMPARE(registeredObj.mReturnedObject, &returnedObjProperty); } +void TestWebChannel::testWrapValues() +{ + QWebChannel channel; + channel.connectTo(m_dummyTransport); + + { + QVariant variant = QVariant::fromValue(TestObject::Asdf); + QJsonValue value = channel.d_func()->publisher->wrapResult(variant, m_dummyTransport); + QVERIFY(value.isDouble()); + QCOMPARE(value.toInt(), (int) TestObject::Asdf); + } + { + TestObject::TestFlags flags = TestObject::FirstFlag | TestObject::SecondFlag; + QVariant variant = QVariant::fromValue(flags); + QJsonValue value = channel.d_func()->publisher->wrapResult(variant, m_dummyTransport); + QVERIFY(value.isDouble()); + QCOMPARE(value.toInt(), (int) flags); + } +} + +void TestWebChannel::testJsonToVariant() +{ + QWebChannel channel; + channel.connectTo(m_dummyTransport); + + { + QVariant variant = QVariant::fromValue(TestObject::Asdf); + QVariant convertedValue = channel.d_func()->publisher->toVariant(static_cast<int>(TestObject::Asdf), variant.userType()); + QCOMPARE(convertedValue, variant); + } + { + TestObject::TestFlags flags = TestObject::FirstFlag | TestObject::SecondFlag; + QVariant variant = QVariant::fromValue(flags); + QVariant convertedValue = channel.d_func()->publisher->toVariant(static_cast<int>(flags), variant.userType()); + QCOMPARE(convertedValue, variant); + } +} + void TestWebChannel::testInfiniteRecursion() { QWebChannel channel; diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h index 85846e7..386f314 100644 --- a/tests/auto/webchannel/tst_webchannel.h +++ b/tests/auto/webchannel/tst_webchannel.h @@ -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. @@ -92,6 +93,13 @@ public: Asdf }; + enum TestFlag : quint16 { + FirstFlag = 0x1, + SecondFlag = 0x2 + }; + Q_DECLARE_FLAGS(TestFlags, TestFlag) + Q_FLAG(TestFlags) + Foo foo() const {return Bar;} int asdf() const {return 42;} QString bar() const {return QString();} @@ -160,6 +168,8 @@ public: QString mProp; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(TestObject::TestFlags) + class BenchObject : public QObject { Q_OBJECT @@ -303,6 +313,8 @@ private slots: void testWrapRegisteredObject(); void testRemoveUnusedTransports(); void testPassWrappedObjectBack(); + void testWrapValues(); + void testJsonToVariant(); void testInfiniteRecursion(); void testAsyncObject(); void testDeletionDuringMethodInvocation_data(); @@ -330,4 +342,6 @@ private: QT_END_NAMESPACE +Q_DECLARE_METATYPE(TestObject::Foo) + #endif // TST_WEBCHANNEL_H |