aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativeimport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativeimport.cpp')
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp208
1 files changed, 142 insertions, 66 deletions
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index e8d593fd1a..c5abe2c75d 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -83,7 +83,7 @@ public:
QDeclarativeType** type_return, QUrl* url_return,
QUrl *base = 0, bool *typeRecursionDetected = 0);
bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
- QUrl* url_return, QUrl *base = 0, QString *errorString = 0);
+ QUrl* url_return, QUrl *base = 0, QList<QDeclarativeError> *errors = 0);
};
class QDeclarativeImportsPrivate {
@@ -93,15 +93,15 @@ public:
bool importExtension(const QString &absoluteFilePath, const QString &uri,
QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components,
- QString *errorString);
+ QList<QDeclarativeError> *errors);
QString resolvedUri(const QString &dir_arg, QDeclarativeImportDatabase *database);
bool add(const QDeclarativeDirComponents &qmldircomponentsnetwork,
const QString& uri_arg, const QString& prefix,
int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType,
- QDeclarativeImportDatabase *database, QString *errorString);
+ QDeclarativeImportDatabase *database, QList<QDeclarativeError> *errors);
bool find(const QByteArray& type, int *vmajor, int *vminor,
- QDeclarativeType** type_return, QUrl* url_return, QString *errorString);
+ QDeclarativeType** type_return, QUrl* url_return, QList<QDeclarativeError> *errors);
QDeclarativeImportedNamespace *findNamespace(const QString& type);
@@ -163,7 +163,7 @@ QUrl QDeclarativeImports::baseUrl() const
static QDeclarativeTypeNameCache *
cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespace &set,
- QDeclarativeTypeNameCache *cache)
+ QDeclarativeTypeNameCache *cache, bool importWasQualified)
{
if (!cache)
cache = new QDeclarativeTypeNameCache(engine);
@@ -171,10 +171,27 @@ cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespac
QList<QDeclarativeType *> types = QDeclarativeMetaType::qmlTypes();
for (int ii = 0; ii < set.uris.count(); ++ii) {
- QByteArray base = set.uris.at(ii).toUtf8() + '/';
+ QByteArray uri = set.uris.at(ii).toUtf8();
int major = set.majversions.at(ii);
int minor = set.minversions.at(ii);
+ if (importWasQualified) {
+ QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, major, minor);
+ if (moduleApi.script || moduleApi.qobject) {
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QDeclarativeMetaType::ModuleApiInstance *a = ep->moduleApiInstances.value(moduleApi);
+ if (!a) {
+ a = new QDeclarativeMetaType::ModuleApiInstance;
+ a->scriptCallback = moduleApi.script;
+ a->qobjectCallback = moduleApi.qobject;
+ ep->moduleApiInstances.insert(moduleApi, a);
+ }
+ cache->setModuleApi(a);
+ }
+ }
+
+ QByteArray base = uri + '/';
+
foreach (QDeclarativeType *type, types) {
if (type->qmlTypeName().startsWith(base) &&
type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) &&
@@ -200,15 +217,15 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
QDeclarativeTypeNameCache::Data *d = cache->data(iter.key());
if (d) {
if (!d->typeNamespace)
- cacheForNamespace(engine, *(*iter), d->typeNamespace);
+ cacheForNamespace(engine, *(*iter), d->typeNamespace, true);
} else {
- QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0);
+ QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0, true);
cache->add(iter.key(), nc);
nc->release();
}
}
- cacheForNamespace(engine, set, cache);
+ cacheForNamespace(engine, set, cache, false);
}
/*!
@@ -227,7 +244,7 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
*/
bool QDeclarativeImports::resolveType(const QByteArray& type,
QDeclarativeType** type_return, QUrl* url_return, int *vmaj, int *vmin,
- QDeclarativeImportedNamespace** ns_return, QString *errorString) const
+ QDeclarativeImportedNamespace** ns_return, QList<QDeclarativeError> *errors) const
{
QDeclarativeImportedNamespace* ns = d->findNamespace(QString::fromUtf8(type));
if (ns) {
@@ -236,7 +253,7 @@ bool QDeclarativeImports::resolveType(const QByteArray& type,
return true;
}
if (type_return || url_return) {
- if (d->find(type,vmaj,vmin,type_return,url_return, errorString)) {
+ if (d->find(type,vmaj,vmin,type_return,url_return, errors)) {
if (qmlImportTrace()) {
if (type_return && *type_return && url_return && !url_return->isEmpty())
qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::resolveType: "
@@ -351,13 +368,16 @@ QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate()
bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri,
QDeclarativeImportDatabase *database,
- QDeclarativeDirComponents* components, QString *errorString)
+ QDeclarativeDirComponents* components, QList<QDeclarativeError> *errors)
{
QFile file(absoluteFilePath);
QString filecontent;
if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath);
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath));
+ errors->prepend(error);
+ }
return false;
} else if (file.open(QFile::ReadOnly)) {
filecontent = QString::fromUtf8(file.readAll());
@@ -365,15 +385,29 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: "
<< "loaded " << absoluteFilePath;
} else {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath);
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath));
+ errors->prepend(error);
+ }
return false;
}
QDir dir = QFileInfo(file).dir();
+ QUrl url = QUrl::fromLocalFile(absoluteFilePath);
QDeclarativeDirParser qmldirParser;
qmldirParser.setSource(filecontent);
- qmldirParser.parse();
+ qmldirParser.setUrl(url);
+
+ // propagate any errors reported by the parser back up to the typeloader.
+ if (qmldirParser.parse()) {
+ if (errors) {
+ for (int i = 0; i < qmldirParser.errors().size(); ++i) {
+ errors->prepend(qmldirParser.errors().at(i));
+ }
+ }
+ return false;
+ }
if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) {
qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath);
@@ -390,14 +424,26 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
}
#endif
if (!resolvedFilePath.isEmpty()) {
- if (!database->importPlugin(resolvedFilePath, uri, errorString)) {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(*errorString);
+ if (!database->importPlugin(resolvedFilePath, uri, errors)) {
+ if (errors) {
+ // XXX TODO: should we leave the import plugin error alone?
+ // Here, we pop it off the top and coalesce it into this error's message.
+ // The reason is that the lower level may add url and line/column numbering information.
+ QDeclarativeError poppedError = errors->takeFirst();
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(poppedError.description()));
+ error.setUrl(url);
+ errors->prepend(error);
+ }
return false;
}
} else {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name);
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name));
+ error.setUrl(url);
+ errors->prepend(error);
+ }
return false;
}
}
@@ -443,7 +489,7 @@ QString QDeclarativeImportsPrivate::resolvedUri(const QString &dir_arg, QDeclara
bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomponentsnetwork,
const QString& uri_arg, const QString& prefix, int vmaj, int vmin,
QDeclarativeScriptParser::Import::Type importType,
- QDeclarativeImportDatabase *database, QString *errorString)
+ QDeclarativeImportDatabase *database, QList<QDeclarativeError> *errors)
{
QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork;
QString uri = uri_arg;
@@ -477,7 +523,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString))
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
return false;
break;
}
@@ -496,7 +542,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString))
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
return false;
break;
}
@@ -516,7 +562,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString))
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
return false;
break;
}
@@ -527,12 +573,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
versionFound = true;
if (!versionFound && qmldircomponents.isEmpty()) {
- if (errorString) {
+ if (errors) {
bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1);
+ QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader.
if (anyversion)
- *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin);
+ error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin));
else
- *errorString = QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg);
+ error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg));
+ errors->prepend(error);
}
return false;
}
@@ -545,15 +593,19 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
QFileInfo dirinfo(dir);
if (dir.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg);
+ if (errors) {
+ QDeclarativeError error; // we don't set the line or column as these will be set by the loader.
+ error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg));
+ error.setUrl(importUrl);
+ errors->prepend(error);
+ }
return false; // local import dirs must exist
}
uri = resolvedUri(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))), database);
if (uri.endsWith(QLatin1Char('/')))
uri.chop(1);
if (QFile::exists(localFileOrQrc)) {
- if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errorString))
+ if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errors))
return false;
}
} else {
@@ -562,11 +614,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
QFileInfo dirinfo(localFileOrQrc);
if (localFileOrQrc.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) {
- if (errorString) {
+ if (errors) {
+ QDeclarativeError error; // we don't set the line or column as these will be set by the loader.
if (localFileOrQrc.isEmpty())
- *errorString = QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri);
+ error.setDescription(QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri));
else
- *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri);
+ error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri));
+ error.setUrl(importUrl);
+ errors->prepend(error);
}
return false;
}
@@ -598,7 +653,11 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (lowest_maj > vmaj || (lowest_maj == vmaj && lowest_min > vmin)
|| highest_maj < vmaj || (highest_maj == vmaj && highest_min < vmin))
{
- *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin);
+ if (errors) {
+ QDeclarativeError error; // we don't set the url or line or column information, as these will be set by the loader.
+ error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin));
+ errors->prepend(error);
+ }
return false;
}
}
@@ -613,7 +672,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
}
bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
- QUrl* url_return, QString *errorString)
+ QUrl* url_return, QList<QDeclarativeError> *errors)
{
QDeclarativeImportedNamespace *s = 0;
int slash = type.indexOf('/');
@@ -621,14 +680,20 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *
QString namespaceName = QString::fromUtf8(type.left(slash));
s = set.value(namespaceName);
if (!s) {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("- %1 is not a namespace").arg(namespaceName);
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("- %1 is not a namespace").arg(namespaceName));
+ errors->prepend(error);
+ }
return false;
}
int nslash = type.indexOf('/',slash+1);
if (nslash > 0) {
- if (errorString)
- *errorString = QDeclarativeImportDatabase::tr("- nested namespaces not allowed");
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("- nested namespaces not allowed"));
+ errors->prepend(error);
+ }
return false;
}
} else {
@@ -636,7 +701,7 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *
}
QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower)
if (s) {
- if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errorString))
+ if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors))
return true;
if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) {
// qualified, and only 1 url
@@ -654,7 +719,7 @@ QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const Q
}
bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
- QUrl* url_return, QUrl *base, QString *errorString)
+ QUrl* url_return, QUrl *base, QList<QDeclarativeError> *errors)
{
bool typeRecursionDetected = false;
for (int i=0; i<urls.count(); ++i) {
@@ -663,7 +728,7 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in
// check for type clashes
for (int j = i+1; j<urls.count(); ++j) {
if (find_helper(j, type, vmajor, vminor, 0, 0, base)) {
- if (errorString) {
+ if (errors) {
QString u1 = urls.at(i);
QString u2 = urls.at(j);
if (base) {
@@ -683,16 +748,16 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in
}
}
- if (u1 != u2)
- *errorString
- = QDeclarativeImportDatabase::tr("is ambiguous. Found in %1 and in %2")
- .arg(u1).arg(u2);
- else
- *errorString
- = QDeclarativeImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5")
- .arg(u1)
- .arg(majversions.at(i)).arg(minversions.at(i))
- .arg(majversions.at(j)).arg(minversions.at(j));
+ QDeclarativeError error;
+ if (u1 != u2) {
+ error.setDescription(QDeclarativeImportDatabase::tr("is ambiguous. Found in %1 and in %2").arg(u1).arg(u2));
+ } else {
+ error.setDescription(QDeclarativeImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5")
+ .arg(u1)
+ .arg(majversions.at(i)).arg(minversions.at(i))
+ .arg(majversions.at(j)).arg(minversions.at(j)));
+ }
+ errors->prepend(error);
}
return false;
}
@@ -701,11 +766,13 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in
return true;
}
}
- if (errorString) {
+ if (errors) {
+ QDeclarativeError error;
if (typeRecursionDetected)
- *errorString = QDeclarativeImportDatabase::tr("is instantiated recursively");
+ error.setDescription(QDeclarativeImportDatabase::tr("is instantiated recursively"));
else
- *errorString = QDeclarativeImportDatabase::tr("is not a type");
+ error.setDescription(QDeclarativeImportDatabase::tr("is not a type"));
+ errors->prepend(error);
}
return false;
}
@@ -790,7 +857,7 @@ bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb,
const QString& uri, const QString& prefix, int vmaj, int vmin,
QDeclarativeScriptParser::Import::Type importType,
const QDeclarativeDirComponents &qmldircomponentsnetwork,
- QString *errorString)
+ QList<QDeclarativeError> *errors)
{
if (qmlImportTrace())
qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::addImport: "
@@ -798,7 +865,7 @@ bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb,
<< (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File")
<< " as " << prefix;
- return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errorString);
+ return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errors);
}
/*!
@@ -1013,7 +1080,7 @@ void QDeclarativeImportDatabase::setImportPathList(const QStringList &paths)
/*!
\internal
*/
-bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
+bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
{
if (qmlImportTrace())
qDebug().nospace() << "QDeclarativeImportDatabase::importPlugin: " << uri << " from " << filePath;
@@ -1033,15 +1100,21 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt
if (!engineInitialized || !typesRegistered) {
if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) {
- if (errorString)
- *errorString = tr("File name case mismatch for \"%2\"").arg(absoluteFilePath);
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(tr("File name case mismatch for \"%2\"").arg(absoluteFilePath));
+ errors->prepend(error);
+ }
return false;
}
QPluginLoader loader(absoluteFilePath);
if (!loader.load()) {
- if (errorString)
- *errorString = loader.errorString();
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(loader.errorString());
+ errors->prepend(error);
+ }
return false;
}
@@ -1063,8 +1136,11 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt
iface->initializeEngine(engine, moduleId);
}
} else {
- if (errorString)
- *errorString = loader.errorString();
+ if (errors) {
+ QDeclarativeError error;
+ error.setDescription(loader.errorString());
+ errors->prepend(error);
+ }
return false;
}
}