diff options
author | Thomas McGuire <thomas.mcguire.qnx@kdab.com> | 2012-08-06 07:36:05 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-31 13:08:29 (GMT) |
commit | 3c4c970962d75a902ff14a1c8b3adb36895c4ffa (patch) | |
tree | 6f6a4060c3e6b9179ac731398f7832427aa28fb1 /src/declarative | |
parent | 43669c58027b9e6ba76b6b2ca6059ab3d9e8c0ea (diff) | |
download | Qt-3c4c970962d75a902ff14a1c8b3adb36895c4ffa.zip Qt-3c4c970962d75a902ff14a1c8b3adb36895c4ffa.tar.gz Qt-3c4c970962d75a902ff14a1c8b3adb36895c4ffa.tar.bz2 |
Make connectNotify() work with QML
Call connectNotify() and disconnectNotify() in QML signal
handlers and in QML bindings.
This is a backport of Qt5's QtDeclarative commit
26ea8e01e9ee2a8c8c09266147b94c9ac92d09f9.
Task-number: QTBUG-11284
Change-Id: If5c3701426208875f3b775040c4e7bcbaac2b0a9
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qdeclarativebinding.cpp | 17 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativebinding_p.h | 33 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeboundsignal.cpp | 41 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeboundsignal_p.h | 28 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativecompiledbindings.cpp | 72 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativedata_p.h | 6 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 35 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativenotifier.cpp | 5 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativenotifier_p.h | 28 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeproperty.cpp | 6 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeproperty_p.h | 2 |
11 files changed, 239 insertions, 34 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 5acbec9..779fdd1 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -75,8 +75,11 @@ Bindings are free to implement their own memory management, so the delete operat necessarily safe. The default implementation clears the binding, removes it from the object and calls delete. */ -void QDeclarativeAbstractBinding::destroy() +void QDeclarativeAbstractBinding::destroy(DestroyMode mode) { + if (mode == DisconnectBinding) + disconnect(QDeclarativeAbstractBinding::DisconnectOne); + removeFromObject(); clear(); @@ -488,6 +491,12 @@ QString QDeclarativeBinding::expression() const return QDeclarativeExpression::expression(); } +void QDeclarativeBinding::disconnect(DisconnectMode disconnectMode) +{ + Q_UNUSED(disconnectMode); + setNotifyOnValueChanged(false); +} + QDeclarativeValueTypeProxyBinding::QDeclarativeValueTypeProxyBinding(QObject *o, int index) : m_object(o), m_index(index), m_bindings(0) { @@ -539,6 +548,12 @@ void QDeclarativeValueTypeProxyBinding::update(QDeclarativePropertyPrivate::Writ { } +void QDeclarativeValueTypeProxyBinding::disconnect(DisconnectMode disconnectMode) +{ + Q_UNUSED(disconnectMode); + // Nothing to do +} + QDeclarativeAbstractBinding *QDeclarativeValueTypeProxyBinding::binding(int propertyIndex) { QDeclarativeAbstractBinding *binding = m_bindings; diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 01d5070..a6bde99 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -71,10 +71,39 @@ public: QDeclarativeAbstractBinding(); - virtual void destroy(); + enum DestroyMode { + // The binding should disconnect itself upon destroy + DisconnectBinding, + + // The binding doesn't need to disconnect itself, but it can if it wants to. + // + // This is used in QDeclarativeData::destroyed() - at the point at which the bindings are + // destroyed, the notifiers are already disconnected, so no need to disconnect each + // binding again. + // + // Bindings can use this flag to speed up destruction, especially for compiled bindings + // disconnecting a single binding might be slow. + KeepBindingConnected + }; + + virtual void destroy(DestroyMode mode = DisconnectBinding); virtual QString expression() const; + enum DisconnectMode { + + // Just this single binding is getting disconnected, other bindings remain connected and + // should not be changed. + DisconnectOne, + + // All bindings of the same object are getting disconnected. As an optimization, it is + // therefore valid to disconnect all bindings in one go. + DisconnectAll + }; + + // disconnectMode can be ignored, it is just a hint for potential optimization + virtual void disconnect(DisconnectMode disconnectMode) = 0; + enum Type { PropertyBinding, ValueTypeProxy }; virtual Type bindingType() const { return PropertyBinding; } @@ -123,6 +152,7 @@ public: virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags); virtual void update(QDeclarativePropertyPrivate::WriteFlags); + virtual void disconnect(DisconnectMode disconnectMode); QDeclarativeAbstractBinding *binding(int propertyIndex); @@ -168,6 +198,7 @@ public: virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); virtual QString expression() const; + virtual void disconnect(DisconnectMode disconnectMode); typedef int Identifier; static Identifier Invalid; diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 089449e..c6ab1f1 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -97,21 +97,23 @@ QDeclarativeAbstractBoundSignal::~QDeclarativeAbstractBoundSignal() QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0), + m_scope(scope, this) { - // This is thread safe. Although it may be updated by two threads, they - // will both set it to the same value - so the worst thing that can happen - // is that they both do the work to figure it out. Boo hoo. - if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); - - QDeclarative_setParent_noEvent(this, parent); - QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + init(parent); } QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val, QObject *scope, const QMetaMethod &signal, QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0), + m_scope(scope, this) +{ + init(parent); + m_expression = new QDeclarativeExpression(ctxt, scope, val); +} + +void QDeclarativeBoundSignal::init(QObject *parent) { // This is thread safe. Although it may be updated by two threads, they // will both set it to the same value - so the worst thing that can happen @@ -119,17 +121,25 @@ QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, cons if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); QDeclarative_setParent_noEvent(this, parent); - QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + QDeclarativePropertyPrivate::connect(m_scope, m_signal.methodIndex(), this, evaluateIdx); - m_expression = new QDeclarativeExpression(ctxt, scope, val); + QDeclarativeData * const data = QDeclarativeData::get(m_scope, true); + data->addBoundSignal(this); } QDeclarativeBoundSignal::~QDeclarativeBoundSignal() { + unregisterScopeObject(); delete m_expression; m_expression = 0; } +void QDeclarativeBoundSignal::disconnect() +{ + QObjectPrivate * const priv = QObjectPrivate::get(m_scope); + priv->disconnectNotify(m_signal.signature()); +} + int QDeclarativeBoundSignal::index() const { return m_signal.methodIndex(); @@ -196,6 +206,15 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) } } +void QDeclarativeBoundSignal::unregisterScopeObject() +{ + if (m_scope) { + QDeclarativeData * const data = QDeclarativeData::get(m_scope, false); + if (data) + data->removeBoundSignal(this); + } +} + QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method, QObject *parent) : QObject(parent), types(0), values(0) diff --git a/src/declarative/qml/qdeclarativeboundsignal_p.h b/src/declarative/qml/qdeclarativeboundsignal_p.h index a0dfe18..4ba8592 100644 --- a/src/declarative/qml/qdeclarativeboundsignal_p.h +++ b/src/declarative/qml/qdeclarativeboundsignal_p.h @@ -54,6 +54,7 @@ // #include "qdeclarativeexpression.h" +#include "qdeclarativeguard_p.h" #include <QtCore/qmetaobject.h> @@ -67,6 +68,10 @@ class QDeclarativeAbstractBoundSignal : public QObject public: QDeclarativeAbstractBoundSignal(QObject *parent = 0); virtual ~QDeclarativeAbstractBoundSignal() = 0; + virtual void disconnect() = 0; + +protected slots: + virtual void unregisterScopeObject() = 0; }; class QDeclarativeBoundSignalParameters; @@ -78,6 +83,8 @@ public: const QMetaMethod &signal, QObject *parent); virtual ~QDeclarativeBoundSignal(); + void disconnect(); + int index() const; QDeclarativeExpression *expression() const; @@ -88,14 +95,35 @@ public: static QDeclarativeBoundSignal *cast(QObject *); protected: + void unregisterScopeObject(); virtual int qt_metacall(QMetaObject::Call c, int id, void **a); private: + class ScopeGuard : public QDeclarativeGuard<QObject> + { + public: + ScopeGuard(QObject *object, QDeclarativeBoundSignal *signal) + : QDeclarativeGuard<QObject>(object), m_signal(signal) + { + } + + void objectDestroyed(QObject *obj) { + Q_UNUSED(obj); + m_signal->unregisterScopeObject(); + } + + private: + QDeclarativeBoundSignal *m_signal; + }; + + void init(QObject *parent); + QDeclarativeExpression *m_expression; QMetaMethod m_signal; bool m_paramsValid : 1; bool m_isEvaluating : 1; QDeclarativeBoundSignalParameters *m_params; + ScopeGuard m_scope; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 3ee365a..5aefa4a 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -216,7 +216,8 @@ public: // Inherited from QDeclarativeAbstractBinding virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); - virtual void destroy(); + virtual void destroy(DestroyMode mode); + virtual void disconnect(DisconnectMode disconnectMode); int index:30; bool enabled:1; @@ -238,6 +239,7 @@ public: QDeclarativeRefCount *dataRef; Binding *m_bindings; quint32 *m_signalTable; + bool m_bindingsDisconnected; static int methodCount; @@ -246,9 +248,10 @@ public: QDeclarativeDelayedError *error, QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags); - inline void unsubscribe(int subIndex); inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex); inline void subscribe(QObject *o, int notifyIndex, int subIndex); + inline void disconnectAll(); + inline void disconnectOne(Binding *bindingToDisconnect); QDeclarativePropertyCache::Data *findproperty(QObject *obj, const QScriptDeclarativeClass::Identifier &name, @@ -268,7 +271,8 @@ public: }; QDeclarativeCompiledBindingsPrivate::QDeclarativeCompiledBindingsPrivate() -: subscriptions(0), identifiers(0), programData(0), dataRef(0), m_bindings(0), m_signalTable(0) + : subscriptions(0), identifiers(0), programData(0), dataRef(0), m_bindings(0), m_signalTable(0), + m_bindingsDisconnected(false) { } @@ -343,14 +347,25 @@ void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPr QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); } -void QDeclarativeCompiledBindingsPrivate::Binding::destroy() +void QDeclarativeCompiledBindingsPrivate::Binding::destroy(DestroyMode mode) { + if (mode == DisconnectBinding) + disconnect(QDeclarativeAbstractBinding::DisconnectOne); + enabled = false; removeFromObject(); clear(); parent->q_func()->release(); } +void QDeclarativeCompiledBindingsPrivate::Binding::disconnect(DisconnectMode disconnectMode) +{ + if (disconnectMode == QDeclarativeAbstractBinding::DisconnectAll) + parent->disconnectAll(); + else + parent->disconnectOne(this); +} + int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **) { Q_D(QDeclarativeCompiledBindings); @@ -696,26 +711,20 @@ struct QDeclarativeBindingCompilerPrivate QByteArray buildExceptionData() const; }; -void QDeclarativeCompiledBindingsPrivate::unsubscribe(int subIndex) -{ - QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - sub->disconnect(); -} - void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex) { Q_Q(QDeclarativeCompiledBindings); - unsubscribe(subIndex); + QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); + sub->disconnect(); if (p->idValues[idIndex]) { - QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); sub->target = q; sub->targetMethod = methodCount + subIndex; sub->connect(&p->idValues[idIndex].bindings); } } - + void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex) { Q_Q(QDeclarativeCompiledBindings); @@ -729,6 +738,43 @@ void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, sub->disconnect(); } +void QDeclarativeCompiledBindingsPrivate::disconnectAll() +{ + // This gets called multiple times in QDeclarativeData::disconnectNotifiers(), avoid unneeded + // work for all but the first call. + if (m_bindingsDisconnected) + return; + + // We disconnect all subscriptions, so we can call disconnect() unconditionally if there is at + // least one connection + Program *program = (Program *)programData; + for (int subIndex = 0; subIndex < program->subscriptions; ++subIndex) { + Subscription * const sub = (subscriptions + subIndex); + if (sub->isConnected()) + sub->disconnect(); + } + m_bindingsDisconnected = true; +} + +void QDeclarativeCompiledBindingsPrivate::disconnectOne( + QDeclarativeCompiledBindingsPrivate::Binding *bindingToDisconnect) +{ + // We iterate over the signal table to find all subscriptions for this binding. This is slowish, + // but disconnectOne() is only called when overwriting a binding, which is quite rare. + Program *program = (Program *)programData; + for (int subIndex = 0; subIndex < program->subscriptions; ++subIndex) { + Subscription * const sub = (subscriptions + subIndex); + quint32 *reeval = m_signalTable + m_signalTable[subIndex]; + quint32 bindingCount = *reeval; + ++reeval; + for (quint32 bindingIndex = 0; bindingIndex < bindingCount; ++bindingIndex) { + Binding * const binding = m_bindings + reeval[bindingIndex]; + if (binding == bindingToDisconnect) + sub->deref(); + } + } +} + // Conversion functions - these MUST match the QtScript expression path inline static qreal toReal(Register *reg, int type, bool *ok = 0) { diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index 7d71406..0057840 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeGuardImpl; class QDeclarativeCompiledData; class QDeclarativeAbstractBinding; +class QDeclarativeAbstractBoundSignal; class QDeclarativeContext; class QDeclarativePropertyCache; class QDeclarativeContextData; @@ -154,9 +155,12 @@ public: bool hasExtendedData() const { return extendedData != 0; } QDeclarativeNotifier *objectNameNotifier() const; QHash<int, QObject *> *attachedProperties() const; + void addBoundSignal(QDeclarativeAbstractBoundSignal *signal); + void removeBoundSignal(QDeclarativeAbstractBoundSignal *signal); + void disconnectNotifiers(); private: - // For objectNameNotifier and attachedProperties + // For objectNameNotifier, attachedProperties and bound signal list mutable QDeclarativeDataExtended *extendedData; }; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index a787fb6..92a7391 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -42,6 +42,7 @@ #include "private/qdeclarativeengine_p.h" #include "qdeclarativeengine.h" +#include "private/qdeclarativeboundsignal_p.h" #include "private/qdeclarativecontext_p.h" #include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativeglobalscriptclass_p.h" @@ -547,6 +548,11 @@ void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o) d->context->destroy(); d->context = 0; } + + // Disconnect the notifiers now - during object destruction this would be too late, since + // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to + // get the metaobject anymore. + d->disconnectNotifiers(); } } @@ -1108,6 +1114,7 @@ public: QHash<int, QObject *> attachedProperties; QDeclarativeNotifier objectNameNotifier; + QList<QDeclarativeAbstractBoundSignal *> boundSignals; }; QDeclarativeDataExtended::QDeclarativeDataExtended() @@ -1130,6 +1137,32 @@ QHash<int, QObject *> *QDeclarativeData::attachedProperties() const return &extendedData->attachedProperties; } +void QDeclarativeData::addBoundSignal(QDeclarativeAbstractBoundSignal *signal) +{ + if (!extendedData) extendedData = new QDeclarativeDataExtended; + extendedData->boundSignals.append(signal); +} + +void QDeclarativeData::removeBoundSignal(QDeclarativeAbstractBoundSignal *signal) +{ + if (extendedData) + extendedData->boundSignals.removeAll(signal); +} + +void QDeclarativeData::disconnectNotifiers() +{ + QDeclarativeAbstractBinding *binding = bindings; + while (binding) { + binding->disconnect(QDeclarativeAbstractBinding::DisconnectAll); + binding = binding->m_nextBinding; + } + + if (extendedData) { + Q_FOREACH (QDeclarativeAbstractBoundSignal *signal, extendedData->boundSignals) + signal->disconnect(); + } +} + void QDeclarativeData::destroyed(QObject *object) { if (deferredComponent) @@ -1145,7 +1178,7 @@ void QDeclarativeData::destroyed(QObject *object) QDeclarativeAbstractBinding *next = binding->m_nextBinding; binding->m_prevBinding = 0; binding->m_nextBinding = 0; - binding->destroy(); + binding->destroy(QDeclarativeAbstractBinding::KeepBindingConnected); binding = next; } diff --git a/src/declarative/qml/qdeclarativenotifier.cpp b/src/declarative/qml/qdeclarativenotifier.cpp index b625038..a3fae93 100644 --- a/src/declarative/qml/qdeclarativenotifier.cpp +++ b/src/declarative/qml/qdeclarativenotifier.cpp @@ -71,8 +71,10 @@ void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal) { Signal *s = toSignal(); - if (s->source == source && s->sourceSignal == sourceSignal) + if (s->source == source && s->sourceSignal == sourceSignal) { + refCount++; return; + } disconnect(); @@ -80,6 +82,7 @@ void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal) s->source = source; s->sourceSignal = sourceSignal; + refCount++; } void QDeclarativeNotifierEndpoint::copyAndClear(QDeclarativeNotifierEndpoint &other) diff --git a/src/declarative/qml/qdeclarativenotifier_p.h b/src/declarative/qml/qdeclarativenotifier_p.h index 524a966..ee80c9a 100644 --- a/src/declarative/qml/qdeclarativenotifier_p.h +++ b/src/declarative/qml/qdeclarativenotifier_p.h @@ -43,6 +43,7 @@ #define QDECLARATIVENOTIFIER_P_H #include "private/qdeclarativeguard_p.h" +#include <QtCore/qmetaobject.h> QT_BEGIN_NAMESPACE @@ -77,8 +78,13 @@ public: void connect(QObject *source, int sourceSignal); inline void connect(QDeclarativeNotifier *); + + // Disconnects unconditionally, regardless of the refcount inline void disconnect(); + // Decreases the refcount and disconnects when refcount reaches 0 + inline void deref(); + void copyAndClear(QDeclarativeNotifierEndpoint &other); private: @@ -110,6 +116,8 @@ private: Notifier notifier; }; + quint16 refCount; + inline Notifier *toNotifier(); inline Notifier *asNotifier(); inline Signal *toSignal(); @@ -143,12 +151,12 @@ void QDeclarativeNotifier::notify() } QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint() -: target(0), targetMethod(0), type(InvalidType) + : target(0), targetMethod(0), type(InvalidType), refCount(0) { } QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint(QObject *t, int m) -: target(t), targetMethod(m), type(InvalidType) +: target(t), targetMethod(m), type(InvalidType), refCount(0) { } @@ -186,8 +194,10 @@ void QDeclarativeNotifierEndpoint::connect(QDeclarativeNotifier *notifier) { Notifier *n = toNotifier(); - if (n->notifier == notifier) + if (n->notifier == notifier) { + refCount++; return; + } disconnect(); @@ -196,6 +206,7 @@ void QDeclarativeNotifierEndpoint::connect(QDeclarativeNotifier *notifier) notifier->endpoints = this; n->prev = ¬ifier->endpoints; n->notifier = notifier; + refCount++; } void QDeclarativeNotifierEndpoint::disconnect() @@ -204,6 +215,9 @@ void QDeclarativeNotifierEndpoint::disconnect() Signal *s = asSignal(); if (s->source) { QMetaObject::disconnectOne(s->source, s->sourceSignal, target, targetMethod); + QObjectPrivate * const priv = QObjectPrivate::get(s->source); + const QMetaMethod signal = s->source->metaObject()->method(s->sourceSignal); + priv->disconnectNotify(signal.signature()); s->source = 0; } } else if (type == NotifierType) { @@ -217,6 +231,14 @@ void QDeclarativeNotifierEndpoint::disconnect() n->disconnected = 0; n->notifier = 0; } + refCount = 0; +} + +void QDeclarativeNotifierEndpoint::deref() +{ + refCount--; + if (refCount <= 0) + disconnect(); } QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::toNotifier() diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 84f492d..2867d27 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -1626,13 +1626,17 @@ it connects any lazy "proxy" signal connections set up by QML. It is possible that this logic should be moved to QMetaObject::connect(). */ -bool QDeclarativePropertyPrivate::connect(const QObject *sender, int signal_index, +bool QDeclarativePropertyPrivate::connect(QObject *sender, int signal_index, const QObject *receiver, int method_index, int type, int *types) { flush_vme_signal(sender, signal_index); flush_vme_signal(receiver, method_index); + const QMetaMethod signal = sender->metaObject()->method(signal_index); + QObjectPrivate * const senderPriv = QObjectPrivate::get(sender); + senderPriv->connectNotify(signal.signature()); + return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types); } diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index 21e3341..4847445 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -134,7 +134,7 @@ public: static int valueTypeCoreIndex(const QDeclarativeProperty &that); static int bindingIndex(const QDeclarativeProperty &that); static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &); - static bool connect(const QObject *sender, int signal_index, + static bool connect(QObject *sender, int signal_index, const QObject *receiver, int method_index, int type = 0, int *types = 0); static const QMetaObject *metaObjectForProperty(const QMetaObject *, int); |