summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h3
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp131
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h1
-rw-r--r--src/declarative/qml/qmlengine.cpp65
-rw-r--r--src/declarative/qml/qmlengine_p.h2
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp3
6 files changed, 131 insertions, 74 deletions
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
index fa11137..ffcef4c 100644
--- a/src/declarative/qml/qmlcompositetypedata_p.h
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -69,7 +69,8 @@ public:
Invalid,
Complete,
Error,
- Waiting
+ Waiting,
+ WaitingResources
};
Status status;
enum ErrorType {
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index 3c76344..9444a22 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -352,18 +352,6 @@ void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
if (!unit->data.parse(data, url)) {
ok = false;
unit->errors << unit->data.errors();
- } else {
- foreach (QmlScriptParser::Import imp, unit->data.imports()) {
- 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));
- unit->errors << error;
- ok = false;
- }
- }
}
if (ok) {
@@ -400,25 +388,11 @@ void QmlCompositeTypeManager::doComplete(QmlCompositeTypeResource *resource)
void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
{
- if (unit->status != QmlCompositeTypeData::Waiting)
+ if (unit->status != QmlCompositeTypeData::Waiting
+ && unit->status != QmlCompositeTypeData::WaitingResources)
return;
int waiting = 0;
- for (int ii = 0; ii < unit->types.count(); ++ii) {
- QmlCompositeTypeData *u = unit->types.at(ii).unit;
-
- if (!u)
- continue;
-
- if (u->status == QmlCompositeTypeData::Error) {
- unit->status = QmlCompositeTypeData::Error;
- unit->errors = u->errors;
- doComplete(unit);
- return;
- } else if (u->status == QmlCompositeTypeData::Waiting) {
- waiting++;
- }
- }
for (int ii = 0; ii < unit->resources.count(); ++ii) {
QmlCompositeTypeResource *r = unit->resources.at(ii);
@@ -429,28 +403,84 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
unit->status = QmlCompositeTypeData::Error;
QmlError error;
error.setUrl(unit->imports.baseUrl());
- error.setDescription(QLatin1String("Resource ") + r->url +
- QLatin1String(" unavailable"));
+ error.setDescription(tr("Resource %1 unavailable").arg(r->url));
unit->errors << error;
doComplete(unit);
return;
- } else if (r->status == QmlCompositeTypeData::Waiting) {
+ } else if (r->status == QmlCompositeTypeResource::Waiting) {
waiting++;
}
}
+ if (waiting == 0) {
+ if (unit->status == QmlCompositeTypeData::WaitingResources) {
+ waiting += resolveTypes(unit);
+ if (unit->status != QmlCompositeTypeData::Error) {
+ if (waiting)
+ unit->status = QmlCompositeTypeData::Waiting;
+ } else {
+ return;
+ }
+ } else {
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData *u = unit->types.at(ii).unit;
+
+ if (!u)
+ continue;
+
+ if (u->status == QmlCompositeTypeData::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errors = u->errors;
+ doComplete(unit);
+ return;
+ } else if (u->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+ }
+ }
+
if (!waiting) {
unit->status = QmlCompositeTypeData::Complete;
doComplete(unit);
}
}
-// ### Check ref counting in here
-void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
+int QmlCompositeTypeManager::resolveTypes(QmlCompositeTypeData *unit)
{
- QList<QmlScriptParser::TypeReference*> types = unit->data.referencedTypes();
+ // not called until all resources are loaded (they include import URLs)
int waiting = 0;
+
+ foreach (QmlScriptParser::Import imp, unit->data.imports()) {
+ int dot = imp.version.indexOf(QLatin1Char('.'));
+ if (dot < 0) dot = imp.version.length();
+ QString qmldir;
+ if (imp.type == QmlScriptParser::Import::File) {
+ QUrl importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir")));
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ if (unit->resources.at(ii)->url == importUrl) {
+ qmldir = QString::fromUtf8(unit->resources.at(ii)->data);
+ break;
+ }
+ }
+ }
+ if (!QmlEnginePrivate::get(engine)->addToImport(
+ &unit->imports, qmldir, imp.uri, imp.qualifier, imp.version.left(dot).toInt(), imp.version.mid(dot+1).toInt(), imp.type))
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Import %1 unavailable").arg(imp.uri));
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ unit->errors << error;
+ doComplete(unit);
+ return 0;
+ }
+ }
+
+ QList<QmlScriptParser::TypeReference*> types = unit->data.referencedTypes();
+
for (int ii = 0; ii < types.count(); ++ii) {
QmlScriptParser::TypeReference *parserRef = types.at(ii);
QByteArray typeName = parserRef->name.toUtf8();
@@ -478,7 +508,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
unit->errorType = QmlCompositeTypeData::GeneralError;
unit->errors << error;
doComplete(unit);
- return;
+ return 0;
}
if (ref.type) {
@@ -521,12 +551,13 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
if (urlUnit->errorType != QmlCompositeTypeData::AccessError)
unit->errors << urlUnit->errors;
doComplete(unit);
- return;
+ return 0;
case QmlCompositeTypeData::Complete:
break;
case QmlCompositeTypeData::Waiting:
+ case QmlCompositeTypeData::WaitingResources:
unit->addref();
ref.unit->dependants << unit;
waiting++;
@@ -535,6 +566,13 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
unit->types << ref;
}
+ return waiting;
+}
+
+// ### Check ref counting in here
+void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
+{
+ int waiting = 0;
QList<QUrl> resourceList = unit->data.referencedResources();
for (int ii = 0; ii < resourceList.count(); ++ii) {
@@ -551,6 +589,9 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
loadResource(resource);
}
+ if (!url.toLocalFile().isEmpty() && url.path().endsWith("/qmldir") && resource->status==QmlCompositeTypeResource::Error)
+ continue; // ignore - can use filesystem dir instead
+
switch(resource->status) {
case QmlCompositeTypeResource::Invalid:
case QmlCompositeTypeResource::Error:
@@ -558,8 +599,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
{
QmlError error;
error.setUrl(unit->imports.baseUrl());
- error.setDescription(QLatin1String("Resource ") + resource->url +
- QLatin1String(" unavailable"));
+ error.setDescription(tr("Resource %1 unavailable").arg(resource->url));
unit->errors << error;
}
doComplete(unit);
@@ -579,11 +619,18 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
unit->resources << resource;
}
- if (waiting) {
- unit->status = QmlCompositeTypeData::Waiting;
+ if (waiting == 0) {
+ waiting += resolveTypes(unit);
+ if (unit->status != QmlCompositeTypeData::Error) {
+ if (!waiting) {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ } else {
+ unit->status = QmlCompositeTypeData::Waiting;
+ }
+ }
} else {
- unit->status = QmlCompositeTypeData::Complete;
- doComplete(unit);
+ unit->status = QmlCompositeTypeData::WaitingResources;
}
}
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
index 843a9cf..b6f84db 100644
--- a/src/declarative/qml/qmlcompositetypemanager_p.h
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -101,6 +101,7 @@ private:
void doComplete(QmlCompositeTypeData *);
void doComplete(QmlCompositeTypeResource *);
void checkComplete(QmlCompositeTypeData *);
+ int resolveTypes(QmlCompositeTypeData *);
QmlEngine *engine;
typedef QHash<QString, QmlCompositeTypeData *> Components;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 354114a..a3fb363 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -1027,6 +1027,7 @@ struct QmlEnginePrivate::ImportedNamespace {
QList<int> minversions;
QList<bool> isLibrary;
QList<bool> isBuiltin;
+ QList<QString> qmlDirContent;
bool find(const QByteArray& type, int *vmajor, int *vminor, QmlType** type_return, QUrl* url_return) const
{
@@ -1048,36 +1049,39 @@ struct QmlEnginePrivate::ImportedNamespace {
}
} else {
QUrl url = QUrl(urls.at(i) + QLatin1String("/") + QString::fromUtf8(type) + QLatin1String(".qml"));
- if (vmaj || vmin) {
+ QString qmldircontent = qmlDirContent.at(i);
+ if (vmaj || vmin || !qmldircontent.isEmpty()) {
// Check version file - XXX cache these in QmlEngine!
- QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir"))));
- if (qmldir.open(QIODevice::ReadOnly)) {
- do {
- QByteArray lineba = qmldir.readLine();
- if (lineba.at(0) == '#')
- continue;
- int space1 = lineba.indexOf(' ');
- if (qstrncmp(lineba,type,space1)==0) {
- // eg. 1.2-5
- QString line = QString::fromUtf8(lineba);
- space1 = line.indexOf(QLatin1Char(' ')); // refind in Unicode
- int space2 = space1 >=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1;
- QString mapversions = line.mid(space1+1,space2<0?line.length()-space1-2:space2-space1-1);
- int dot = mapversions.indexOf(QLatin1Char('.'));
- int dash = mapversions.indexOf(QLatin1Char('-'));
- int mapvmaj = mapversions.left(dot).toInt();
- if (mapvmaj==vmaj) {
- int mapvmin_from = (dash <= 0 ? mapversions.mid(dot+1) : mapversions.mid(dot+1,dash-dot-1)).toInt();
- int mapvmin_to = dash <= 0 ? mapvmin_from : mapversions.mid(dash+1).toInt();
- if (vmin >= mapvmin_from && vmin <= mapvmin_to) {
- QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-2);
- if (url_return)
- *url_return = url.resolved(mapfile.toString());
- return true;
- }
+ if (qmldircontent.isEmpty()) {
+ QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir"))));
+ if (qmldir.open(QIODevice::ReadOnly)) {
+ qmldircontent = QString::fromUtf8(qmldir.readAll());
+ }
+ }
+ QString typespace = QString::fromUtf8(type)+QLatin1Char(' ');
+ QStringList lines = qmldircontent.split(QLatin1Char('\n'));
+ foreach (QString line, lines) {
+ if (line.isEmpty() || line.at(0) == QLatin1Char('#'))
+ continue;
+ if (line.startsWith(typespace)) {
+ // eg. 1.2-5
+ int space1 = line.indexOf(QLatin1Char(' '));
+ int space2 = space1 >=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1;
+ QString mapversions = line.mid(space1+1,space2<0?line.length()-space1-1:space2-space1-1);
+ int dot = mapversions.indexOf(QLatin1Char('.'));
+ int dash = mapversions.indexOf(QLatin1Char('-'));
+ int mapvmaj = mapversions.left(dot).toInt();
+ if (mapvmaj==vmaj) {
+ int mapvmin_from = (dash <= 0 ? mapversions.mid(dot+1) : mapversions.mid(dot+1,dash-dot-1)).toInt();
+ int mapvmin_to = dash <= 0 ? mapvmin_from : mapversions.mid(dash+1).toInt();
+ if (vmin >= mapvmin_from && vmin <= mapvmin_to) {
+ QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-1);
+ if (url_return)
+ *url_return = url.resolved(mapfile.toString());
+ return true;
}
}
- } while (!qmldir.atEnd());
+ }
}
} else {
// XXX search non-files too! (eg. zip files, see QT-524)
@@ -1106,7 +1110,7 @@ public:
delete s;
}
- bool add(const QUrl& base, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType, const QStringList& importPath)
+ bool add(const QUrl& base, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType, const QStringList& importPath)
{
QmlEnginePrivate::ImportedNamespace *s;
if (prefix.isEmpty()) {
@@ -1142,6 +1146,7 @@ public:
s->minversions.prepend(vmin);
s->isLibrary.prepend(importType == QmlScriptParser::Import::Library);
s->isBuiltin.prepend(isbuiltin);
+ s->qmlDirContent.prepend(qmldircontent);
return true;
}
@@ -1366,9 +1371,9 @@ QString QmlEngine::offlineStoragePath() const
The base URL must already have been set with Import::setBaseUrl().
*/
-bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const
+bool QmlEnginePrivate::addToImport(Imports* imports, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const
{
- bool ok = imports->d->add(imports->d->base,uri,prefix,vmaj,vmin,importType,fileImportPath);
+ bool ok = imports->d->add(imports->d->base,qmldircontent,uri,prefix,vmaj,vmin,importType,fileImportPath);
if (qmlImportTrace())
qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << vmaj << "." << vmin << (importType==QmlScriptParser::Import::Library? "Library" : "File") << ": " << ok;
return ok;
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index a74854d..bd1cab2 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -223,7 +223,7 @@ public:
QmlImportsPrivate *d;
};
- bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const;
+ bool addToImport(Imports*, const QString& qmlDirContent,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,
int *version_major, int *version_minor,
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index fb84651..b61ffaa 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -424,6 +424,9 @@ bool ProcessAST::visit(AST::UiImport *node)
if (node->fileName) {
import.type = QmlScriptParser::Import::File;
uri = node->fileName->asString();
+ QUrl ref(uri);
+ ref.setPath(ref.path()+QLatin1String("/qmldir"));
+ _parser->_refUrls << ref;
} else {
import.type = QmlScriptParser::Import::Library;
uri = asString(node->importUri);