From 8f60083c0ea560de3dedd5dfd087a06212594fc9 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 17 Aug 2009 17:40:03 +1000 Subject: More namespace improvements - Store and find QML version ranges efficiently - Require version for QmlType-from-string - Removed unused version-ignorant QmlType-from-string functions - Some attached properties now resolve (eg. tst_qmlparser) - Still no better: - interfaces not versioned - some attached properties still hard-codec to Qt --- src/declarative/qml/qmlcompiler.cpp | 15 ++- src/declarative/qml/qmlcompiler_p.h | 1 + src/declarative/qml/qmlcompositetypemanager.cpp | 4 +- src/declarative/qml/qmldom.cpp | 2 +- src/declarative/qml/qmlengine.cpp | 34 ++--- src/declarative/qml/qmlengine_p.h | 2 +- src/declarative/qml/qmlmetaproperty.cpp | 10 +- src/declarative/qml/qmlmetatype.cpp | 158 ++++++------------------ src/declarative/qml/qmlmetatype.h | 17 +-- 9 files changed, 82 insertions(+), 161 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index caf78e8..dea41ab 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -576,6 +576,7 @@ bool QmlCompiler::compile(QmlEngine *engine, Q_ASSERT(root); this->engine = engine; + this->unit = unit; compileTree(root); if (!isError()) { @@ -1036,7 +1037,7 @@ bool QmlCompiler::buildSubObject(Object *obj, const BindingContext &ctxt) int QmlCompiler::componentTypeRef() { - QmlType *t = QmlMetaType::qmlType("Qt/4.6/Component"); + QmlType *t = QmlMetaType::qmlType("Qt/Component",4,6); for (int ii = output->types.count() - 1; ii >= 0; --ii) { if (output->types.at(ii).type == t) return ii; @@ -1148,7 +1149,9 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, COMPILE_EXCEPTION(prop, "Attached properties cannot be used here"); } - QmlType *type = QmlMetaType::qmlType("Qt/4.6/"+prop->name); // XXX Should not hard-code namespace + QmlType *type = 0; + QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name, &type, 0); + // 0: attached properties not supported in QML component files if (!type || !type->attachedPropertiesType()) COMPILE_EXCEPTION(prop, "Non-existant attached object"); @@ -1156,6 +1159,8 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, if (!prop->value) COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); + Q_ASSERT(type->attachedPropertiesFunction()); + prop->index = type->index(); prop->value->metatype = type->attachedPropertiesType(); } else { // Setup regular property data @@ -1428,10 +1433,8 @@ bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop, const BindingContext &ctxt) { Q_ASSERT(prop->value); - int id = QmlMetaType::attachedPropertiesFuncId(prop->name); - Q_ASSERT(id != -1); // This is checked in compileProperty() + Q_ASSERT(prop->index != -1); // This is set in buildProperty() - prop->index = id; obj->addAttachedProperty(prop); COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr())); @@ -1715,7 +1718,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, QmlParser::Object *root = v->object; QmlParser::Object *component = new QmlParser::Object; component->type = componentTypeRef(); - component->typeName = "Qt/4.6/Component"; + component->typeName = "Qt/Component"; component->metatype = &QmlComponent::staticMetaObject; component->location = root->location; QmlParser::Value *componentValue = new QmlParser::Value; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 4f56169..58279c4 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -267,6 +267,7 @@ private: QList exceptions; QmlCompiledData *output; QmlEngine *engine; + QmlCompositeTypeData *unit; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index b0a8642..97391e6 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -247,7 +247,9 @@ void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit, unit->errors << unit->data.errors(); } else { foreach (QmlScriptParser::Import imp, unit->data.imports()) { - if (!QmlEnginePrivate::get(engine)->addToImport(&unit->imports, imp.uri, imp.qualifier, imp.version, imp.type)) { + int dot = imp.version.indexOf(QLatin1Char('.')); + if (dot < 0) dot = imp.version.length(); + if (!QmlEnginePrivate::get(engine)->addToImport(&unit->imports, imp.uri, imp.qualifier, imp.version.left(dot).toInt(), imp.version.mid(dot+1).toInt(), imp.type)) { QmlError error; error.setUrl(url); error.setDescription(tr("Import %1 unavailable").arg(imp.uri)); diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index c6b7192..cdd5eef 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -967,7 +967,7 @@ QByteArray QmlDomObject::customTypeData() const bool QmlDomObject::isComponent() const { return d->isVirtualComponent || - (d->object && d->object->typeName == "Qt/4.6/Component"); + (d->object && d->object->typeName == "Qt/Component"); } /*! diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 68f0833..6756642 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -1041,19 +1041,22 @@ void QmlObjectScriptClass::setProperty(QScriptValue &object, struct QmlEnginePrivate::ImportedNamespace { QStringList urls; - QStringList versions; + QList majversions; + QList minversions; QList isLibrary; QUrl find(const QString& type) const { for (int i=0; iurls.append(url); - s->versions.append(version); + s->majversions.append(vmaj); + s->minversions.append(vmin); s->isLibrary.append(importType == QmlScriptParser::Import::Library); return true; } @@ -1252,11 +1254,11 @@ void QmlEngine::addImportPath(const QString& path) The base URL must already have been set with Import::setBaseUrl(). */ -bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const QString& prefix, const QString& version, QmlScriptParser::Import::Type importType) const +bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const { - bool ok = imports->d->add(imports->base,uri,prefix,version,importType,fileImportPath); + bool ok = imports->d->add(imports->base,uri,prefix,vmaj,vmin,importType,fileImportPath); if (qmlImportTrace()) - qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << version << (importType==QmlScriptParser::Import::Library? "Library" : "File") << ": " << ok; + qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << vmaj << "." << vmin << (importType==QmlScriptParser::Import::Library? "Library" : "File") << ": " << ok; return ok; } @@ -1281,7 +1283,7 @@ bool QmlEnginePrivate::resolveType(const Imports& imports, const QByteArray& typ } if (type_return) { QmlType* t = imports.d->findBuiltin(type); - if (!t) t = QmlMetaType::qmlType(type); + if (!t) t = QmlMetaType::qmlType(type,0,0); // Try global namespace if (t) { if (type_return) *type_return = t; if (qmlImportTrace()) diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index d2e3ef4..aaf679f 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -196,7 +196,7 @@ public: QmlImportsPrivate *d; }; struct ImportedNamespace; - bool addToImport(Imports*, const QString& uri, const QString& prefix, const QString& version, QmlScriptParser::Import::Type type) const; + bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const; bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, ImportedNamespace** ns_return=0) const; void resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type, QmlType** type_return, QUrl* url_return ) const; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index d986077..c1736cb 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -218,9 +218,13 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (name.at(0).isUpper()) { // Attached property - attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1()); - if (attachedFunc != -1) - type = QmlMetaProperty::Property | QmlMetaProperty::Attached; + // XXX name should be resolved with QmlEngine::resolveType(), not like this! + QmlType *t = QmlMetaType::qmlType("Qt/"+name.toLatin1(),-1,-1); + if (t && t->attachedPropertiesFunction()) { + attachedFunc = t->index(); + if (attachedFunc != -1) + type = QmlMetaProperty::Property | QmlMetaProperty::Attached; + } return; } else if (name.count() >= 3 && diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 512650f..5ebe970 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -110,6 +110,9 @@ public: bool m_isInterface : 1; const char *m_iid; QByteArray m_name; + int m_version_maj; + int m_version_min_from; + int m_version_min_to; int m_typeId; int m_listId; int m_qmlListId; QmlPrivate::Func m_opFunc; const QMetaObject *m_baseMetaObject; @@ -146,10 +149,14 @@ QmlType::QmlType(int type, int listType, int qmlListType, d->m_opFunc = opFunc; d->m_index = index; d->m_isSetup = true; + d->m_version_maj = 0; + d->m_version_min_from = 0; + d->m_version_min_to = 0; } QmlType::QmlType(int type, int listType, int qmlListType, QmlPrivate::Func opFunc, const char *qmlName, + int version_maj, int version_min_from, int version_min_to, const QMetaObject *metaObject, QmlAttachedPropertiesFunc attachedPropertiesFunc, const QMetaObject *attachedType, @@ -159,6 +166,9 @@ QmlType::QmlType(int type, int listType, int qmlListType, : d(new QmlTypePrivate) { d->m_name = qmlName; + d->m_version_maj = version_maj; + d->m_version_min_from = version_min_from; + d->m_version_min_to = version_min_to; d->m_typeId = type; d->m_listId = listType; d->m_qmlListId = qmlListType; @@ -180,6 +190,11 @@ QmlType::~QmlType() delete d; } +bool QmlType::availableInVersion(int vmajor, int vminor) const +{ + return vmajor == d->m_version_maj && vminor >= d->m_version_min_from && vminor <= d->m_version_min_to; +} + void QmlTypePrivate::init() const { if (m_isSetup) return; @@ -401,6 +416,7 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, data->idToType.insert(type->typeId(), type); data->idToType.insert(type->qListTypeId(), type); data->idToType.insert(type->qmlListTypeId(), type); + // XXX No insertMulti, so no multi-version interfaces? if (!type->qmlTypeName().isEmpty()) data->nameToType.insert(type->qmlTypeName(), type); @@ -422,48 +438,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) { - QByteArray version; - if (uri && (version_maj || version_min_from || version_min_to)) { - if (version_min_from != version_min_to) { - int r=-1; - for (int min=version_min_from; min<=version_min_to; ++min) { - int e = registerType(id,func,uri,version_maj,min,min,cname,mo,attach,attachMo,pStatus,object,extFunc,extmo,parser); - if (e<0) return -1; - if (r<0) r = e; - } - return r; // returns index of FIRST version of type (not currently used anywhere though) - } - version = QByteArray::number(version_maj) + '.' + QByteArray::number(version_min_from); - } else { - // No URI? No version! - Q_ASSERT(!version_maj && !version_min_from && !version_min_to); - } - return registerType(id,func,uri,version,cname,mo,attach,attachMo,pStatus,object,extFunc,extmo,parser); -} - - -int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, - const char *uri, const char *version, const char *cname, - const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, - int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) -{ Q_UNUSED(object); - QByteArray name; - if (uri) { - // Convert to path - name = uri; - name.replace('.','/'); - if (version) { - name += '/'; - name += version; - } - name += '/'; - name += cname; - } else { - // No URI? No version! - name = cname; - Q_ASSERT(!version); - } if (cname) { for (int ii = 0; cname[ii]; ++ii) { @@ -476,11 +451,16 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun QWriteLocker lock(metaTypeDataLock()); QmlMetaTypeData *data = metaTypeData(); - int index = data->types.count(); + QByteArray name = uri; + if (uri) + name += "/"; + name += cname; + name.replace('.','/'); + QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, - func, name, mo, attach, attachMo, pStatus, extFunc, + func, name, version_maj, version_min_from, version_min_to, mo, attach, attachMo, pStatus, extFunc, extmo, index, parser); data->types.append(type); @@ -489,7 +469,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun data->idToType.insert(type->qmlListTypeId(), type); if (!type->qmlTypeName().isEmpty()) - data->nameToType.insert(type->qmlTypeName(), type); + data->nameToType.insertMulti(type->qmlTypeName(), type); data->metaObjectToType.insert(type->baseMetaObject(), type); @@ -503,7 +483,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun data->qmllists.setBit(id.qmlListId, true); data->lists.setBit(id.listId, true); - return index; // Note: multi-version call only uses first. + return index; } int QmlMetaType::qmlParserStatusCast(int userType) @@ -587,19 +567,6 @@ bool QmlMetaType::append(const QVariant &list, const QVariant &item) } } -QObject *QmlMetaType::create(const QByteArray &name) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - lock.unlock(); - - QmlType *type = data->nameToType.value(name); - if (type) - return type->create(); - else - return 0; -} - QVariant QmlMetaType::fromObject(QObject *obj, int typeId) { QReadLocker lock(metaTypeDataLock()); @@ -624,18 +591,6 @@ const QMetaObject *QmlMetaType::rawMetaObjectForType(int id) return 0; } -const QMetaObject *QmlMetaType::rawMetaObjectForType(const QByteArray &name) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - - QmlType *type = data->nameToType.value(name); - if (type) - return type->baseMetaObject(); - else - return 0; -} - const QMetaObject *QmlMetaType::metaObjectForType(int id) { QReadLocker lock(metaTypeDataLock()); @@ -649,43 +604,6 @@ const QMetaObject *QmlMetaType::metaObjectForType(int id) return 0; } -const QMetaObject *QmlMetaType::metaObjectForType(const QByteArray &name) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->nameToType.value(name); - lock.unlock(); - - if (type) - return type->metaObject(); - else - return 0; -} - -int QmlMetaType::type(const QByteArray &name) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - - QmlType *type = data->nameToType.value(name); - if (type) - return type->typeId(); - else - return 0; -} - -int QmlMetaType::attachedPropertiesFuncId(const QByteArray &name) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - - QmlType *type = data->nameToType.value("Qt/4.6/"+name); // XXX Should not hard-code namespace - if (type && type->attachedPropertiesFunction()) - return type->index(); - else - return -1; -} - int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo) { QReadLocker lock(metaTypeDataLock()); @@ -707,18 +625,6 @@ QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id) return data->types.at(id)->attachedPropertiesFunction(); } -QmlAttachedPropertiesFunc -QmlMetaType::attachedPropertiesFunc(const QByteArray &name) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->nameToType.value(name); - if (type) - return type->attachedPropertiesFunction(); - else - return 0; -} - QMetaProperty QmlMetaType::defaultProperty(const QMetaObject *metaObject) { int idx = metaObject->indexOfClassInfo("DefaultProperty"); @@ -939,12 +845,22 @@ QmlMetaType::StringConverter QmlMetaType::customStringConverter(int type) return data->stringConverters.value(type); } -QmlType *QmlMetaType::qmlType(const QByteArray &name) +/*! + Returns the type (if any) of URI-qualified named \a name in version specified + by \a version_major and \a version_minor. +*/ +QmlType *QmlMetaType::qmlType(const QByteArray &name, int version_major, int version_minor) { QReadLocker lock(metaTypeDataLock()); QmlMetaTypeData *data = metaTypeData(); - return data->nameToType.value(name); + QList types = data->nameToType.values(name); + foreach (QmlType *t, types) { + // XXX version_major<0 just a kludge for QmlMetaPropertyPrivate::initProperty + if (version_major<0 || t->availableInVersion(version_major,version_minor)) + return t; + } + return 0; } QmlType *QmlMetaType::qmlType(const QMetaObject *metaObject) diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 9cbf7f3..94029ce 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -59,7 +59,6 @@ class QmlCustomParser; class Q_DECLARATIVE_EXPORT QmlMetaType { public: - static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, const char *version, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *); @@ -67,7 +66,7 @@ public: static QList qmlTypeNames(); - static QmlType *qmlType(const QByteArray &); + static QmlType *qmlType(const QByteArray &, int, int); static QmlType *qmlType(const QMetaObject *); static QMetaProperty defaultProperty(const QMetaObject *); @@ -79,20 +78,13 @@ public: static QObject *toQObject(const QVariant &); static int qmlParserStatusCast(int); static int listType(int); - static int type(const QByteArray &); - static int type(const QString &); static bool clear(const QVariant &); static bool append(const QVariant &, const QVariant &); static QVariant fromObject(QObject *, int type); - static QObject *create(const QByteArray &); - static const QMetaObject *rawMetaObjectForType(const QByteArray &); static const QMetaObject *rawMetaObjectForType(int); - static const QMetaObject *metaObjectForType(const QByteArray &); static const QMetaObject *metaObjectForType(int); - static int attachedPropertiesFuncId(const QByteArray &); static int attachedPropertiesFuncId(const QMetaObject *); static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int); - static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &); enum TypeCategory { Unknown, Object, List, QmlList }; static TypeCategory typeCategory(int); @@ -119,6 +111,7 @@ class Q_DECLARATIVE_EXPORT QmlType public: QByteArray typeName() const; QByteArray qmlTypeName() const; + bool availableInVersion(int vmajor, int vminor) const; QByteArray hash() const; @@ -151,7 +144,7 @@ private: friend class QmlMetaType; friend class QmlTypePrivate; QmlType(int, int, int, QmlPrivate::Func, const char *, int); - QmlType(int, int, int, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); + QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); ~QmlType(); QmlTypePrivate *d; @@ -167,7 +160,7 @@ int qmlRegisterType(const char *typeName) qRegisterMetaType(QByteArray("QmlList<" + name + "*>*").constData()) }; - return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op, 0, 0, 0, + return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op, 0, 0, 0, 0, 0, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc(), QmlPrivate::attachedPropertiesMetaObject(), @@ -215,7 +208,7 @@ int qmlRegisterExtendedType(const char *typeName) attachedMo = QmlPrivate::attachedPropertiesMetaObject(); } - return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op, 0, 0, 0, + return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op, 0, 0, 0, 0, 0, &T::staticMetaObject, attached, attachedMo, QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), -- cgit v0.12