diff options
author | Arno Rehn <a.rehn@menlosystems.com> | 2021-04-16 22:45:21 +0200 |
---|---|---|
committer | Arno Rehn <a.rehn@menlosystems.com> | 2021-04-22 13:31:31 +0200 |
commit | 87ca0ba70cd9cb4cd33e4c59986ede6b40cfe4be (patch) | |
tree | a2a279c7c056e4cde3402abafaa056d918896392 /src/webchannel/qmetaobjectpublisher_p.h | |
parent | 85fb5a65ee4cabd0eb319a840b82145d1f4567c1 (diff) |
Use QProperty observation to push property updates to clients
If the property is BINDABLE but lacks a NOTIFY signal, the
client will have no way to register a callback for change
notifications. Document this behavior as such.
A future patch could synthesize signals for purely BINDABLE
properties on the client side, but this needs some more thought.
Change-Id: I5e723e294dc01890956fee179fb3ba30aecf8cc1
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/webchannel/qmetaobjectpublisher_p.h')
-rw-r--r-- | src/webchannel/qmetaobjectpublisher_p.h | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index e87e4f0..f54f569 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -86,8 +86,24 @@ enum MessageType { TYPES_LAST_VALUE = 10 }; +class QMetaObjectPublisher; class QWebChannel; class QWebChannelAbstractTransport; + +struct QWebChannelPropertyChangeNotifier : QPropertyObserver +{ + QWebChannelPropertyChangeNotifier(QMetaObjectPublisher *publisher, const QObject *object, int propertyIndex) + : QPropertyObserver(&QWebChannelPropertyChangeNotifier::notify), + publisher(publisher), object(object), propertyIndex(propertyIndex) + { + } + + QMetaObjectPublisher *publisher = nullptr; + const QObject *object = nullptr; + int propertyIndex = 0; + static void notify(QPropertyObserver *, QUntypedPropertyData *); +}; + class Q_WEBCHANNEL_EXPORT QMetaObjectPublisher : public QObject { Q_OBJECT @@ -136,7 +152,7 @@ public: * When receiving a notify signal, it will store the information in pendingPropertyUpdates which * gets send via a Qt.propertyUpdate message to the server when the grouping timer timeouts. */ - void initializePropertyUpdates(const QObject *const object, const QJsonObject &objectInfo); + void initializePropertyUpdates(QObject *const object, const QJsonObject &objectInfo); /** * Send the clients the new property values since the last time this function was invoked. @@ -186,6 +202,17 @@ public: void signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments); /** + * Callback for bindable property value changes which forwards the change to the webchannel clients. + */ + void propertyValueChanged(const QObject *object, const int propertyIndex); + + /** + * Called after a property has been updated. Starts the update timer if + * the client is idle and updates are not blocked. + */ + void startPropertyUpdateTimer(); + + /** * Callback for registered or wrapped objects which erases all data related to @p object. * * @sa signalEmitted @@ -319,10 +346,32 @@ private: typedef QHash<int, QSet<int> > SignalToPropertyNameMap; QHash<const QObject *, SignalToPropertyNameMap> signalToPropertyMap; + // Keeps property observers alive for as long as we track an object + std::unordered_multimap<const QObject*, QWebChannelPropertyChangeNotifier> propertyObservers; + // Objects that changed their properties and are waiting for idle client. - // map of object name to map of signal index to arguments typedef QHash<int, QVariantList> SignalToArgumentsMap; - typedef QHash<const QObject *, SignalToArgumentsMap> PendingPropertyUpdates; + + // A set of plain property index (for bindable properties) and a map of + // signal index to arguments (for property updates from a notify signal). + // NOTIFY signals and their arguments are first collected and then mapped to + // the corresponding property in sendPendingPropertyUpdates() + struct PropertyUpdate + { + public: + SignalToArgumentsMap signalMap; + QSet<int> plainProperties; + + /** + * Given a SignalToPropertyNameMap, returns the set of all property + * indices of properties that were changed in this PropertyUpdate. + */ + QSet<int> propertyIndices(const SignalToPropertyNameMap &map) const; + }; + + // map of object to either a property index for plain bindable properties + // or a to map of signal index to arguments + typedef QHash<const QObject *, PropertyUpdate> PendingPropertyUpdates; PendingPropertyUpdates pendingPropertyUpdates; // Aggregate property updates since we get multiple Qt.idle message when we have multiple @@ -331,6 +380,14 @@ private: QBasicTimer timer; }; +inline QSet<int> QMetaObjectPublisher::PropertyUpdate::propertyIndices(const SignalToPropertyNameMap &map) const { + auto indexes = plainProperties; + for (auto it = signalMap.cbegin(); it != signalMap.cend(); ++it) { + indexes += map.value(it.key()); + } + return indexes; +} + QT_END_NAMESPACE #endif // QMETAOBJECTPUBLISHER_P_H |