summaryrefslogtreecommitdiff
path: root/src/webchannel/qmetaobjectpublisher.cpp
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2014-10-16 13:37:22 +0200
committerMilian Wolff <milian.wolff@kdab.com>2014-12-02 14:16:55 +0100
commit81dac6e848da8e8a071a2069862590889a287067 (patch)
treeb8bbca884fd5e04755f6feaa7310e2d02c5fac34 /src/webchannel/qmetaobjectpublisher.cpp
parent86d77a900852691267f556fbde98406a12ee4310 (diff)
downloadqtwebchannel-81dac6e848da8e8a071a2069862590889a287067.tar.gz
Make objects inside properties accessible.
Similar to the support for factory-methods, we must wrap objects in properties to make them accessible to clients. This patch adds the required code for that. Besides support for simple properties that reference an object, this patch also adds support for list properties that contain objects. The client-side unwrap of properties is delayed until all objects are initialized, as a property might reference another registered object. Change-Id: I9fb90a8eab4c66d2f4231fdb482e0d97d128df3e Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
Diffstat (limited to 'src/webchannel/qmetaobjectpublisher.cpp')
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp73
1 files changed, 45 insertions, 28 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index 27eb134..90c39ff 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -95,15 +95,18 @@ QMetaObjectPublisher::~QMetaObjectPublisher()
void QMetaObjectPublisher::registerObject(const QString &id, QObject *object)
{
- if (propertyUpdatesInitialized) {
- qWarning("Registered new object after initialization. This does not work!");
- return;
- }
registeredObjects[id] = object;
registeredObjectIds[object] = id;
+ if (propertyUpdatesInitialized) {
+ if (!webChannel->d_func()->transports.isEmpty()) {
+ qWarning("Registered new object after initialization, existing clients won't be notified!");
+ // TODO: send a message to clients that an object was added
+ }
+ initializePropertyUpdates(object, classInfoForObject(object));
+ }
}
-QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object) const
+QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object)
{
QJsonObject data;
if (!object) {
@@ -151,7 +154,7 @@ QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object) cons
prop.name(), object->metaObject()->className());
}
propertyInfo.append(signalInfo);
- propertyInfo.append(QJsonValue::fromVariant(prop.read(object)));
+ propertyInfo.append(wrapResult(prop.read(object)));
qtProperties.append(propertyInfo);
}
for (int i = 0; i < metaObject->methodCount(); ++i) {
@@ -289,7 +292,7 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates()
foreach (const int propertyIndex, objectsSignalToPropertyMap.value(sigIt.key())) {
const QMetaProperty &property = metaObject->property(propertyIndex);
Q_ASSERT(property.isValid());
- properties[QString::number(propertyIndex)] = QJsonValue::fromVariant(property.read(object));
+ properties[QString::number(propertyIndex)] = wrapResult(property.read(object));
}
sigs[QString::number(sigIt.key())] = QJsonArray::fromVariantList(sigIt.value());
}
@@ -374,9 +377,7 @@ void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signal
message[KEY_OBJECT] = objectName;
message[KEY_SIGNAL] = signalIndex;
if (!arguments.isEmpty()) {
- // TODO: wrap (new) objects on the fly
- QJsonArray args = QJsonArray::fromVariantList(arguments);
- message[KEY_ARGS] = args;
+ message[KEY_ARGS] = wrapList(arguments);
}
message[KEY_TYPE] = TypeSignal;
broadcastMessage(message);
@@ -408,33 +409,49 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object)
QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result)
{
if (QObject *object = result.value<QObject *>()) {
- QJsonObject &objectInfo = wrappedObjects[object];
- if (!objectInfo.isEmpty()) {
- // already registered, use cached information
- Q_ASSERT(registeredObjectIds.contains(object));
- return objectInfo;
- } // else the object is not yet wrapped, do it now
-
- const QString &id = QUuid::createUuid().toString();
- Q_ASSERT(!registeredObjectIds.contains(object));
-
- QJsonObject info = classInfoForObject(object);
+ QJsonObject objectInfo;
objectInfo[KEY_QOBJECT] = true;
- objectInfo[KEY_ID] = id;
- objectInfo[KEY_DATA] = info;
-
- registeredObjectIds[object] = id;
- registeredObjects[id] = object;
- wrappedObjects.insert(object, objectInfo);
+ QString id = registeredObjectIds.value(object);
+ if (id.isEmpty()) {
+ // neither registered, nor wrapped, do so now
+ id = QUuid::createUuid().toString();
+
+ registeredObjectIds[object] = id;
+ registeredObjects[id] = object;
+
+ QJsonObject info = classInfoForObject(object);
+ wrappedObjects[object] = info;
+ objectInfo[KEY_DATA] = info;
+ if (propertyUpdatesInitialized) {
+ // if other objects are initialized already, do the same here
+ initializePropertyUpdates(object, info);
+ }
+ } else if (wrappedObjects.contains(object)) {
+ // if this object was wrapped, send the full class info
+ // this is required for proper multi-client support
+ objectInfo[KEY_DATA] = wrappedObjects.value(object);
+ }
- initializePropertyUpdates(object, info);
+ objectInfo[KEY_ID] = id;
return objectInfo;
+ } else if (result.canConvert<QVariantList>()) {
+ // recurse and potentially wrap contents of the array
+ return wrapList(result.toList());
}
// no need to wrap this
return QJsonValue::fromVariant(result);
}
+QJsonArray QMetaObjectPublisher::wrapList(const QVariantList &list)
+{
+ QJsonArray array;
+ foreach (const QVariant &arg, list) {
+ array.append(wrapResult(arg));
+ }
+ return array;
+}
+
void QMetaObjectPublisher::deleteWrappedObject(QObject *object) const
{
if (!wrappedObjects.contains(object)) {