diff options
Diffstat (limited to 'src/webchannel')
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 24 | ||||
-rw-r--r-- | src/webchannel/qmetaobjectpublisher_p.h | 7 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.cpp | 5 |
3 files changed, 35 insertions, 1 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index b3fc53d..cd6ad70 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -449,6 +449,29 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object) pendingPropertyUpdates.remove(object); } +void QMetaObjectPublisher::transportRemoved(QWebChannelAbstractTransport *transport) +{ + QHash<QWebChannelAbstractTransport*, QString>::iterator it = transportedWrappedObjects.find(transport); + // It is not allowed to modify a container while iterating over it. So save + // objects which should be removed and call objectDestroyed() on them later. + QVector<QObject*> objectsForDeletion; + while (it != transportedWrappedObjects.end() && it.key() == transport) { + if (wrappedObjects.contains(it.value())) { + QVector<QWebChannelAbstractTransport*> &transports = wrappedObjects[it.value()].transports; + transports.removeOne(transport); + if (transports.isEmpty()) + objectsForDeletion.append(wrappedObjects[it.value()].object); + } + + it++; + } + + transportedWrappedObjects.remove(transport); + + foreach (QObject *obj, objectsForDeletion) + objectDestroyed(obj); +} + QObject *QMetaObjectPublisher::unwrapObject(const QString &objectId) const { if (!objectId.isEmpty()) { @@ -520,6 +543,7 @@ QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelA oi.transports = webChannel->d_func()->transports; } wrappedObjects.insert(id, oi); + transportedWrappedObjects.insert(transport, id); initializePropertyUpdates(object, classInfo); } else if (wrappedObjects.contains(id)) { diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index 048a33c..95e5077 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -171,6 +171,11 @@ public: QVariant toVariant(const QJsonValue &value, int targetType) const; /** + * Remove wrapped objects which last transport relation is with the passed transport object. + */ + void transportRemoved(QWebChannelAbstractTransport *transport); + + /** * Given a QVariant containing a QObject*, wrap the object and register for property updates * return the objects class information. * @@ -251,6 +256,8 @@ private: // Map of objects wrapped from invocation returns QHash<QString, ObjectInfo> wrappedObjects; + // Map of transports to wrapped object ids + QMultiHash<QWebChannelAbstractTransport*, QString> transportedWrappedObjects; // Map of objects to maps of signal indices to a set of all their property indices. // The last value is a set as a signal can be the notify signal of multiple properties. diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index 1e8ed8f..b591ee1 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -75,9 +75,11 @@ QT_BEGIN_NAMESPACE */ void QWebChannelPrivate::_q_transportDestroyed(QObject *object) { - const int idx = transports.indexOf(static_cast<QWebChannelAbstractTransport*>(object)); + QWebChannelAbstractTransport *transport = static_cast<QWebChannelAbstractTransport*>(object); + const int idx = transports.indexOf(transport); if (idx != -1) { transports.remove(idx); + publisher->transportRemoved(transport); } } @@ -246,6 +248,7 @@ void QWebChannel::disconnectFrom(QWebChannelAbstractTransport *transport) disconnect(transport, 0, this, 0); disconnect(transport, 0, d->publisher, 0); d->transports.remove(idx); + d->publisher->transportRemoved(transport); } } |