From 30a3e78a12b72ab6f67992ec2f06cd4f21a01a6c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 15 Apr 2010 16:35:51 +1000 Subject: Add Component.onDestruction attached property This property complements Component.onCompleted. It is emitted before the destruction actually begins (for the most part) so the objects are still alive and accessible. The QtObject.onDestroyed signal is now blocked as it never really worked properly anyway. --- src/declarative/qml/qdeclarativecompiler.cpp | 31 +----------- src/declarative/qml/qdeclarativecompiler_p.h | 2 - src/declarative/qml/qdeclarativecomponent.cpp | 45 +++++++++-------- src/declarative/qml/qdeclarativecomponent_p.h | 15 +++++- src/declarative/qml/qdeclarativecontext.cpp | 57 +++++++++++----------- src/declarative/qml/qdeclarativecontext_p.h | 7 ++- src/declarative/qml/qdeclarativeengine.cpp | 11 +++-- src/declarative/qml/qdeclarativeengine_p.h | 2 +- src/declarative/qml/qdeclarativeproperty.cpp | 34 ++++++++++++- src/declarative/qml/qdeclarativeproperty_p.h | 3 +- src/declarative/qml/qdeclarativepropertycache.cpp | 6 +-- .../tst_qdeclarativecontext.cpp | 10 ++-- .../data/OnDestructionType.qml | 8 +++ .../data/destroyedSignal.errors.txt | 1 + .../qdeclarativelanguage/data/destroyedSignal.qml | 5 ++ .../qdeclarativelanguage/data/onDestruction.qml | 17 +++++++ .../tst_qdeclarativelanguage.cpp | 16 ++++++ 17 files changed, 171 insertions(+), 99 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/OnDestructionType.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.errors.txt create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/onDestruction.qml diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index fad7779..5c5ad37 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1364,35 +1364,6 @@ int QDeclarativeCompiler::componentTypeRef() return output->types.count() - 1; } -QMetaMethod QDeclarativeCompiler::findSignalByName(const QMetaObject *mo, const QByteArray &name) -{ - Q_ASSERT(mo); - int methods = mo->methodCount(); - for (int ii = methods - 1; ii >= 0; --ii) { - QMetaMethod method = mo->method(ii); - QByteArray methodName = method.signature(); - int idx = methodName.indexOf('('); - methodName = methodName.left(idx); - - if (methodName == name) - return method; - } - - // If no signal is found, but the signal is of the form "onBlahChanged", - // return the notify signal for the property "Blah" - if (name.endsWith("Changed")) { - QByteArray propName = name.mid(0, name.length() - 7); - int propIdx = mo->indexOfProperty(propName.constData()); - if (propIdx >= 0) { - QMetaProperty prop = mo->property(propIdx); - if (prop.hasNotifySignal()) - return prop.notifySignal(); - } - } - - return QMetaMethod(); -} - bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj, const BindingContext &ctxt) { @@ -1404,7 +1375,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl if(name[0] >= 'A' && name[0] <= 'Z') name[0] = name[0] - 'A' + 'a'; - int sigIdx = findSignalByName(obj->metaObject(), name).methodIndex(); + int sigIdx = QDeclarativePropertyPrivate::findSignalByName(obj->metaObject(), name).methodIndex(); if (sigIdx == -1) { diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 0e47774..002c6c9 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -159,8 +159,6 @@ public: static bool isAttachedPropertyName(const QByteArray &); static bool isSignalPropertyName(const QByteArray &); - static QMetaMethod findSignalByName(const QMetaObject *, const QByteArray &name); - int evaluateEnum(const QByteArray& script) const; // for QDeclarativeCustomParser::evaluateEnum private: diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 7744b75..5cc6639 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -657,11 +657,11 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *ctxt, QDe state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; - state->componentAttacheds = enginePriv->componentAttacheds; - if (state->componentAttacheds) - state->componentAttacheds->prev = &state->componentAttacheds; + state->componentAttached = enginePriv->componentAttached; + if (state->componentAttached) + state->componentAttached->prev = &state->componentAttached; - enginePriv->componentAttacheds = 0; + enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); state->completePending = true; @@ -688,11 +688,11 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; - state->componentAttacheds = enginePriv->componentAttacheds; - if (state->componentAttacheds) - state->componentAttacheds->prev = &state->componentAttacheds; + state->componentAttached = enginePriv->componentAttached; + if (state->componentAttached) + state->componentAttached->prev = &state->componentAttached; - enginePriv->componentAttacheds = 0; + enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); state->completePending = true; @@ -729,11 +729,13 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri QDeclarativeEnginePrivate::clear(ps); } - while (state->componentAttacheds) { - QDeclarativeComponentAttached *a = state->componentAttacheds; - if (a->next) a->next->prev = &state->componentAttacheds; - state->componentAttacheds = a->next; - a->prev = 0; a->next = 0; + while (state->componentAttached) { + QDeclarativeComponentAttached *a = state->componentAttached; + a->rem(); + QDeclarativeData *d = QDeclarativeData::get(a->parent()); + Q_ASSERT(d); + Q_ASSERT(d->context); + a->add(&d->context->componentAttached); emit a->completed(); } @@ -793,15 +795,18 @@ QDeclarativeComponentAttached *QDeclarativeComponent::qmlAttachedProperties(QObj QDeclarativeComponentAttached *a = new QDeclarativeComponentAttached(obj); QDeclarativeEngine *engine = qmlEngine(obj); - if (!engine || !QDeclarativeEnginePrivate::get(engine)->inBeginCreate) + if (!engine) return a; - QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); - - a->next = p->componentAttacheds; - a->prev = &p->componentAttacheds; - if (a->next) a->next->prev = &a->next; - p->componentAttacheds = a; + if (QDeclarativeEnginePrivate::get(engine)->inBeginCreate) { + QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); + a->add(&p->componentAttached); + } else { + QDeclarativeData *d = QDeclarativeData::get(obj); + Q_ASSERT(d); + Q_ASSERT(d->context); + a->add(&d->context->componentAttached); + } return a; } diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index dfd0fc3..24e5386 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -99,10 +99,10 @@ public: QDeclarativeCompiledData *cc; struct ConstructionState { - ConstructionState() : componentAttacheds(0), completePending(false) {} + ConstructionState() : componentAttached(0), completePending(false) {} QList > bindValues; QList > parserStatus; - QDeclarativeComponentAttached *componentAttacheds; + QDeclarativeComponentAttached *componentAttached; QList errors; bool completePending; }; @@ -132,13 +132,24 @@ public: QDeclarativeComponentAttached(QObject *parent = 0); ~QDeclarativeComponentAttached(); + void add(QDeclarativeComponentAttached **a) { + prev = a; next = *a; *a = this; + if (next) next->prev = &next; + } + void rem() { + if (next) next->prev = prev; + *prev = next; + next = 0; prev = 0; + } QDeclarativeComponentAttached **prev; QDeclarativeComponentAttached *next; Q_SIGNALS: void completed(); + void destruction(); private: + friend class QDeclarativeContextData;; friend class QDeclarativeComponentPrivate; }; diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 42e7386..6657fea 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -42,6 +42,7 @@ #include "qdeclarativecontext.h" #include "private/qdeclarativecontext_p.h" +#include "private/qdeclarativecomponent_p.h" #include "private/qdeclarativeexpression_p.h" #include "private/qdeclarativeengine_p.h" #include "qdeclarativeengine.h" @@ -476,21 +477,34 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListPropertydestroy(); + while (childContexts) + childContexts->invalidate(); + + while (componentAttached) { + QDeclarativeComponentAttached *a = componentAttached; + componentAttached = a->next; + if (componentAttached) componentAttached->prev = &componentAttached; + + a->next = 0; + a->prev = 0; + + emit a->destruction(); + } if (prevChild) { *prevChild = nextChild; @@ -498,19 +512,17 @@ void QDeclarativeContextData::destroy() nextChild = 0; prevChild = 0; } - - QDeclarativeContextData *child = childContexts; - while (child) { - QDeclarativeContextData *next = child->nextChild; - child->invalidateEngines(); - child->parent = 0; - child->nextChild = 0; - child->prevChild = 0; + engine = 0; + parent = 0; +} - child = next; - } - childContexts = 0; +void QDeclarativeContextData::destroy() +{ + if (linkedContext) + linkedContext->destroy(); + + if (engine) invalidate(); QDeclarativeAbstractExpression *expression = expressions; while (expression) { @@ -573,19 +585,6 @@ void QDeclarativeContextData::setParent(QDeclarativeContextData *p) } } -void QDeclarativeContextData::invalidateEngines() -{ - if (!engine) - return; - engine = 0; - - QDeclarativeContextData *child = childContexts; - while (child) { - child->invalidateEngines(); - child = child->nextChild; - } -} - /* Refreshes all expressions that could possibly depend on this context. Refreshing flushes all context-tree dependent caches in the expressions, and should occur every time the context tree diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 5d26e7e..77a6d94 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -106,6 +106,7 @@ public: static QObject *context_at(QDeclarativeListProperty *, int); }; +class QDeclarativeComponentAttached; class QDeclarativeGuardedContextData; class QDeclarativeContextData { @@ -113,6 +114,7 @@ public: QDeclarativeContextData(); QDeclarativeContextData(QDeclarativeContext *); void destroy(); + void invalidate(); inline bool isValid() const { return engine && (!isInternal || !contextObject || !QObjectPrivate::get(contextObject)->wasDeleted); @@ -123,7 +125,6 @@ public: QDeclarativeEngine *engine; void setParent(QDeclarativeContextData *); - void invalidateEngines(); void refreshExpressions(); void addObject(QObject *); @@ -194,6 +195,10 @@ public: // Linked contexts. this owns linkedContext. QDeclarativeContextData *linkedContext; + // Linked list of uses of the Component attached property in this + // context + QDeclarativeComponentAttached *componentAttached; + QString findObjectId(const QObject *obj) const; static QDeclarativeContextData *get(QDeclarativeContext *context) { diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index a478bf5..1deadb2 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -155,7 +155,7 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) : captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false), contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), - scriptEngine(this), workerScriptEngine(0), componentAttacheds(0), inBeginCreate(false), + scriptEngine(this), workerScriptEngine(0), componentAttached(0), inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0), typeManager(e), uniqueId(1) { @@ -350,8 +350,13 @@ typedef QMap StringStringMap; Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri -void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *) +void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o) { + QObjectPrivate *p = QObjectPrivate::get(o); + Q_ASSERT(p->declarativeData); + QDeclarativeData *d = static_cast(p->declarativeData); + if (d->ownContext) + d->context->destroy(); } void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o) @@ -855,7 +860,7 @@ void QDeclarativeData::destroyed(QObject *object) if (propertyCache) propertyCache->release(); - if (ownContext) + if (ownContext && context) context->destroy(); QDeclarativeGuard *guard = guards; diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 7766ad6..b3bba43 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -215,7 +215,7 @@ public: QList > bindValues; QList > parserStatus; - QDeclarativeComponentAttached *componentAttacheds; + QDeclarativeComponentAttached *componentAttached; bool inBeginCreate; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 9cb2416..afd0d84 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -286,7 +286,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name QString signalName = terminal.mid(2); signalName[0] = signalName.at(0).toLower(); - QMetaMethod method = QDeclarativeCompiler::findSignalByName(currentObject->metaObject(), signalName.toLatin1().constData()); + QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName.toLatin1().constData()); if (method.signature()) { object = currentObject; core.load(method); @@ -1353,4 +1353,36 @@ bool QDeclarativePropertyPrivate::canConvert(const QMetaObject *from, const QMet return false; } +/*! + Return the signal corresponding to \a name +*/ +QMetaMethod QDeclarativePropertyPrivate::findSignalByName(const QMetaObject *mo, const QByteArray &name) +{ + Q_ASSERT(mo); + int methods = mo->methodCount(); + for (int ii = methods - 1; ii >= 2; --ii) { // >= 2 to block the destroyed signal + QMetaMethod method = mo->method(ii); + QByteArray methodName = method.signature(); + int idx = methodName.indexOf('('); + methodName = methodName.left(idx); + + if (methodName == name) + return method; + } + + // If no signal is found, but the signal is of the form "onBlahChanged", + // return the notify signal for the property "Blah" + if (name.endsWith("Changed")) { + QByteArray propName = name.mid(0, name.length() - 7); + int propIdx = mo->indexOfProperty(propName.constData()); + if (propIdx >= 0) { + QMetaProperty prop = mo->property(propIdx); + if (prop.hasNotifySignal()) + return prop.notifySignal(); + } + } + + return QMetaMethod(); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index 420a1ba..8522561 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -96,8 +96,6 @@ public: void initProperty(QObject *obj, const QString &name); void initDefault(QObject *obj); - QMetaMethod findSignal(QObject *, const QString &); - bool isValueType() const; int propertyType() const; QDeclarativeProperty::PropertyTypeCategory propertyTypeCategory() const; @@ -134,6 +132,7 @@ public: static bool write(const QDeclarativeProperty &that, const QVariant &, WriteFlags); static int valueTypeCoreIndex(const QDeclarativeProperty &that); static int bindingIndex(const QDeclarativeProperty &that); + static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyPrivate::WriteFlags) diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 4b4b142..888945b 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -147,7 +147,7 @@ QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObj } int methodCount = metaObject->methodCount(); - for (int ii = methodCount - 1; ii >= 0; --ii) { + for (int ii = methodCount - 1; ii >= 2; --ii) { // >=2 to block the destroyed signal QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; @@ -216,7 +216,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb } int methodCount = metaObject->methodCount(); - int methodOffset = metaObject->methodOffset(); + int methodOffset = qMax(2, metaObject->methodOffset()); // 2 to block the destroyed signal for (int ii = methodOffset; ii < methodCount; ++ii) { QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) @@ -289,7 +289,7 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb } int methodCount = metaObject->methodCount(); - for (int ii = methodCount - 1; ii >= 0; --ii) { + for (int ii = methodCount - 1; ii >= 2; --ii) { // >=2 to block the destroyed signal QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; diff --git a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp index 35cffdc..851460f 100644 --- a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp +++ b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp @@ -172,8 +172,8 @@ void tst_qdeclarativecontext::parentContext() delete ctxt2; ctxt2 = 0; QCOMPARE(ctxt->parentContext(), engine->rootContext()); - QCOMPARE(ctxt3->parentContext(), ctxt2); - QCOMPARE(ctxt4->parentContext(), ctxt2); + QCOMPARE(ctxt3->parentContext(), (QDeclarativeContext *)0); + QCOMPARE(ctxt4->parentContext(), (QDeclarativeContext *)0); QCOMPARE(ctxt5->parentContext(), ctxt); QCOMPARE(ctxt6->parentContext(), engine->rootContext()); QCOMPARE(ctxt7->parentContext(), engine->rootContext()); @@ -181,9 +181,9 @@ void tst_qdeclarativecontext::parentContext() delete engine; engine = 0; QCOMPARE(ctxt->parentContext(), (QDeclarativeContext *)0); - QCOMPARE(ctxt3->parentContext(), ctxt2); - QCOMPARE(ctxt4->parentContext(), ctxt2); - QCOMPARE(ctxt5->parentContext(), ctxt); + QCOMPARE(ctxt3->parentContext(), (QDeclarativeContext *)0); + QCOMPARE(ctxt4->parentContext(), (QDeclarativeContext *)0); + QCOMPARE(ctxt5->parentContext(), (QDeclarativeContext *)0); QCOMPARE(ctxt6->parentContext(), (QDeclarativeContext *)0); QCOMPARE(ctxt7->parentContext(), (QDeclarativeContext *)0); diff --git a/tests/auto/declarative/qdeclarativelanguage/data/OnDestructionType.qml b/tests/auto/declarative/qdeclarativelanguage/data/OnDestructionType.qml new file mode 100644 index 0000000..e5a7cf8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/OnDestructionType.qml @@ -0,0 +1,8 @@ +import Test 1.0 +import Qt 4.6 + +MyQmlObject { + property int a: Math.max(10, 9) + property int b: 11 + Component.onDestruction: console.log("Destruction " + a + " " + b); +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.errors.txt new file mode 100644 index 0000000..3348494 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.errors.txt @@ -0,0 +1 @@ +4:5:Cannot assign to non-existent property "onDestroyed" diff --git a/tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.qml b/tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.qml new file mode 100644 index 0000000..4eab50a --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/destroyedSignal.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +QtObject { + onDestroyed: print("Hello World!") +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/onDestruction.qml b/tests/auto/declarative/qdeclarativelanguage/data/onDestruction.qml new file mode 100644 index 0000000..7ebae7b --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/onDestruction.qml @@ -0,0 +1,17 @@ +import Test 1.0 +import Qt 4.6 + +MyTypeObject { + // We set a and b to ensure that onCompleted is executed after bindings and + // constants have been assigned + property int a: Math.min(6, 7) + Component.onDestruction: console.log("Destruction " + a + " " + nestedObject.b) + + objectProperty: OnDestructionType { + qmlobjectProperty: MyQmlObject { + id: nestedObject + property int b: 10 + Component.onDestruction: console.log("Destruction " + a + " " + nestedObject.b) + } + } +} diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 7c327c2..8feab32 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -113,6 +113,7 @@ private slots: void i18n(); void i18n_data(); void onCompleted(); + void onDestruction(); void scriptString(); void defaultPropertyListOrder(); void declaredPropertyValues(); @@ -329,6 +330,7 @@ void tst_qdeclarativelanguage::errors_data() QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false; QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false; QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false; + QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false; } @@ -1049,6 +1051,20 @@ void tst_qdeclarativelanguage::onCompleted() QVERIFY(object != 0); } +// Check that the Component::onDestruction attached property works +void tst_qdeclarativelanguage::onDestruction() +{ + QDeclarativeComponent component(&engine, TEST_FILE("onDestruction.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11"); + delete object; +} + // Check that assignments to QDeclarativeScriptString properties work void tst_qdeclarativelanguage::scriptString() { -- cgit v0.12