summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2010-03-10 06:35:44 (GMT)
committerMartin Jones <martin.jones@nokia.com>2010-03-10 06:35:44 (GMT)
commitfedf97276ce8b9b982b2d897a40f5b6428c710a8 (patch)
treeada6810c08189df96d59c2b4b3bb83efd96150e3 /src/declarative
parent7b29dc7daa035a351ba10dcfb879bc3f70434f63 (diff)
parent099d63fd9b4017b8e02b2cfaae82f29c0c0d294f (diff)
downloadQt-fedf97276ce8b9b982b2d897a40f5b6428c710a8.zip
Qt-fedf97276ce8b9b982b2d897a40f5b6428c710a8.tar.gz
Qt-fedf97276ce8b9b982b2d897a40f5b6428c710a8.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings.cpp97
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp7
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h5
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp153
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h19
-rw-r--r--src/declarative/qml/qdeclarativenotifier.cpp109
-rw-r--r--src/declarative/qml/qdeclarativenotifier_p.h272
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp4
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h19
-rw-r--r--src/declarative/qml/qml.pri2
10 files changed, 458 insertions, 229 deletions
diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp
index 17937fd..b35b5b5 100644
--- a/src/declarative/qml/qdeclarativecompiledbindings.cpp
+++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp
@@ -124,24 +124,7 @@ public:
QDeclarativeCompiledBindingsPrivate *parent;
};
- struct Subscription {
- struct Signal {
- QDeclarativeGuard<QObject> source;
- int notifyIndex;
- };
-
- enum { InvalidType, SignalType, IdType } type;
- inline Subscription();
- inline ~Subscription();
- bool isSignal() const { return type == SignalType; }
- bool isId() const { return type == IdType; }
- inline Signal *signal();
- inline QDeclarativeContextPrivate::IdNotifier *id();
- union {
- char signalData[sizeof(Signal)];
- char idData[sizeof(QDeclarativeContextPrivate::IdNotifier)];
- };
- };
+ typedef QDeclarativeNotifierEndpoint Subscription;
Subscription *subscriptions;
QScriptDeclarativeClass::PersistentIdentifier *identifiers;
@@ -190,18 +173,6 @@ QDeclarativeCompiledBindingsPrivate::~QDeclarativeCompiledBindingsPrivate()
delete [] identifiers; identifiers = 0;
}
-QDeclarativeCompiledBindingsPrivate::Subscription::Subscription()
-: type(InvalidType)
-{
-}
-
-QDeclarativeCompiledBindingsPrivate::Subscription::~Subscription()
-{
- if (type == SignalType) ((Signal *)signalData)->~Signal();
- else if (type == IdType) ((QDeclarativeContextPrivate::IdNotifier *)idData)->~IdNotifier();
-}
-
-
int QDeclarativeCompiledBindingsPrivate::methodCount = -1;
QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContext *context)
@@ -330,22 +301,6 @@ void QDeclarativeCompiledBindingsPrivate::run(Binding *binding)
}
}
-QDeclarativeCompiledBindingsPrivate::Subscription::Signal *QDeclarativeCompiledBindingsPrivate::Subscription::signal()
-{
- if (type == IdType) ((QDeclarativeContextPrivate::IdNotifier *)idData)->~IdNotifier();
- if (type != SignalType) new (signalData) Signal;
- type = SignalType;
- return (Signal *)signalData;
-}
-
-QDeclarativeContextPrivate::IdNotifier *QDeclarativeCompiledBindingsPrivate::Subscription::id()
-{
- if (type == SignalType) ((Signal *)signalData)->~Signal();
- if (type != IdType) new (idData) QDeclarativeContextPrivate::IdNotifier;
- type = IdType;
- return (QDeclarativeContextPrivate::IdNotifier *)idData;
-}
-
namespace {
// This structure is exactly 8-bytes in size
struct Instr {
@@ -656,20 +611,7 @@ void QDeclarativeCompiledBindingsPrivate::unsubscribe(int subIndex)
Q_Q(QDeclarativeCompiledBindings);
QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
- if (sub->isSignal()) {
- QDeclarativeCompiledBindingsPrivate::Subscription::Signal *s = sub->signal();
- if (s->source)
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
- QMetaObject::disconnectOne(s->source, s->notifyIndex,
- q, methodCount + subIndex);
-#else
- // QTBUG-6781
- QMetaObject::disconnect(s->source, s->notifyIndex,
- q, methodCount + subIndex);
-#endif
- } else if (sub->isId()) {
- sub->id()->clear();
- }
+ sub->disconnect();
}
void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextPrivate *p, int idIndex, int subIndex)
@@ -680,15 +622,8 @@ void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextPrivate
if (p->idValues[idIndex]) {
QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
- QDeclarativeContextPrivate::IdNotifier *i = sub->id();
-
- i->next = p->idValues[idIndex].bindings;
- i->prev = &p->idValues[idIndex].bindings;
- p->idValues[idIndex].bindings = i;
- if (i->next) i->next->prev = &i->next;
-
- i->target = q;
- i->methodIndex = methodCount + subIndex;
+ sub->target = q;
+ sub->targetMethod = methodCount + subIndex;
}
}
@@ -697,27 +632,9 @@ void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex,
Q_Q(QDeclarativeCompiledBindings);
QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
-
- if (sub->isId())
- unsubscribe(subIndex);
-
- QDeclarativeCompiledBindingsPrivate::Subscription::Signal *s = sub->signal();
- if (o != s->source || notifyIndex != s->notifyIndex) {
- if (s->source)
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
- QMetaObject::disconnectOne(s->source, s->notifyIndex,
- q, methodCount + subIndex);
-#else
- // QTBUG-6781
- QMetaObject::disconnect(s->source, s->notifyIndex,
- q, methodCount + subIndex);
-#endif
- s->source = o;
- s->notifyIndex = notifyIndex;
- if (s->source && s->notifyIndex != -1)
- QMetaObject::connect(s->source, s->notifyIndex, q,
- methodCount + subIndex, Qt::DirectConnection);
- }
+ sub->target = q;
+ sub->targetMethod = methodCount + subIndex;
+ sub->connect(o, notifyIndex);
}
// Conversion functions - these MUST match the QtScript expression path
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index f70e143..356a4ab 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -109,12 +109,7 @@ void QDeclarativeContextPrivate::destroyed(ContextGuard *guard)
if (parent && QObjectPrivate::get(parent)->wasDeleted)
return;
- while(guard->bindings) {
- QObject *o = guard->bindings->target;
- int mi = guard->bindings->methodIndex;
- guard->bindings->clear();
- if (o) o->qt_metacall(QMetaObject::InvokeMetaMethod, mi, 0);
- }
+ guard->bindings.notify();
for (int ii = 0; ii < idValueCount; ++ii) {
if (&idValues[ii] == guard) {
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index 8297280..5b597fa 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -59,6 +59,7 @@
#include "qdeclarativeengine_p.h"
#include "qdeclarativeintegercache_p.h"
#include "qdeclarativetypenamecache_p.h"
+#include "qdeclarativenotifier_p.h"
#include <QtCore/qhash.h>
#include <QtScript/qscriptvalue.h>
@@ -133,7 +134,7 @@ public:
inline virtual void objectDestroyed(QObject *);
QDeclarativeContextPrivate *priv;
- IdNotifier *bindings;
+ QDeclarativeNotifier bindings;
};
ContextGuard *idValues;
int idValueCount;
@@ -176,7 +177,7 @@ void QDeclarativeContextPrivate::IdNotifier::clear()
}
QDeclarativeContextPrivate::ContextGuard::ContextGuard()
-: priv(0), bindings(0)
+: priv(0)
{
}
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index e528e9e..207ded6 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -621,137 +621,74 @@ void QDeclarativeExpression::__q_notify()
void QDeclarativeExpressionPrivate::clearGuards()
{
- Q_Q(QDeclarativeExpression);
-
- static int notifyIdx = -1;
- if (notifyIdx == -1)
- notifyIdx =
- QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()");
-
- for (int ii = 0; ii < data->guardListLength; ++ii) {
- if (data->guardList[ii].data()) {
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
- QMetaObject::disconnectOne(data->guardList[ii].data(),
- data->guardList[ii].notifyIndex,
- q, notifyIdx);
-#else
- // QTBUG-6781
- QMetaObject::disconnect(data->guardList[ii].data(),
- data->guardList[ii].notifyIndex,
- q, notifyIdx);
-#endif
- }
- }
-
- delete [] data->guardList; data->guardList = 0;
+ delete [] data->guardList;
+ data->guardList = 0;
data->guardListLength = 0;
}
void QDeclarativeExpressionPrivate::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
{
- //clearGuards();
Q_Q(QDeclarativeExpression);
static int notifyIdx = -1;
if (notifyIdx == -1)
- notifyIdx =
- QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()");
+ notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()");
- QDeclarativeExpressionData::SignalGuard *newGuardList = 0;
-
- if (properties.count() != data->guardListLength)
- newGuardList = new QDeclarativeExpressionData::SignalGuard[properties.count()];
+ if (properties.count() != data->guardListLength) {
+ QDeclarativeNotifierEndpoint *newGuardList =
+ new QDeclarativeNotifierEndpoint[properties.count()];
+
+ for (int ii = 0; ii < qMin(data->guardListLength, properties.count()); ++ii)
+ data->guardList[ii].copyAndClear(newGuardList[ii]);
+
+ delete [] data->guardList;
+ data->guardList = newGuardList;
+ data->guardListLength = properties.count();
+ }
bool outputWarningHeader = false;
- int hit = 0;
+ bool noChanges = true;
for (int ii = 0; ii < properties.count(); ++ii) {
+ QDeclarativeNotifierEndpoint &guard = data->guardList[ii];
const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
- bool needGuard = true;
- if (ii >= data->guardListLength) {
- // New guard
- } else if(data->guardList[ii].data() == property.object &&
- data->guardList[ii].notifyIndex == property.notifyIndex) {
- // Cache hit
- if (!data->guardList[ii].isDuplicate ||
- (data->guardList[ii].isDuplicate && hit == ii)) {
- needGuard = false;
- ++hit;
- }
- } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
- // Cache miss
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
- QMetaObject::disconnectOne(data->guardList[ii].data(),
- data->guardList[ii].notifyIndex,
- q, notifyIdx);
-#else
- // QTBUG-6781
- QMetaObject::disconnect(data->guardList[ii].data(),
- data->guardList[ii].notifyIndex,
- q, notifyIdx);
-#endif
- }
- /* else {
- // Cache miss, but nothing to do
- } */
-
- if (needGuard) {
- if (!newGuardList) {
- newGuardList = new QDeclarativeExpressionData::SignalGuard[properties.count()];
- for (int jj = 0; jj < ii; ++jj)
- newGuardList[jj] = data->guardList[jj];
- }
+ guard.target = q;
+ guard.targetMethod = notifyIdx;
+
+ if (property.notifyIndex != -1) {
+
+ if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
+ // Nothing to do
+
+ } else {
+ noChanges = false;
- if (property.notifyIndex != -1) {
bool existing = false;
for (int jj = 0; !existing && jj < ii; ++jj)
- existing = newGuardList[jj].data() == property.object &&
- newGuardList[jj].notifyIndex == property.notifyIndex;
-
- newGuardList[ii] = property.object;
- newGuardList[ii].notifyIndex = property.notifyIndex;
- if (existing)
- newGuardList[ii].isDuplicate = true;
- else
- QMetaObject::connect(property.object, property.notifyIndex,
- q, notifyIdx);
- } else {
- if (!outputWarningHeader) {
- outputWarningHeader = true;
- qWarning() << "QDeclarativeExpression: Expression" << q->expression()
- << "depends on non-NOTIFYable properties:";
+ if (data->guardList[jj].isConnected(property.object, property.notifyIndex))
+ existing = true;
+
+ if (existing) {
+ // duplicate
+ guard.disconnect();
+ } else {
+ guard.connect(property.object, property.notifyIndex);
}
+ }
- const QMetaObject *metaObj = property.object->metaObject();
- QMetaProperty metaProp = metaObj->property(property.coreIndex);
-
- qWarning().nospace() << " " << metaObj->className()
- << "::" << metaProp.name();
+ } else {
+ if (!outputWarningHeader) {
+ outputWarningHeader = true;
+ qWarning() << "QDeclarativeExpression: Expression" << q->expression()
+ << "depends on non-NOTIFYable properties:";
}
- } else if (newGuardList) {
- newGuardList[ii] = data->guardList[ii];
- }
- }
- for (int ii = properties.count(); ii < data->guardListLength; ++ii) {
- if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
- QMetaObject::disconnectOne(data->guardList[ii].data(),
- data->guardList[ii].notifyIndex,
- q, notifyIdx);
-#else
- // QTBUG-6781
- QMetaObject::disconnect(data->guardList[ii].data(),
- data->guardList[ii].notifyIndex,
- q, notifyIdx);
-#endif
- }
- }
+ const QMetaObject *metaObj = property.object->metaObject();
+ QMetaProperty metaProp = metaObj->property(property.coreIndex);
- if (newGuardList) {
- if (data->guardList) delete [] data->guardList;
- data->guardList = newGuardList;
- data->guardListLength = properties.count();
+ qWarning().nospace() << " " << metaObj->className()
+ << "::" << metaProp.name();
+ }
}
}
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index cd1729d..d170559 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -129,24 +129,7 @@ public:
QString url; // This is a QString for a reason. QUrls are slooooooow...
int line;
- struct SignalGuard : public QDeclarativeGuard<QObject> {
- SignalGuard() : isDuplicate(false), notifyIndex(-1) {}
-
- SignalGuard &operator=(QObject *obj) {
- QDeclarativeGuard<QObject>::operator=(obj);
- return *this;
- }
- SignalGuard &operator=(const SignalGuard &o) {
- QDeclarativeGuard<QObject>::operator=(o);
- isDuplicate = o.isDuplicate;
- notifyIndex = o.notifyIndex;
- return *this;
- }
-
- bool isDuplicate:1;
- int notifyIndex:31;
- };
- SignalGuard *guardList;
+ QDeclarativeNotifierEndpoint *guardList;
int guardListLength;
};
diff --git a/src/declarative/qml/qdeclarativenotifier.cpp b/src/declarative/qml/qdeclarativenotifier.cpp
new file mode 100644
index 0000000..0a8783a
--- /dev/null
+++ b/src/declarative/qml/qdeclarativenotifier.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativenotifier_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void QDeclarativeNotifier::emitNotify(QDeclarativeNotifierEndpoint *endpoint)
+{
+ QDeclarativeNotifierEndpoint::Notifier *n = endpoint->asNotifier();
+
+ QDeclarativeNotifierEndpoint::Notifier **oldDisconnected = n->disconnected;
+ n->disconnected = &n;
+
+ if (n->next)
+ emitNotify(n->next);
+
+ if (n) {
+ void *args[] = { 0 };
+
+ QMetaObject::metacall(endpoint->target, QMetaObject::InvokeMetaMethod,
+ endpoint->targetMethod, args);
+
+ n->disconnected = oldDisconnected;
+ }
+
+ if (oldDisconnected) *oldDisconnected = n;
+}
+
+void QDeclarativeNotifierEndpoint::copyAndClear(QDeclarativeNotifierEndpoint &other)
+{
+ other.disconnect();
+
+ other.target = target;
+ other.targetMethod = targetMethod;
+
+ if (!isConnected())
+ return;
+
+ if (SignalType == type) {
+ Signal *other_s = other.toSignal();
+ Signal *s = asSignal();
+
+ other_s->source = s->source;
+ other_s->sourceSignal = s->sourceSignal;
+ s->source = 0;
+ } else if(NotifierType == type) {
+ Notifier *other_n = other.toNotifier();
+ Notifier *n = asNotifier();
+
+ other_n->notifier = n->notifier;
+ other_n->disconnected = n->disconnected;
+ if (other_n->disconnected) *other_n->disconnected = other_n;
+
+ if (n->next) {
+ other_n->next = n->next;
+ n->next->asNotifier()->prev = &other_n->next;
+ }
+ other_n->prev = n->prev;
+ *other_n->prev = &other;
+
+ n->prev = 0;
+ n->next = 0;
+ n->disconnected = 0;
+ n->notifier = 0;
+ }
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qdeclarativenotifier_p.h b/src/declarative/qml/qdeclarativenotifier_p.h
new file mode 100644
index 0000000..a0e6b43
--- /dev/null
+++ b/src/declarative/qml/qdeclarativenotifier_p.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVENOTIFIER_P_H
+#define QDECLARATIVENOTIFIER_P_H
+
+#include "qdeclarativeguard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeNotifierEndpoint;
+class QDeclarativeNotifier
+{
+public:
+ inline QDeclarativeNotifier();
+ inline ~QDeclarativeNotifier();
+ inline void notify();
+
+private:
+ friend class QDeclarativeNotifierEndpoint;
+
+ static void emitNotify(QDeclarativeNotifierEndpoint *);
+ QDeclarativeNotifierEndpoint *endpoints;
+};
+
+class QDeclarativeNotifierEndpoint
+{
+public:
+ inline QDeclarativeNotifierEndpoint();
+ inline QDeclarativeNotifierEndpoint(QObject *t, int m);
+ inline ~QDeclarativeNotifierEndpoint();
+
+ QObject *target;
+ int targetMethod;
+
+ inline bool isConnected();
+ inline bool isConnected(QObject *source, int sourceSignal);
+ inline bool isConnected(QDeclarativeNotifier *);
+
+ inline void connect(QObject *source, int sourceSignal);
+ inline void connect(QDeclarativeNotifier *);
+ inline void disconnect();
+
+ void copyAndClear(QDeclarativeNotifierEndpoint &other);
+
+private:
+ friend class QDeclarativeNotifier;
+
+ struct Signal {
+ QDeclarativeGuard<QObject> source;
+ int sourceSignal;
+ };
+
+ struct Notifier {
+ QDeclarativeNotifier *notifier;
+ Notifier **disconnected;
+
+ QDeclarativeNotifierEndpoint *next;
+ QDeclarativeNotifierEndpoint **prev;
+ };
+
+ enum { InvalidType, SignalType, NotifierType } type;
+ union {
+ char signalData[sizeof(Signal)];
+ char notifierData[sizeof(Notifier)];
+ };
+
+ inline Notifier *toNotifier();
+ inline Notifier *asNotifier();
+ inline Signal *toSignal();
+ inline Signal *asSignal();
+};
+
+QDeclarativeNotifier::QDeclarativeNotifier()
+: endpoints(0)
+{
+ QDeclarativeNotifierEndpoint *endpoint = endpoints;
+ while (endpoint) {
+ QDeclarativeNotifierEndpoint *next = endpoint->asNotifier()->next;
+ endpoint->asNotifier()->next = 0;
+ endpoint->asNotifier()->prev = 0;
+ endpoint->asNotifier()->notifier = 0;
+ endpoint = next;
+ }
+}
+
+QDeclarativeNotifier::~QDeclarativeNotifier()
+{
+}
+
+void QDeclarativeNotifier::notify()
+{
+ if (endpoints) emitNotify(endpoints);
+}
+
+QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint()
+: target(0), targetMethod(0), type(InvalidType)
+{
+}
+
+QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint(QObject *t, int m)
+: target(t), targetMethod(m), type(InvalidType)
+{
+}
+
+QDeclarativeNotifierEndpoint::~QDeclarativeNotifierEndpoint()
+{
+ disconnect();
+ if (SignalType == type) {
+ Signal *s = asSignal();
+ s->~Signal();
+ }
+}
+
+bool QDeclarativeNotifierEndpoint::isConnected()
+{
+ if (SignalType == type) {
+ return asSignal()->source;
+ } else if (NotifierType == type) {
+ return asNotifier()->notifier;
+ } else {
+ return false;
+ }
+}
+
+bool QDeclarativeNotifierEndpoint::isConnected(QObject *source, int sourceSignal)
+{
+ return SignalType == type && asSignal()->source == source && asSignal()->sourceSignal == sourceSignal;
+}
+
+bool QDeclarativeNotifierEndpoint::isConnected(QDeclarativeNotifier *notifier)
+{
+ return NotifierType == type && asNotifier()->notifier == notifier;
+}
+
+void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal)
+{
+ Signal *s = toSignal();
+
+ if (s->source == source && s->sourceSignal == sourceSignal)
+ return;
+
+ disconnect();
+
+ QMetaObject::connect(source, sourceSignal, target, targetMethod);
+
+ s->source = source;
+ s->sourceSignal = sourceSignal;
+}
+
+void QDeclarativeNotifierEndpoint::connect(QDeclarativeNotifier *notifier)
+{
+ Notifier *n = toNotifier();
+
+ if (n->notifier == notifier)
+ return;
+
+ disconnect();
+
+ n->next = notifier->endpoints;
+ if (n->next) { n->next->asNotifier()->prev = &n->next; }
+ notifier->endpoints = this;
+ n->prev = &notifier->endpoints;
+ n->notifier = notifier;
+}
+
+void QDeclarativeNotifierEndpoint::disconnect()
+{
+ if (type == SignalType) {
+ Signal *s = (Signal *)&signalData;
+ if (s->source) {
+ QMetaObject::disconnectOne(s->source, s->sourceSignal, target, targetMethod);
+ s->source = 0;
+ }
+ } else if (type == NotifierType) {
+ Notifier *n = asNotifier();
+
+ if (n->next) n->next->asNotifier()->prev = n->prev;
+ if (n->prev) *n->prev = n->next;
+ if (n->disconnected) *n->disconnected = 0;
+ n->next = 0;
+ n->prev = 0;
+ n->disconnected = 0;
+ n->notifier = 0;
+ }
+}
+
+QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::toNotifier()
+{
+ if (NotifierType == type)
+ return asNotifier();
+
+ if (SignalType == type) {
+ disconnect();
+ Signal *s = asSignal();
+ s->~Signal();
+ }
+
+ Notifier *n = asNotifier();
+ n->next = 0;
+ n->prev = 0;
+ n->disconnected = 0;
+ n->notifier = 0;
+ type = NotifierType;
+ return n;
+}
+
+QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::asNotifier()
+{
+ return (Notifier *)(&notifierData);
+}
+
+QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::toSignal()
+{
+ if (SignalType == type)
+ return asSignal();
+
+ disconnect();
+ Signal *s = asSignal();
+ new (s) Signal;
+ type = SignalType;
+
+ return s;
+}
+
+QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::asSignal()
+{
+ return (Signal *)(&signalData);
+}
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVENOTIFIER_P_H
+
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index fea59e5..cbb67e1 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -420,4 +420,8 @@ QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativ
return rv;
}
+QDeclarativePropertyCache::Data QDeclarativePropertyCache::property(const QMetaObject *, const char *)
+{
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 68e6e6b..ea2f01a 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -55,15 +55,16 @@
#include "qdeclarativerefcount_p.h"
#include "qdeclarativecleanup_p.h"
+#include "qdeclarativenotifier_p.h"
#include <QtCore/qvector.h>
#include <QtScript/private/qscriptdeclarativeclass_p.h>
-
QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
class QMetaProperty;
+
class QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup
{
public:
@@ -81,11 +82,12 @@ public:
IsConstant = 0x00000001,
IsWritable = 0x00000002,
IsResettable = 0x00000004,
+ HasNotify = 0x00000008,
// These are mutualy exclusive
- IsFunction = 0x00000008,
- IsQObjectDerived = 0x00000010,
- IsEnumType = 0x00000020,
+ IsFunction = 0x00000010,
+ IsQObjectDerived = 0x00000020,
+ IsEnumType = 0x00000040,
IsQList = 0x00000080,
IsQmlBinding = 0x00000100,
IsQScriptValue = 0x00000200,
@@ -97,11 +99,17 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
+ enum Call { ReadProperty, WriteProperty, ConnectNotify, DisconnectNotify };
+ typedef void (*MetaCall)(QObject *, Call, void *);
+
bool isValid() const { return coreIndex != -1; }
Flags flags;
int propType;
- int coreIndex;
+ union {
+ MetaCall call;
+ int coreIndex;
+ };
int notifyIndex;
static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0);
@@ -136,6 +144,7 @@ public:
inline QDeclarativeEngine *qmlEngine() const;
static Data *property(QDeclarativeEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &);
static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &);
+ static Data property(const QMetaObject *, const char *);
protected:
virtual void clear();
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index aa1a34b..49888c3 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -38,6 +38,7 @@ SOURCES += \
$$PWD/qdeclarativescript.cpp \
$$PWD/qdeclarativecleanup.cpp \
$$PWD/qdeclarativepropertycache.cpp \
+ $$PWD/qdeclarativenotifier.cpp \
$$PWD/qdeclarativeintegercache.cpp \
$$PWD/qdeclarativetypenamecache.cpp \
$$PWD/qdeclarativescriptstring.cpp \
@@ -108,6 +109,7 @@ HEADERS += \
$$PWD/qdeclarativewatcher_p.h \
$$PWD/qdeclarativecleanup_p.h \
$$PWD/qdeclarativepropertycache_p.h \
+ $$PWD/qdeclarativenotifier_p.h \
$$PWD/qdeclarativeintegercache_p.h \
$$PWD/qdeclarativetypenamecache_p.h \
$$PWD/qdeclarativescriptstring.h \