diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2016-05-25 18:20:30 +0200 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2016-05-26 09:56:54 +0000 |
commit | bec50124b893c4632829d9806f49f64c4debf936 (patch) | |
tree | 90986763724e26b5f0b5df993dda06b3f2086081 | |
parent | 97c876a1353f29ed0129360f013f2529bed69d98 (diff) | |
download | qtwebchannel-bec50124b893c4632829d9806f49f64c4debf936.tar.gz |
Fix setting properties of QJson{Value,Array,Object} type.
Similar to the previous issue, where these types were not properly
converted to QVariant when invoking a method, we manually do the
conversion now to get the desired behavior. The culprit is again
that QJsonValue::toVariant converts an object e.g. to a QVariantMap,
and not to a QVariant containing a QJsonObject.
[ChangeLog] QObject properties of type QJsonValue, QJsonArray or
QJsonObject can now be set via the Qt WebChannel.
Task-number: QTBUG-48198
Change-Id: I5d574b1a5cffd6d6ad9b555f2a3e872b9c3425a7
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 20 | ||||
-rw-r--r-- | src/webchannel/qmetaobjectpublisher_p.h | 5 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.cpp | 94 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.h | 25 |
4 files changed, 132 insertions, 12 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index e85bc76..0fa4ae2 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -410,6 +410,16 @@ QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const int met return returnValue; } +void QMetaObjectPublisher::setProperty(QObject *object, const int propertyIndex, const QJsonValue &value) +{ + QMetaProperty property = object->metaObject()->property(propertyIndex); + if (!property.isValid()) { + qWarning() << "Cannot set unknown property" << propertyIndex << "of object" << object; + } else if (!property.write(object, toVariant(value, property.userType()))) { + qWarning() << "Could not write value " << value << "to property" << property.name() << "of object" << object; + } +} + void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments) { if (!webChannel || webChannel->d_func()->transports.isEmpty()) { @@ -607,14 +617,8 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel } else if (type == TypeDisconnectFromSignal) { signalHandler.disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1)); } else if (type == TypeSetProperty) { - const int propertyIdx = message.value(KEY_PROPERTY).toInt(-1); - QMetaProperty property = object->metaObject()->property(propertyIdx); - if (!property.isValid()) { - qWarning() << "Cannot set unknown property" << message.value(KEY_PROPERTY) << "of object" << objectName; - } else if (!object->metaObject()->property(propertyIdx).write(object, message.value(KEY_VALUE).toVariant())) { - qWarning() << "Could not write value " << message.value(KEY_VALUE) - << "to property" << property.name() << "of object" << objectName; - } + setProperty(object, message.value(KEY_PROPERTY).toInt(-1), + message.value(KEY_VALUE)); } } } diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index cb3350e..b0ebd84 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -150,6 +150,11 @@ public: QVariant invokeMethod(QObject *const object, const int methodIndex, const QJsonArray &args); /** + * Set the value of property @p propertyIndex on @p object to @p value. + */ + void setProperty(QObject *object, const int propertyIndex, const QJsonValue &value); + + /** * Callback of the signalHandler which forwards the signal invocation to the webchannel clients. */ void signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments); diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index 4db8bae..93c7aa8 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.cpp @@ -200,35 +200,70 @@ TestWebChannel::~TestWebChannel() { } +int TestWebChannel::readInt() const +{ + return m_lastInt; +} void TestWebChannel::setInt(int i) { m_lastInt = i; + emit lastIntChanged(); +} + +double TestWebChannel::readDouble() const +{ + return m_lastDouble; } void TestWebChannel::setDouble(double d) { m_lastDouble = d; + emit lastDoubleChanged(); +} + +QVariant TestWebChannel::readVariant() const +{ + return m_lastVariant; } void TestWebChannel::setVariant(const QVariant &v) { m_lastVariant = v; + emit lastVariantChanged(); +} + +QJsonValue TestWebChannel::readJsonValue() const +{ + return m_lastJsonValue; } void TestWebChannel::setJsonValue(const QJsonValue& v) { m_lastJsonValue = v; + emit lastJsonValueChanged(); +} + +QJsonObject TestWebChannel::readJsonObject() const +{ + return m_lastJsonObject; } void TestWebChannel::setJsonObject(const QJsonObject& v) { - m_lastJsonValue = v; + m_lastJsonObject = v; + emit lastJsonObjectChanged(); +} + +QJsonArray TestWebChannel::readJsonArray() const +{ + return m_lastJsonArray; } void TestWebChannel::setJsonArray(const QJsonArray& v) { - m_lastJsonValue = v; + m_lastJsonArray = v; + emit lastJsonArrayChanged(); } void TestWebChannel::testRegisterObjects() @@ -455,7 +490,7 @@ void TestWebChannel::testInvokeMethodConversion() object["bar"] = QJsonValue(4.2); args[0] = object; channel.d_func()->publisher->invokeMethod(this, method, args); - QCOMPARE(m_lastJsonValue.toObject(), object); + QCOMPARE(m_lastJsonObject, object); } { int method = metaObject()->indexOfMethod("setJsonArray(QJsonArray)"); @@ -465,7 +500,58 @@ void TestWebChannel::testInvokeMethodConversion() array << QJsonValue(4.2); args[0] = array; channel.d_func()->publisher->invokeMethod(this, method, args); - QCOMPARE(m_lastJsonValue.toArray(), array); + QCOMPARE(m_lastJsonArray, array); + } +} + +void TestWebChannel::testSetPropertyConversion() +{ + QWebChannel channel; + channel.connectTo(m_dummyTransport); + + { + int property = metaObject()->indexOfProperty("lastInt"); + QVERIFY(property != -1); + channel.d_func()->publisher->setProperty(this, property, QJsonValue(42)); + QCOMPARE(m_lastInt, 42); + } + { + int property = metaObject()->indexOfProperty("lastDouble"); + QVERIFY(property != -1); + channel.d_func()->publisher->setProperty(this, property, QJsonValue(-4.2)); + QCOMPARE(m_lastDouble, -4.2); + } + { + int property = metaObject()->indexOfProperty("lastVariant"); + QVERIFY(property != -1); + QVariant variant("foo bar asdf"); + channel.d_func()->publisher->setProperty(this, property, QJsonValue::fromVariant(variant)); + QCOMPARE(m_lastVariant, variant); + } + { + int property = metaObject()->indexOfProperty("lastJsonValue"); + QVERIFY(property != -1); + QJsonValue value("asdf asdf"); + channel.d_func()->publisher->setProperty(this, property, value); + QCOMPARE(m_lastJsonValue, value); + } + { + int property = metaObject()->indexOfProperty("lastJsonArray"); + QVERIFY(property != -1); + QJsonArray array; + array << QJsonValue(-123); + array << QJsonValue(-42); + channel.d_func()->publisher->setProperty(this, property, array); + QCOMPARE(m_lastJsonArray, array); + } + { + int property = metaObject()->indexOfProperty("lastJsonObject"); + QVERIFY(property != -1); + QJsonObject object; + object["foo"] = QJsonValue(-123); + object["bar"] = QJsonValue(-4.2); + channel.d_func()->publisher->setProperty(this, property, object); + QCOMPARE(m_lastJsonObject, object); } } diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h index e551458..13294c2 100644 --- a/tests/auto/webchannel/tst_webchannel.h +++ b/tests/auto/webchannel/tst_webchannel.h @@ -37,6 +37,8 @@ #include <QObject> #include <QVariant> #include <QJsonValue> +#include <QJsonObject> +#include <QJsonArray> #include <QtWebChannel/QWebChannelAbstractTransport> @@ -223,22 +225,43 @@ class TestWebChannel : public QObject { Q_OBJECT + Q_PROPERTY(int lastInt READ readInt WRITE setInt NOTIFY lastIntChanged); + Q_PROPERTY(double lastDouble READ readDouble WRITE setDouble NOTIFY lastDoubleChanged); + Q_PROPERTY(QVariant lastVariant READ readVariant WRITE setVariant NOTIFY lastVariantChanged); + Q_PROPERTY(QJsonValue lastJsonValue READ readJsonValue WRITE setJsonValue NOTIFY lastJsonValueChanged); + Q_PROPERTY(QJsonObject lastJsonObject READ readJsonObject WRITE setJsonObject NOTIFY lastJsonObjectChanged); + Q_PROPERTY(QJsonArray lastJsonArray READ readJsonArray WRITE setJsonArray NOTIFY lastJsonArrayChanged); public: explicit TestWebChannel(QObject *parent = 0); virtual ~TestWebChannel(); + int readInt() const; Q_INVOKABLE void setInt(int i); + double readDouble() const; Q_INVOKABLE void setDouble(double d); + QVariant readVariant() const; Q_INVOKABLE void setVariant(const QVariant &v); + QJsonValue readJsonValue() const; Q_INVOKABLE void setJsonValue(const QJsonValue &v); + QJsonObject readJsonObject() const; Q_INVOKABLE void setJsonObject(const QJsonObject &v); + QJsonArray readJsonArray() const; Q_INVOKABLE void setJsonArray(const QJsonArray &v); +signals: + void lastIntChanged(); + void lastDoubleChanged(); + void lastVariantChanged(); + void lastJsonValueChanged(); + void lastJsonObjectChanged(); + void lastJsonArrayChanged(); + private slots: void testRegisterObjects(); void testDeregisterObjects(); void testInfoForObject(); void testInvokeMethodConversion(); + void testSetPropertyConversion(); void testDisconnect(); void testWrapRegisteredObject(); void testInfiniteRecursion(); @@ -257,6 +280,8 @@ private: double m_lastDouble; QVariant m_lastVariant; QJsonValue m_lastJsonValue; + QJsonObject m_lastJsonObject; + QJsonArray m_lastJsonArray; }; QT_END_NAMESPACE |