diff options
author | Thomas McGuire <thomas.mcguire@kdab.com> | 2012-07-17 17:35:53 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-22 12:25:33 +0200 |
commit | 26ea8e01e9ee2a8c8c09266147b94c9ac92d09f9 (patch) | |
tree | c058873b0082b18a09dde27f7ee124285e696807 /src/qml/qml/v4 | |
parent | 2cc57f1e33cc4d739b1b76c605e6241fa0f134a8 (diff) |
Make connectNotify() work with QML
Call connectNotify() and disconnectNotify() in QQmlNotifierEndPoint,
which works for QML signal handlers and for QML bindings.
Task-number: QTBUG-11284
Change-Id: Ic9a08ee6687e5c7e606f315c8fb30eec1493cd83
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src/qml/qml/v4')
-rw-r--r-- | src/qml/qml/v4/qv4bindings.cpp | 75 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4bindings_p.h | 10 |
2 files changed, 59 insertions, 26 deletions
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index 150a11d011..0088741170 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -382,10 +382,13 @@ void QV4Bindings::Binding::update(QQmlAbstractBinding *_This, QQmlPropertyPrivat This->parent->run(This, flags); } -void QV4Bindings::Binding::destroy(QQmlAbstractBinding *_This) +void QV4Bindings::Binding::destroy(QQmlAbstractBinding *_This, QQmlAbstractBinding::DestroyMode mode) { QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This); + if (mode == QQmlAbstractBinding::DisconnectBinding) + This->disconnect(); + This->setEnabledFlag(false); This->removeFromObject(); This->clear(); @@ -417,8 +420,30 @@ void QV4Bindings::Binding::retargetBinding(QQmlAbstractBinding *_This, QObject * This->target.value().targetProperty = i; } +void QV4Bindings::Binding::disconnect() +{ + // We iterate over the signal table to find all subscriptions associated with this binding. + // This is slow, but disconnect() is not called in the common case, only in special cases + // like when the binding is overwritten. + QV4Program * const program = parent->program; + for (quint16 subIndex = 0; subIndex < program->subscriptions; subIndex++) { + QV4Program::BindingReferenceList * const list = program->signalTable(subIndex); + for (quint32 bindingIndex = 0; bindingIndex < list->count; ++bindingIndex) { + QV4Program::BindingReference * const bindingRef = list->bindings + bindingIndex; + Binding * const binding = parent->bindings + bindingRef->binding; + if (binding == this) { + Subscription * const sub = parent->subscriptions + subIndex; + if (sub->active) { + sub->active = false; + sub->disconnect(); + } + } + } + } +} + QV4Bindings::Subscription::Subscription() -: bindings(0), method(-1) + : bindings(0), method(-1), active(false) { setCallback(QQmlNotifierEndpoint::QV4BindingsSubscription); } @@ -526,22 +551,18 @@ void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags) } } - -void QV4Bindings::unsubscribe(int subIndex) +void QV4Bindings::subscribeId(QQmlContextData *p, int idIndex, int subIndex) { Subscription *sub = (subscriptions + subIndex); sub->disconnect(); -} - -void QV4Bindings::subscribeId(QQmlContextData *p, int idIndex, int subIndex) -{ - unsubscribe(subIndex); if (p->idValues[idIndex]) { - Subscription *sub = (subscriptions + subIndex); sub->bindings = this; sub->method = subIndex; sub->connect(&p->idValues[idIndex].bindings); + sub->active = true; + } else { + sub->active = false; } } @@ -552,10 +573,13 @@ void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex, QQmlEngin return; sub->bindings = this; sub->method = subIndex; - if (o) + if (o) { sub->connect(o, notifyIndex, e); - else + sub->active = true; + } else { sub->disconnect(); + sub->active = false; + } } static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4) @@ -942,14 +966,6 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } else { INVALIDATION_CHECK(invalidated, object, instr->fetchAndSubscribe.property.coreIndex); - int subIdx = instr->fetchAndSubscribe.subscription; - Subscription *sub = 0; - if (subIdx != -1) { - sub = (subscriptions + subIdx); - sub->bindings = this; - sub->method = subIdx; - } - const Register::Type valueType = (Register::Type)instr->fetchAndSubscribe.valueType; reg.init(valueType); if (instr->fetchAndSubscribe.valueType >= FirstCleanupType) @@ -967,9 +983,22 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, if (accessors->notifier) { QQmlNotifier *notifier = 0; accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, ¬ifier); - if (notifier) sub->connect(notifier); - } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) { - sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex, context->engine); + if (notifier) { + int subIdx = instr->fetchAndSubscribe.subscription; + Subscription *sub = 0; + if (subIdx != -1) { + sub = (subscriptions + subIdx); + sub->bindings = this; + sub->method = subIdx; + } + sub->connect(notifier); + } + } else { + const int notifyIndex = instr->fetchAndSubscribe.property.notifyIndex; + if (notifyIndex != -1) { + const int subIdx = instr->fetchAndSubscribe.subscription; + subscribe(object, notifyIndex, subIdx, context->engine); + } } } } diff --git a/src/qml/qml/v4/qv4bindings_p.h b/src/qml/qml/v4/qv4bindings_p.h index 0553e575a5..04fca8529f 100644 --- a/src/qml/qml/v4/qv4bindings_p.h +++ b/src/qml/qml/v4/qv4bindings_p.h @@ -84,13 +84,15 @@ public: : QQmlAbstractBinding(V4), target(0), scope(0), instruction(0), executedBlocks(0), parent(0) {} // Inherited from QQmlAbstractBinding - static void destroy(QQmlAbstractBinding *); + static void destroy(QQmlAbstractBinding *, QQmlAbstractBinding::DestroyMode mode); static int propertyIndex(const QQmlAbstractBinding *); static QObject *object(const QQmlAbstractBinding *); static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags); static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); static void retargetBinding(QQmlAbstractBinding *, QObject *, int); + void disconnect(); + struct Retarget { QObject *target; int targetProperty; @@ -121,7 +123,10 @@ private: public: inline Subscription(); QV4Bindings *bindings; - int method; + int method:31; + + // Subscriptions are not shared between bindings (anymore), so this can be a simple bool flag + bool active:1; }; friend void QV4BindingsSubscription_callback(QQmlNotifierEndpoint *e, void **); @@ -144,7 +149,6 @@ private: ); - inline void unsubscribe(int subIndex); inline void subscribeId(QQmlContextData *p, int idIndex, int subIndex); inline void subscribe(QObject *o, int notifyIndex, int subIndex, QQmlEngine *); |