diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2014-10-16 13:37:22 +0200 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2014-12-02 14:16:55 +0100 |
commit | 81dac6e848da8e8a071a2069862590889a287067 (patch) | |
tree | b8bbca884fd5e04755f6feaa7310e2d02c5fac34 /src/webchannel/qmetaobjectpublisher.cpp | |
parent | 86d77a900852691267f556fbde98406a12ee4310 (diff) | |
download | qtwebchannel-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.cpp | 73 |
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)) { |