diff options
-rw-r--r-- | src/declarative/qml/qml.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 54 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmldeclarativedata_p.h | 94 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 41 | ||||
-rw-r--r-- | src/declarative/qml/qmlinstruction_p.h | 8 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 13 |
7 files changed, 182 insertions, 30 deletions
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h index 370bb58..51ca612 100644 --- a/src/declarative/qml/qml.h +++ b/src/declarative/qml/qml.h @@ -90,6 +90,7 @@ QT_MODULE(Declarative) class QmlContext; class QmlEngine; +Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *); Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *); Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *); Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index d29ac1f..2a3cc8d 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -621,13 +621,19 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt) output->types.at(obj->type).type->customParser() != 0; QList<QmlCustomParserProperty> customProps; + QStringList deferred = deferredProperties(obj); + QList<Property *> deferredProps; + // Compile all explicit properties specified foreach(Property *prop, obj->properties) { if (isCustomParser) { // Custom parser types don't support signal properties if (testProperty(prop, obj)) { - COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); + if (deferred.contains(prop->name)) + deferredProps << prop; + else + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } else { customProps << QmlCustomParserNodePrivate::fromProperty(prop); } @@ -635,7 +641,10 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt) if (isSignalPropertyName(prop->name)) { COMPILE_CHECK(compileSignal(prop,obj)); } else { - COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); + if (deferred.contains(prop->name)) + deferredProps << prop; + else + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } } @@ -647,12 +656,20 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt) if (isCustomParser) { if (testProperty(prop, obj)) { - COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); + QMetaProperty p = deferred.isEmpty()?QMetaProperty():QmlMetaType::defaultProperty(obj->metaObject()); + if (deferred.contains(p.name())) + deferredProps << prop; + else + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } else { customProps << QmlCustomParserNodePrivate::fromProperty(prop); } } else { - COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); + QMetaProperty p = deferred.isEmpty()?QMetaProperty():QmlMetaType::defaultProperty(obj->metaObject()); + if (deferred.contains(p.name())) + deferredProps << prop; + else + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); } } @@ -670,6 +687,22 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt) output->indexForByteArray(customData); } + // Build the deferred block (### Need to check for presence of "id") + if (!deferredProps.isEmpty()) { + QmlInstruction defer; + defer.type = QmlInstruction::Defer; + defer.line = 0; + int deferIdx = output->bytecode.count(); + output->bytecode << defer; + + foreach (Property *prop, deferredProps) { + COMPILE_CHECK(compileProperty(prop, obj, objCtxt)); + } + + output->bytecode[deferIdx].defer.deferCount = + output->bytecode.count() - deferIdx - 1; + } + // If the type support the QmlParserStatusInterface we need to invoke // classComplete() if (parserStatusCast != -1) { @@ -1634,6 +1667,19 @@ bool QmlCompiler::canConvert(int convertType, QmlParser::Object *object) return false; } +QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj) +{ + const QMetaObject *mo = obj->metatype; + + int idx = mo->indexOfClassInfo("DeferredPropertyNames"); + if (idx == -1) + return QStringList(); + + QMetaClassInfo classInfo = mo->classInfo(idx); + QStringList rv = QString(QLatin1String(classInfo.value())).split(','); + return rv; +} + QmlCompiledData::QmlCompiledData() { } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 3b1a496..2559b14 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -180,6 +180,7 @@ private: void finalizeBinding(const BindingReference &); bool canConvert(int, QmlParser::Object *); + QStringList deferredProperties(QmlParser::Object *); struct IdReference { QString id; diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index fb7a015..b8d3cf4 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -52,20 +52,108 @@ public: QmlSimpleDeclarativeData() : flags(0), context(0) {} virtual void destroyed(QObject *); - enum Flag { Extended = 0x00000001 }; + enum Flag { Instance = 0x00000001, Extended = 0x00000002 }; quint32 flags; QmlContext *context; + + static inline QmlSimpleDeclarativeData *get(QObject *object, + bool create = false); }; -class QmlExtendedDeclarativeData : public QmlSimpleDeclarativeData +class QmlCompiledComponent; +class QmlInstanceDeclarativeData : public QmlSimpleDeclarativeData { public: - QmlExtendedDeclarativeData() { flags = Extended; } + QmlInstanceDeclarativeData() { flags |= Instance; } virtual void destroyed(QObject *); + + QmlCompiledComponent *deferredComponent; + unsigned int deferredIdx; + + static inline QmlInstanceDeclarativeData *get(QObject *object, + bool create = false); +}; + +class QmlExtendedDeclarativeData : public QmlInstanceDeclarativeData +{ +public: + QmlExtendedDeclarativeData() { flags |= Extended; } + QHash<int, QObject *> attachedProperties; + + static inline QmlExtendedDeclarativeData *get(QObject *object, + bool create = false); }; +QmlSimpleDeclarativeData * +QmlSimpleDeclarativeData::get(QObject *object, bool create) +{ + QObjectPrivate *priv = QObjectPrivate::get(object); + + if (create && !priv->declarativeData) + priv->declarativeData = new QmlInstanceDeclarativeData; + + return static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); +} + +QmlInstanceDeclarativeData * +QmlInstanceDeclarativeData::get(QObject *object, bool create) +{ + QObjectPrivate *priv = QObjectPrivate::get(object); + + QmlSimpleDeclarativeData *simple = + static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); + + if (simple && (simple->flags & Instance)) { + return static_cast<QmlInstanceDeclarativeData *>(simple); + } else if (create && simple) { + QmlInstanceDeclarativeData *rv = new QmlInstanceDeclarativeData; + rv->context = simple->context; + simple->destroyed(object); + priv->declarativeData = rv; + return rv; + } else if (create) { + QmlInstanceDeclarativeData *rv = new QmlInstanceDeclarativeData; + priv->declarativeData = rv; + return rv; + } + return 0; +} + +QmlExtendedDeclarativeData * +QmlExtendedDeclarativeData::get(QObject *object, bool create) +{ + QObjectPrivate *priv = QObjectPrivate::get(object); + + QmlSimpleDeclarativeData *simple = + static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); + + if (simple && (simple->flags & Extended)) { + return static_cast<QmlExtendedDeclarativeData *>(simple); + } else if (create && simple) { + QmlExtendedDeclarativeData *rv = new QmlExtendedDeclarativeData; + rv->context = simple->context; + + if (simple->flags & Instance) { + QmlInstanceDeclarativeData *instance = + static_cast<QmlInstanceDeclarativeData *>(priv->declarativeData); + rv->deferredComponent = instance->deferredComponent; + rv->deferredIdx = instance->deferredIdx; + delete simple; + } else { + simple->destroyed(object); + } + priv->declarativeData = rv; + return rv; + } else if (create) { + QmlExtendedDeclarativeData *rv = new QmlExtendedDeclarativeData; + priv->declarativeData = rv; + return rv; + } + return 0; +} + QT_END_NAMESPACE #endif // QMLDECLARATIVEDATA_P_H diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 66781ce..edc76c2 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -706,6 +706,14 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) context->d_func()->contextObjects.append(object); } +void qmlExecuteDeferred(QObject *object) +{ + QmlInstanceDeclarativeData *data = QmlInstanceDeclarativeData::get(object); + + if (data) { + } +} + QmlContext *qmlContext(const QObject *obj) { return QmlEngine::contextForObject(obj); @@ -719,36 +727,21 @@ QmlEngine *qmlEngine(const QObject *obj) QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object) { - QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object)); - - - QmlSimpleDeclarativeData *data = static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); + QmlExtendedDeclarativeData *edata = + QmlExtendedDeclarativeData::get(const_cast<QObject *>(object), true); - QmlExtendedDeclarativeData *edata = (data && data->flags & QmlSimpleDeclarativeData::Extended)?static_cast<QmlExtendedDeclarativeData *>(data):0; - - if (edata) { - QObject *rv = edata->attachedProperties.value(id); - if (rv) - return rv; - } + QObject *rv = edata->attachedProperties.value(id); + if (rv) + return rv; QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id); if (!pf) return 0; - QObject *rv = pf(const_cast<QObject *>(object)); - - if (rv) { - if (!edata) { - - edata = new QmlExtendedDeclarativeData; - if (data) edata->context = data->context; - priv->declarativeData = edata; - - } + rv = pf(const_cast<QObject *>(object)); + if (rv) edata->attachedProperties.insert(id, rv); - } return rv; } @@ -759,9 +752,11 @@ void QmlSimpleDeclarativeData::destroyed(QObject *object) context->d_func()->contextObjects.removeAll(object); } -void QmlExtendedDeclarativeData::destroyed(QObject *object) +void QmlInstanceDeclarativeData::destroyed(QObject *object) { QmlSimpleDeclarativeData::destroyed(object); + if (deferredComponent) + deferredComponent->release(); delete this; } diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 0f1f697..e3b0dfe 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -139,6 +139,11 @@ public: PopFetchedObject, PopQList, + // + // Deferred creation + // + Defer, /* defer */ + // // Expression optimizations // @@ -270,6 +275,9 @@ public: int property; int object; } assignStackObject; + struct { + int deferCount; + } defer; }; void dump(QmlCompiledComponent *); diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 3a66c69..58972ef 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -44,6 +44,7 @@ #include <private/qmlboundsignal_p.h> #include <private/qmlstringconverters_p.h> #include "private/qmetaobjectbuilder_p.h" +#include "private/qmldeclarativedata_p.h" #include <qml.h> #include <private/qmlcustomparser_p.h> #include <qperformancelog.h> @@ -745,6 +746,18 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in } break; + case QmlInstruction::Defer: + { + QObject *target = stack.top(); + QmlInstanceDeclarativeData *data = + QmlInstanceDeclarativeData::get(target, true); + comp->addref(); + data->deferredComponent = comp; + data->deferredIdx = ii; + ii += instr.defer.deferCount; + } + break; + case QmlInstruction::PopFetchedObject: { stack.pop(); |