summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2016-05-25 18:20:30 +0200
committerMilian Wolff <milian.wolff@kdab.com>2016-05-26 09:56:54 +0000
commitbec50124b893c4632829d9806f49f64c4debf936 (patch)
tree90986763724e26b5f0b5df993dda06b3f2086081
parent97c876a1353f29ed0129360f013f2529bed69d98 (diff)
downloadqtwebchannel-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.cpp20
-rw-r--r--src/webchannel/qmetaobjectpublisher_p.h5
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp94
-rw-r--r--tests/auto/webchannel/tst_webchannel.h25
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