if (property.notifier != 0) {
- if (!noChanges && guard.isConnected(property.notifier)) {
- // Nothing to do
-
+ if (guard.isConnected(property.notifier)) {
+ guard.cancelNotify();
} else {
- noChanges = false;
-
- bool existing = false;
- for (int jj = 0; !existing && jj < ii; ++jj)
- if (endpoints[jj].isConnected(property.notifier))
- existing = true;
-
- if (existing) {
- // duplicate
- guard.disconnect();
- } else {
- guard.connect(property.notifier);
- }
+ guard.connect(property.notifier);
}
-
} else if (property.notifyIndex != -1) {
- if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
- // Nothing to do
-
- } else {
- noChanges = false;
-
- bool existing = false;
- for (int jj = 0; !existing && jj < ii; ++jj)
- if (endpoints[jj].isConnected(property.object, property.notifyIndex))
- existing = true;
-
- if (existing) {
- // duplicate
- guard.disconnect();
- } else {
- guard.connect(property.object, property.notifyIndex);
- }
+ if (guard.isConnected(property.object, property.notifyIndex)) {
+ guard.cancelNotify();
+ } else {
+ guard.connect(property.object, property.notifyIndex);
}
} else {
{
QDeclarativeNotifierEndpoint **oldDisconnected = endpoint->disconnected;
endpoint->disconnected = &endpoint;
+ endpoint->notifying = 1;
if (endpoint->next)
emitNotify(endpoint->next);
if (endpoint) {
- void *args[] = { 0 };
Q_ASSERT(endpoint->callback);
+
endpoint->callback(endpoint);
if (endpoint)
}
if (oldDisconnected) *oldDisconnected = endpoint;
+ else if (endpoint) endpoint->notifying = 0;
}
void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal)
other.notifier = notifier;
other.sourceSignal = sourceSignal;
other.disconnected = disconnected;
+ other.notifying = notifying;
if (other.disconnected) *other.disconnected = &other;
if (next) {
next = 0;
disconnected = 0;
notifier = 0;
+ notifying = 0;
sourceSignal = -1;
}
inline void connect(QDeclarativeNotifier *);
inline void disconnect();
+ inline bool isNotifying() const;
+ inline void cancelNotify();
+
void copyAndClear(QDeclarativeNotifierEndpoint &other);
private:
QDeclarativeNotifier *notifier;
QObject *source;
};
- int sourceSignal;
+ unsigned int notifying : 1;
+ signed int sourceSignal : 31;
QDeclarativeNotifierEndpoint **disconnected;
QDeclarativeNotifierEndpoint *next;
QDeclarativeNotifierEndpoint **prev;
}
QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint()
-: callback(0), notifier(0), sourceSignal(-1), disconnected(0), next(0), prev(0)
+: callback(0), notifier(0), notifying(0), sourceSignal(-1), disconnected(0), next(0), prev(0)
{
}
bool QDeclarativeNotifierEndpoint::isConnected(QObject *source, int sourceSignal)
{
- return sourceSignal != -1 && this->source == source && this->sourceSignal == sourceSignal;
+ return this->sourceSignal != -1 && this->source == source && this->sourceSignal == sourceSignal;
}
bool QDeclarativeNotifierEndpoint::isConnected(QDeclarativeNotifier *notifier)
prev = 0;
disconnected = 0;
notifier = 0;
+ notifying = 0;
sourceSignal = -1;
}
+/*!
+Returns true if a notify is in progress. This means that the signal or QDeclarativeNotifier
+that this endpoing is connected to has been triggered, but this endpoint's callback has not
+yet been called.
+
+An in progress notify can be cancelled by calling cancelNotify.
+*/
+bool QDeclarativeNotifierEndpoint::isNotifying() const
+{
+ return notifying == 1;
+}
+
+/*!
+Cancel any notifies that are in progress.
+*/
+void QDeclarativeNotifierEndpoint::cancelNotify()
+{
+ notifying = 0;
+ if (disconnected) {
+ *disconnected = 0;
+ disconnected = 0;
+ }
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVENOTIFIER_P_H
--- /dev/null
+import Qt.test 1.0
+
+WriteCounter {
+ property int x: 0
+ value: if (1) x + x
+}
qmlRegisterType<CircularReferenceHandle>("Qt.test", 1, 0, "CircularReferenceHandle");
qmlRegisterType<MyDynamicCreationDestructionObject>("Qt.test", 1, 0, "MyDynamicCreationDestructionObject");
+ qmlRegisterType<WriteCounter>("Qt.test", 1, 0, "WriteCounter");
}
#include "testtypes.moc"
int *m_dtorCount;
};
+class WriteCounter : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue);
+public:
+ WriteCounter() : m_value(0), m_count(0) {}
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; ++m_count; }
+
+ int count() const { return m_count; }
+
+private:
+ int m_value;
+ int m_count;
+};
+
void registerTypes();
#endif // TESTTYPES_H
void dynamicString();
void include();
void signalHandlers();
+ void doubleEvaluate();
void callQtInvokables();
void invokableObjectArg();
QVERIFY(object != 0);
}
+// Makes sure that a binding isn't double re-evaluated when it depends on the same variable twice
+void tst_qdeclarativeecmascript::doubleEvaluate()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("doubleEvaluate.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ WriteCounter *wc = qobject_cast<WriteCounter *>(object);
+ QVERIFY(wc != 0);
+ QCOMPARE(wc->count(), 1);
+
+ wc->setProperty("x", 9);
+
+ QCOMPARE(wc->count(), 2);
+
+ delete object;
+}
+
QTEST_MAIN(tst_qdeclarativeecmascript)
#include "tst_qdeclarativeecmascript.moc"