From 4d3a64c5e65a781acb4acf4ba641456da28bd1e4 Mon Sep 17 00:00:00 2001 From: Alan Alpert <416365416c@gmail.com> Date: Sun, 16 Dec 2012 21:24:14 -0800 Subject: Add Composite Types to QQmlType When a composite type is loaded from a QML file, it now generates a QQmlType entry in QQmlMetaTypeData. Change-Id: I9b127dff7955456aacb25138fa6ea8efb7bb9221 Reviewed-by: Christopher Adams Reviewed-by: Alan Alpert --- src/qml/qml/qqmlimport.cpp | 107 +++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 42 deletions(-) (limited to 'src/qml/qml/qqmlimport.cpp') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 52d07b23ec..95b59f93f4 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -124,6 +124,39 @@ bool isPathAbsolute(const QString &path) #endif } +// If the type does not already exist as a file import, add the type and return the new type +QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName, QList *errors) +{ + QUrl url(urlString); + QQmlType *ret = QQmlMetaType::qmlType(url); + if (!ret) { //QQmlType not yet existing for composite type + int dot = typeName.indexOf(QLatin1Char('.')); + QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1); + + //XXX: The constData of the string ref is pointing somewhere unsafe in qmlregister, so we need to create a temporary copy + QByteArray buf(unqualifiedtype.toUtf8().constData()); + + QQmlPrivate::RegisterCompositeType reg = { + url, + "", //Empty URI indicates loaded via file imports + -1, + -1, + buf.constData() + }; + ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, ®)); + } + if (!ret) {//Usually when a type name is "found" but invalid + //qDebug() << ret << urlString << QQmlMetaType::qmlType(url); + if (!errors) // Cannot list errors properly, just quit + qFatal(QQmlMetaType::typeRegistrationFailures().join('\n').toLatin1().constData()); + QQmlError error; + error.setDescription(QQmlMetaType::typeRegistrationFailures().join('\n')); + errors->prepend(error); + } + return ret; + +} + } typedef QMap StringStringMap; @@ -150,8 +183,7 @@ public: static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin); bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, - QQmlType** type_return, QString* url_return, + int *vmajor, int *vminor, QQmlType** type_return, QString *base = 0, bool *typeRecursionDetected = 0) const; }; QList imports; @@ -159,8 +191,7 @@ public: Import *findImport(const QString &uri); bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, - int *vmajor, int *vminor, - QQmlType** type_return, QString* url_return, + int *vmajor, int *vminor, QQmlType** type_return, QString *base = 0, QList *errors = 0); // Prefix when used as a qualified import. Otherwise empty. @@ -194,8 +225,7 @@ public: QList *errors); bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, - QQmlType** type_return, QString* url_return, - QList *errors); + QQmlType** type_return, QList *errors); QUrl baseUrl; QString base; @@ -379,9 +409,8 @@ QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, The given (namespace qualified) \a type is resolved to either \list - \li a QQmlImportNamespace stored at \a ns_return, - \li a QQmlType stored at \a type_return, or - \li a component located at \a url_return. + \li a QQmlImportNamespace stored at \a ns_return, or + \li a QQmlType stored at \a type_return, \endlist If any return pointer is 0, the corresponding search is not done. @@ -389,7 +418,7 @@ QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, \sa addFileImport(), addLibraryImport */ bool QQmlImports::resolveType(const QHashedStringRef &type, - QQmlType** type_return, QString* url_return, int *vmaj, int *vmin, + QQmlType** type_return, int *vmaj, int *vmin, QQmlImportNamespace** ns_return, QList *errors) const { QQmlImportNamespace* ns = d->findQualifiedNamespace(type); @@ -398,19 +427,16 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, *ns_return = ns; return true; } - if (type_return || url_return) { - if (d->resolveType(type,vmaj,vmin,type_return,url_return, errors)) { + if (type_return) { + if (d->resolveType(type,vmaj,vmin,type_return, errors)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ << ')' << "::resolveType: " << type.toString() << " => " - if (type_return && *type_return && url_return && !url_return->isEmpty()) - RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << *url_return << " TYPE/URL"; - if (type_return && *type_return) + if (type_return && *type_return && (*type_return)->isComposite()) + RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << (*type_return)->sourceUrl() << " TYPE/URL"; + else if (type_return && *type_return) RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << " TYPE"; - if (url_return && !url_return->isEmpty()) - RESOLVE_TYPE_DEBUG << *url_return << " URL"; - #undef RESOLVE_TYPE_DEBUG } return true; @@ -469,23 +495,21 @@ QQmlDirScripts QQmlImportNamespace::Import::getVersionedScripts(const QQmlDirScr \internal Searching \e only in the namespace \a ns (previously returned in a call to - resolveType(), \a type is found and returned to either - a QQmlType stored at \a type_return, or - a component located at \a url_return. + resolveType(), \a type is found and returned to + a QQmlType stored at \a type_return. If the type is from a QML file, the returned + type will be a CompositeType. - If either return pointer is 0, the corresponding search is not done. + If the return pointer is 0, the corresponding search is not done. */ bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &type, - QQmlType** type_return, QString* url_return, - int *vmaj, int *vmin) const + QQmlType** type_return, int *vmaj, int *vmin) const { - return ns->resolveType(d->typeLoader,type,vmaj,vmin,type_return,url_return); + return ns->resolveType(d->typeLoader,type,vmaj,vmin,type_return); } bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType** type_return, QString* url_return, - QString *base, bool *typeRecursionDetected) const + QQmlType** type_return, QString *base, bool *typeRecursionDetected) const { if (majversion >= 0 && minversion >= 0) { QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion); @@ -530,9 +554,9 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, } if (candidate != end) { - if (url_return) - *url_return = componentUrl; - return true; + if (type_return) + *type_return = getTypeForUrl(componentUrl, type, 0); + return (*type_return != 0); } } else if (!isLibrary) { QString qmlUrl = url + QString::fromRawData(type.constData(), type.length()) + dotqml_string; @@ -550,9 +574,9 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, if (typeRecursionDetected) *typeRecursionDetected = true; } else { - if (url_return) - *url_return = qmlUrl; - return true; + if (type_return) + *type_return = getTypeForUrl(qmlUrl, type, 0); + return (*type_return) != 0; } } } @@ -561,8 +585,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, } bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType** type_return, QString* url_return, - QList *errors) + QQmlType** type_return, QList *errors) { QQmlImportNamespace *s = 0; int dot = type.indexOf(Dot); @@ -591,12 +614,12 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, } QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1); if (s) { - if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors)) + if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors)) return true; - if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && url_return && s != &unqualifiedset) { + if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) { // qualified, and only 1 url - *url_return = resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")); - return true; + *type_return = getTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, errors); + return (*type_return != 0); } } @@ -615,18 +638,18 @@ QQmlImportNamespace::Import *QQmlImportNamespace::findImport(const QString &uri) bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType** type_return, - QString* url_return, QString *base, QList *errors) + QString *base, QList *errors) { bool typeRecursionDetected = false; for (int i=0; iresolveType(typeLoader, type, vmajor, vminor, type_return, url_return, + if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base, &typeRecursionDetected)) { if (qmlCheckTypes()) { // check for type clashes for (int j = i+1; jresolveType(typeLoader, type, vmajor, vminor, 0, 0, base)) { + if (import2->resolveType(typeLoader, type, vmajor, vminor, 0, base)) { if (errors) { QString u1 = import->url; QString u2 = import2->url; -- cgit v1.2.3