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.cpp1183
1 files changed, 0 insertions, 1183 deletions
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
deleted file mode 100644
index a8d9035079..0000000000
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ /dev/null
@@ -1,1183 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdeclarativeimport_p.h"
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qdir.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qpluginloader.h>
-#include <QtCore/qlibraryinfo.h>
-#include <QtDeclarative/qdeclarativeextensioninterface.h>
-#include <private/qdeclarativeglobal_p.h>
-#include <private/qdeclarativetypenamecache_p.h>
-#include <private/qdeclarativeengine_p.h>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qmlImportTrace, QML_IMPORT_TRACE)
-DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
-
-static bool greaterThan(const QString &s1, const QString &s2)
-{
- return s1 > s2;
-}
-
-QString resolveLocalUrl(const QString &url, const QString &relative)
-{
- if (relative.contains(QLatin1Char(':'))) {
- // contains a host name
- return QUrl(url).resolved(QUrl(relative)).toString();
- } else if (relative.isEmpty()) {
- return url;
- } else if (relative.at(0) == QLatin1Char('/') || !url.contains(QLatin1Char('/'))) {
- return relative;
- } else {
- if (relative == QLatin1String("."))
- return url.left(url.lastIndexOf(QLatin1Char('/')) + 1);
- else if (relative.startsWith(QLatin1String("./")))
- return url.left(url.lastIndexOf(QLatin1Char('/')) + 1) + relative.mid(2);
- return url.left(url.lastIndexOf(QLatin1Char('/')) + 1) + relative;
- }
-}
-
-
-
-typedef QMap<QString, QString> StringStringMap;
-Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri
-
-class QDeclarativeImportedNamespace
-{
-public:
- struct Data {
- QString uri;
- QString url;
- int majversion;
- int minversion;
- bool isLibrary;
- QDeclarativeDirComponents qmlDirComponents;
- QDeclarativeDirScripts qmlDirScripts;
- };
- QList<Data> imports;
-
-
- bool find_helper(QDeclarativeTypeLoader *typeLoader, const Data &data, const QString& type, int *vmajor, int *vminor,
- QDeclarativeType** type_return, QString* url_return,
- QString *base = 0, bool *typeRecursionDetected = 0);
- bool find(QDeclarativeTypeLoader *typeLoader, const QString& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
- QString* url_return, QString *base = 0, QList<QDeclarativeError> *errors = 0);
-};
-
-class QDeclarativeImportsPrivate {
-public:
- QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader);
- ~QDeclarativeImportsPrivate();
-
- bool importExtension(const QString &absoluteFilePath, const QString &uri,
- QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components,
- QDeclarativeDirScripts *scripts,
- 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, QDeclarativeScript::Import::Type importType,
- QDeclarativeImportDatabase *database, QList<QDeclarativeError> *errors);
- bool find(const QString& type, int *vmajor, int *vminor,
- QDeclarativeType** type_return, QString* url_return, QList<QDeclarativeError> *errors);
-
- QDeclarativeImportedNamespace *findNamespace(const QString& type);
-
- QUrl baseUrl;
- QString base;
- int ref;
-
- QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded;
- QDeclarativeImportedNamespace unqualifiedset;
- QHash<QString,QDeclarativeImportedNamespace* > set;
- QDeclarativeTypeLoader *typeLoader;
-};
-
-/*!
-\class QDeclarativeImports
-\brief The QDeclarativeImports class encapsulates one QML document's import statements.
-\internal
-*/
-QDeclarativeImports::QDeclarativeImports(const QDeclarativeImports &copy)
-: d(copy.d)
-{
- ++d->ref;
-}
-
-QDeclarativeImports &
-QDeclarativeImports::operator =(const QDeclarativeImports &copy)
-{
- ++copy.d->ref;
- if (--d->ref == 0)
- delete d;
- d = copy.d;
- return *this;
-}
-
-QDeclarativeImports::QDeclarativeImports(QDeclarativeTypeLoader *typeLoader)
- : d(new QDeclarativeImportsPrivate(typeLoader))
-{
-}
-
-QDeclarativeImports::~QDeclarativeImports()
-{
- if (--d->ref == 0)
- delete d;
-}
-
-/*!
- Sets the base URL to be used for all relative file imports added.
-*/
-void QDeclarativeImports::setBaseUrl(const QUrl& url, const QString &urlString)
-{
- d->baseUrl = url;
-
- if (urlString.isEmpty()) {
- d->base = url.toString();
- } else {
- //Q_ASSERT(url.toString() == urlString);
- d->base = urlString;
- }
-}
-
-/*!
- Returns the base URL to be used for all relative file imports added.
-*/
-QUrl QDeclarativeImports::baseUrl() const
-{
- return d->baseUrl;
-}
-
-void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const
-{
- const QDeclarativeImportedNamespace &set = d->unqualifiedset;
-
- for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
- const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
- QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(data.uri, data.majversion);
- if (module)
- cache->m_anonymousImports.append(QDeclarativeTypeModuleVersion(module, data.minversion));
- }
-
- for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.begin();
- iter != d->set.end();
- ++iter) {
-
- const QDeclarativeImportedNamespace &set = *iter.value();
- for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
- const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
- QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(data.uri, data.majversion);
- if (module) {
- QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
- import.modules.append(QDeclarativeTypeModuleVersion(module, data.minversion));
- }
-
- QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(data.uri, data.majversion, data.minversion);
- if (moduleApi.script || moduleApi.qobject) {
- QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- import.moduleApi = ep->moduleApiInstance(moduleApi);
- }
- }
- }
-}
-
-QList<QDeclarativeImports::ScriptReference> QDeclarativeImports::resolvedScripts() const
-{
- QList<QDeclarativeImports::ScriptReference> scripts;
-
- const QDeclarativeImportedNamespace &set = d->unqualifiedset;
-
- for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
- const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
-
- foreach (const QDeclarativeDirParser::Script &script, data.qmlDirScripts) {
- ScriptReference ref;
- ref.nameSpace = script.nameSpace;
- ref.location = QUrl(data.url).resolved(QUrl(script.fileName));
- scripts.append(ref);
- }
- }
-
- for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.constBegin();
- iter != d->set.constEnd();
- ++iter) {
- const QDeclarativeImportedNamespace &set = *iter.value();
-
- for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
- const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
-
- foreach (const QDeclarativeDirParser::Script &script, data.qmlDirScripts) {
- ScriptReference ref;
- ref.nameSpace = script.nameSpace;
- ref.qualifier = iter.key();
- ref.location = QUrl(data.url).resolved(QUrl(script.fileName));
- scripts.append(ref);
- }
- }
- }
-
- return scripts;
-}
-
-/*!
- \internal
-
- The given (namespace qualified) \a type is resolved to either
- \list
- \o a QDeclarativeImportedNamespace stored at \a ns_return,
- \o a QDeclarativeType stored at \a type_return, or
- \o a component located at \a url_return.
- \endlist
-
- If any return pointer is 0, the corresponding search is not done.
-
- \sa addImport()
-*/
-bool QDeclarativeImports::resolveType(const QString& type,
- QDeclarativeType** type_return, QString* url_return, int *vmaj, int *vmin,
- QDeclarativeImportedNamespace** ns_return, QList<QDeclarativeError> *errors) const
-{
- QDeclarativeImportedNamespace* ns = d->findNamespace(type);
- if (ns) {
- if (ns_return)
- *ns_return = ns;
- return true;
- }
- if (type_return || url_return) {
- 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: "
- << type << " => " << (*type_return)->typeName() << " " << *url_return;
- if (type_return && *type_return)
- qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::resolveType: "
- << type << " => " << (*type_return)->typeName();
- if (url_return && !url_return->isEmpty())
- qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::resolveType: "
- << type << " => " << *url_return;
- }
- return true;
- }
- }
- return false;
-}
-
-/*!
- \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 QDeclarativeType stored at \a type_return, or
- a component located at \a url_return.
-
- If either return pointer is 0, the corresponding search is not done.
-*/
-bool QDeclarativeImports::resolveType(QDeclarativeImportedNamespace* ns, const QString& type,
- QDeclarativeType** type_return, QString* url_return,
- int *vmaj, int *vmin) const
-{
- return ns->find(d->typeLoader,type,vmaj,vmin,type_return,url_return);
-}
-
-bool QDeclarativeImportedNamespace::find_helper(QDeclarativeTypeLoader *typeLoader, const Data &data, const QString& type, int *vmajor, int *vminor,
- QDeclarativeType** type_return, QString* url_return,
- QString *base, bool *typeRecursionDetected)
-{
- int vmaj = data.majversion;
- int vmin = data.minversion;
-
- if (vmaj >= 0 && vmin >= 0) {
- QString qt = data.uri + QLatin1Char('/') + type;
- QDeclarativeType *t = QDeclarativeMetaType::qmlType(qt,vmaj,vmin);
- if (t) {
- if (vmajor) *vmajor = vmaj;
- if (vminor) *vminor = vmin;
- if (type_return)
- *type_return = t;
- return true;
- }
- }
-
- const QDeclarativeDirComponents &qmldircomponents = data.qmlDirComponents;
- bool typeWasDeclaredInQmldir = false;
- if (!qmldircomponents.isEmpty()) {
- foreach (const QDeclarativeDirParser::Component &c, qmldircomponents) {
- if (c.typeName == type) {
- typeWasDeclaredInQmldir = true;
- // importing version -1 means import ALL versions
- if ((vmaj == -1) || (c.majorVersion == vmaj && vmin >= c.minorVersion)) {
- QString url(data.url + type + QLatin1String(".qml"));
- QString candidate = resolveLocalUrl(url, c.fileName);
- if (c.internal && base) {
- if (resolveLocalUrl(*base, c.fileName) != candidate)
- continue; // failed attempt to access an internal type
- }
- if (base && *base == candidate) {
- if (typeRecursionDetected)
- *typeRecursionDetected = true;
- continue; // no recursion
- }
- if (url_return)
- *url_return = candidate;
- return true;
- }
- }
- }
- }
-
- if (!typeWasDeclaredInQmldir && !data.isLibrary) {
- // XXX search non-files too! (eg. zip files, see QT-524)
- QString url(data.url + type + QLatin1String(".qml"));
- QString file = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
- if (!typeLoader->absoluteFilePath(file).isEmpty()) {
- if (base && *base == url) { // no recursion
- if (typeRecursionDetected)
- *typeRecursionDetected = true;
- } else {
- if (url_return)
- *url_return = url;
- return true;
- }
- }
- }
- return false;
-}
-
-QDeclarativeImportsPrivate::QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader)
- : ref(1), typeLoader(loader)
-{
-}
-
-QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate()
-{
- foreach (QDeclarativeImportedNamespace* s, set.values())
- delete s;
-}
-
-bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri,
- QDeclarativeImportDatabase *database,
- QDeclarativeDirComponents* components,
- QDeclarativeDirScripts* scripts,
- QList<QDeclarativeError> *errors)
-{
- const QDeclarativeDirParser *qmldirParser = typeLoader->qmlDirParser(absoluteFilePath);
- if (qmldirParser->hasError()) {
- if (errors) {
- const QList<QDeclarativeError> qmldirErrors = qmldirParser->errors(uri);
- for (int i = 0; i < qmldirErrors.size(); ++i)
- errors->prepend(qmldirErrors.at(i));
- }
- return false;
- }
-
- if (qmlImportTrace())
- qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base) << "::importExtension: "
- << "loaded " << absoluteFilePath;
-
- if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) {
- qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath);
-
- QString qmldirPath = absoluteFilePath;
- int slash = absoluteFilePath.lastIndexOf(QLatin1Char('/'));
- if (slash > 0)
- qmldirPath.truncate(slash);
- foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser->plugins()) {
-
- QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name);
- if (!resolvedFilePath.isEmpty()) {
- 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(QUrl::fromLocalFile(absoluteFilePath));
- errors->prepend(error);
- }
- return false;
- }
- } else {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name));
- error.setUrl(QUrl::fromLocalFile(absoluteFilePath));
- errors->prepend(error);
- }
- return false;
- }
- }
- }
-
- if (components)
- *components = qmldirParser->components();
- if (scripts)
- *scripts = qmldirParser->scripts();
-
- return true;
-}
-
-QString QDeclarativeImportsPrivate::resolvedUri(const QString &dir_arg, QDeclarativeImportDatabase *database)
-{
- QString dir = dir_arg;
- if (dir.endsWith(QLatin1Char('/')) || dir.endsWith(QLatin1Char('\\')))
- dir.chop(1);
-
- QStringList paths = database->fileImportPath;
- qSort(paths.begin(), paths.end(), greaterThan); // Ensure subdirs preceed their parents.
-
- QString stableRelativePath = dir;
- foreach(const QString &path, paths) {
- if (dir.startsWith(path)) {
- stableRelativePath = dir.mid(path.length()+1);
- break;
- }
- }
-
- stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('/'));
-
- // remove optional versioning in dot notation from uri
- int lastSlash = stableRelativePath.lastIndexOf(QLatin1Char('/'));
- if (lastSlash >= 0) {
- int versionDot = stableRelativePath.indexOf(QLatin1Char('.'), lastSlash);
- if (versionDot >= 0)
- stableRelativePath = stableRelativePath.left(versionDot);
- }
-
- stableRelativePath.replace(QLatin1Char('/'), QLatin1Char('.'));
- return stableRelativePath;
-}
-
-bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomponentsnetwork,
- const QString& uri_arg, const QString& prefix, int vmaj, int vmin,
- QDeclarativeScript::Import::Type importType,
- QDeclarativeImportDatabase *database, QList<QDeclarativeError> *errors)
-{
- static QLatin1String Slash_qmldir("/qmldir");
- static QLatin1Char Slash('/');
-
- QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork;
- QDeclarativeDirScripts qmldirscripts;
- QString uri = uri_arg;
- QDeclarativeImportedNamespace *s;
- if (prefix.isEmpty()) {
- s = &unqualifiedset;
- } else {
- s = set.value(prefix);
- if (!s)
- set.insert(prefix,(s=new QDeclarativeImportedNamespace));
- }
- QString url = uri;
- bool versionFound = false;
- if (importType == QDeclarativeScript::Import::Library) {
-
- Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries
-
- url.replace(QLatin1Char('.'), Slash);
- bool found = false;
- QString dir;
- QString qmldir;
-
- // step 1: search for extension with fully encoded version number
- foreach (const QString &p, database->fileImportPath) {
- dir = p+Slash+url;
-
- QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir"));
- const QString absoluteFilePath = fi.absoluteFilePath();
-
- if (fi.isFile()) {
- found = true;
-
- const QString absolutePath = fi.absolutePath();
- if (absolutePath.at(0) == QLatin1Char(':'))
- url = QLatin1String("qrc://") + absolutePath.mid(1);
- else
- url = QUrl::fromLocalFile(fi.absolutePath()).toString();
- uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return false;
- break;
- }
- }
-
- // TODO: Should this search be omitted if found == true?
-
- // step 2: search for extension with encoded version major
- foreach (const QString &p, database->fileImportPath) {
- dir = p+Slash+url;
-
- QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"));
- const QString absoluteFilePath = fi.absoluteFilePath();
-
- if (fi.isFile()) {
- found = true;
-
- const QString absolutePath = fi.absolutePath();
- if (absolutePath.at(0) == QLatin1Char(':'))
- url = QLatin1String("qrc://") + absolutePath.mid(1);
- else
- url = QUrl::fromLocalFile(fi.absolutePath()).toString();
- uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return false;
- break;
- }
- }
-
- if (!found) {
- // step 3: search for extension without version number
-
- foreach (const QString &p, database->fileImportPath) {
- dir = p+Slash+url;
- qmldir = dir+Slash_qmldir;
-
- QString absoluteFilePath = typeLoader->absoluteFilePath(qmldir);
- if (!absoluteFilePath.isEmpty()) {
- found = true;
- QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1);
- if (absolutePath.at(0) == QLatin1Char(':'))
- url = QLatin1String("qrc://") + absolutePath.mid(1);
- else
- url = QUrl::fromLocalFile(absolutePath).toString();
- uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return false;
- break;
- }
- }
- }
-
- if (QDeclarativeMetaType::isModule(uri, vmaj, vmin))
- versionFound = true;
-
- if (!versionFound && qmldircomponents.isEmpty() && qmldirscripts.isEmpty()) {
- if (errors) {
- QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader.
- if (QDeclarativeMetaType::isAnyModule(uri))
- error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin));
- else
- error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg));
- errors->prepend(error);
- }
- return false;
- }
- } else {
- if (importType == QDeclarativeScript::Import::File && qmldircomponents.isEmpty()) {
- QString importUrl = resolveLocalUrl(base, uri + Slash_qmldir);
- QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl);
- if (!localFileOrQrc.isEmpty()) {
- QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(resolveLocalUrl(base, uri));
- if (!typeLoader->directoryExists(dir)) {
- 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(QUrl(importUrl));
- errors->prepend(error);
- }
- return false; // local import dirs must exist
- }
- uri = resolvedUri(dir, database);
- if (uri.endsWith(Slash))
- uri.chop(1);
- if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) {
- if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,&qmldirscripts,errors))
- return false;
- }
- } else {
- if (prefix.isEmpty()) {
- // directory must at least exist for valid import
- QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(resolveLocalUrl(base, uri));
- if (!typeLoader->directoryExists(localFileOrQrc)) {
- if (errors) {
- QDeclarativeError error; // we don't set the line or column as these will be set by the loader.
- if (localFileOrQrc.isEmpty())
- error.setDescription(QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri));
- else
- error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri));
- error.setUrl(QUrl(importUrl));
- errors->prepend(error);
- }
- return false;
- }
- }
- }
- }
-
- url = resolveLocalUrl(base, url);
- }
-
- if (!versionFound && (vmaj > -1) && (vmin > -1) && !qmldircomponents.isEmpty()) {
- int lowest_min = INT_MAX;
- int highest_min = INT_MIN;
-
- QList<QDeclarativeDirParser::Component>::const_iterator cend = qmldircomponents.constEnd();
- for (QList<QDeclarativeDirParser::Component>::const_iterator cit = qmldircomponents.constBegin(); cit != cend; ++cit) {
- if (cit->majorVersion == vmaj) {
- lowest_min = qMin(lowest_min, cit->minorVersion);
- highest_min = qMax(highest_min, cit->minorVersion);
- }
- }
-
- if (lowest_min > vmin || highest_min < 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;
- }
- }
-
- if (!url.endsWith(Slash))
- url += Slash;
-
- QMap<QString, QDeclarativeDirParser::Script> scripts;
-
- if (!qmldirscripts.isEmpty()) {
- // Verify that we haven't imported these scripts already
- QList<QDeclarativeImportedNamespace::Data>::const_iterator end = s->imports.constEnd();
- for (QList<QDeclarativeImportedNamespace::Data>::const_iterator it = s->imports.constBegin(); it != end; ++it) {
- if (it->uri == uri) {
- QDeclarativeError error;
- error.setDescription(QDeclarativeImportDatabase::tr("\"%1\" is ambiguous. Found in %2 and in %3").arg(uri).arg(url).arg(it->url));
- errors->prepend(error);
- return false;
- }
- }
-
- QList<QDeclarativeDirParser::Script>::const_iterator send = qmldirscripts.constEnd();
- for (QList<QDeclarativeDirParser::Script>::const_iterator sit = qmldirscripts.constBegin(); sit != send; ++sit) {
- // Only include scripts that match our requested version
- if (((vmaj == -1) || (sit->majorVersion == vmaj)) &&
- ((vmin == -1) || (sit->minorVersion <= vmin))) {
-
- // Load the highest version that matches
- QMap<QString, QDeclarativeDirParser::Script>::iterator it = scripts.find(sit->nameSpace);
- if (it == scripts.end() || (it->minorVersion < sit->minorVersion)) {
- scripts.insert(sit->nameSpace, *sit);
- }
- }
- }
- }
-
- QDeclarativeImportedNamespace::Data data;
- data.uri = uri;
- data.url = url;
- data.majversion = vmaj;
- data.minversion = vmin;
- data.isLibrary = importType == QDeclarativeScript::Import::Library;
- data.qmlDirComponents = qmldircomponents;
- data.qmlDirScripts = scripts.values();
-
- s->imports.prepend(data);
-
- return true;
-}
-
-bool QDeclarativeImportsPrivate::find(const QString& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
- QString* url_return, QList<QDeclarativeError> *errors)
-{
- QDeclarativeImportedNamespace *s = 0;
- int slash = type.indexOf(QLatin1Char('/'));
- if (slash >= 0) {
- QString namespaceName = type.left(slash);
- s = set.value(namespaceName);
- if (!s) {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(QDeclarativeImportDatabase::tr("- %1 is not a namespace").arg(namespaceName));
- errors->prepend(error);
- }
- return false;
- }
- int nslash = type.indexOf(QLatin1Char('/'),slash+1);
- if (nslash > 0) {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(QDeclarativeImportDatabase::tr("- nested namespaces not allowed"));
- errors->prepend(error);
- }
- return false;
- }
- } else {
- s = &unqualifiedset;
- }
- QString unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower)
- if (s) {
- if (s->find(typeLoader,unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors))
- return true;
- if (s->imports.count() == 1 && !s->imports.at(0).isLibrary && url_return && s != &unqualifiedset) {
- // qualified, and only 1 url
- *url_return = resolveLocalUrl(s->imports.at(0).url, unqualifiedtype + QLatin1String(".qml"));
- return true;
- }
- }
-
- return false;
-}
-
-QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const QString& type)
-{
- return set.value(type);
-}
-
-bool QDeclarativeImportedNamespace::find(QDeclarativeTypeLoader *typeLoader, const QString& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
- QString* url_return, QString *base, QList<QDeclarativeError> *errors)
-{
- bool typeRecursionDetected = false;
- for (int i=0; i<imports.count(); ++i) {
- if (find_helper(typeLoader, imports.at(i), type, vmajor, vminor, type_return, url_return, base, &typeRecursionDetected)) {
- if (qmlCheckTypes()) {
- // check for type clashes
- for (int j = i+1; j<imports.count(); ++j) {
- if (find_helper(typeLoader, imports.at(j), type, vmajor, vminor, 0, 0, base)) {
- if (errors) {
- QString u1 = imports.at(i).url;
- QString u2 = imports.at(j).url;
- if (base) {
- QString b = *base;
- int slash = b.lastIndexOf(QLatin1Char('/'));
- if (slash >= 0) {
- b = b.left(slash+1);
- QString l = b.left(slash);
- if (u1.startsWith(b))
- u1 = u1.mid(b.count());
- else if (u1 == l)
- u1 = QDeclarativeImportDatabase::tr("local directory");
- if (u2.startsWith(b))
- u2 = u2.mid(b.count());
- else if (u2 == l)
- u2 = QDeclarativeImportDatabase::tr("local directory");
- }
- }
-
- 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(imports.at(i).majversion).arg(imports.at(i).minversion)
- .arg(imports.at(j).majversion).arg(imports.at(j).minversion));
- }
- errors->prepend(error);
- }
- return false;
- }
- }
- }
- return true;
- }
- }
- if (errors) {
- QDeclarativeError error;
- if (typeRecursionDetected)
- error.setDescription(QDeclarativeImportDatabase::tr("is instantiated recursively"));
- else
- error.setDescription(QDeclarativeImportDatabase::tr("is not a type"));
- errors->prepend(error);
- }
- return false;
-}
-
-/*!
-\class QDeclarativeImportDatabase
-\brief The QDeclarativeImportDatabase class manages the QML imports for a QDeclarativeEngine.
-\internal
-*/
-QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e)
-: engine(e)
-{
- filePluginPath << QLatin1String(".");
-
- // Search order is applicationDirPath(), $QML_IMPORT_PATH, QLibraryInfo::ImportsPath
-
-#ifndef QT_NO_SETTINGS
- QString installImportsPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
- addImportPath(installImportsPath);
-#endif // QT_NO_SETTINGS
-
- // env import paths
- QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
- if (!envImportPath.isEmpty()) {
-#if defined(Q_OS_WIN)
- QLatin1Char pathSep(';');
-#else
- QLatin1Char pathSep(':');
-#endif
- QStringList paths = QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts);
- for (int ii = paths.count() - 1; ii >= 0; --ii)
- addImportPath(paths.at(ii));
- }
-
- addImportPath(QCoreApplication::applicationDirPath());
-}
-
-QDeclarativeImportDatabase::~QDeclarativeImportDatabase()
-{
-}
-
-/*!
- \internal
-
- Adds information to \a imports such that subsequent calls to resolveType()
- will resolve types qualified by \a prefix by considering types found at the given \a uri.
-
- The uri is either a directory (if importType is FileImport), or a URI resolved using paths
- added via addImportPath() (if importType is LibraryImport).
-
- The \a prefix may be empty, in which case the import location is considered for
- unqualified types.
-
- The base URL must already have been set with Import::setBaseUrl().
-*/
-bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb,
- const QString& uri, const QString& prefix, int vmaj, int vmin,
- QDeclarativeScript::Import::Type importType,
- const QDeclarativeDirComponents &qmldircomponentsnetwork,
- QList<QDeclarativeError> *errors)
-{
- if (qmlImportTrace())
- qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::addImport: "
- << uri << " " << vmaj << '.' << vmin << " "
- << (importType==QDeclarativeScript::Import::Library? "Library" : "File")
- << " as " << prefix;
-
- return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errors);
-}
-
-/*!
- \internal
-
- Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix.
- The \a prefix must contain the dot.
-
- \a qmldirPath is the location of the qmldir file.
- */
-QString QDeclarativeImportDatabase::resolvePlugin(QDeclarativeTypeLoader *typeLoader,
- const QString &qmldirPath, const QString &qmldirPluginPath,
- const QString &baseName, const QStringList &suffixes,
- const QString &prefix)
-{
- QStringList searchPaths = filePluginPath;
- bool qmldirPluginPathIsRelative = QDir::isRelativePath(qmldirPluginPath);
- if (!qmldirPluginPathIsRelative)
- searchPaths.prepend(qmldirPluginPath);
-
- foreach (const QString &pluginPath, searchPaths) {
-
- QString resolvedPath;
- if (pluginPath == QLatin1String(".")) {
- if (qmldirPluginPathIsRelative && !qmldirPluginPath.isEmpty() && qmldirPluginPath != QLatin1String("."))
- resolvedPath = QDir::cleanPath(qmldirPath + QLatin1Char('/') + qmldirPluginPath);
- else
- resolvedPath = qmldirPath;
- } else {
- if (QDir::isRelativePath(pluginPath))
- resolvedPath = QDir::cleanPath(qmldirPath + QLatin1Char('/') + pluginPath);
- else
- resolvedPath = pluginPath;
- }
-
- // hack for resources, should probably go away
- if (resolvedPath.startsWith(QLatin1Char(':')))
- resolvedPath = QCoreApplication::applicationDirPath();
-
- if (!resolvedPath.endsWith(QLatin1Char('/')))
- resolvedPath += QLatin1Char('/');
-
- foreach (const QString &suffix, suffixes) {
- QString pluginFileName = prefix;
-
- pluginFileName += baseName;
- pluginFileName += suffix;
-
- QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + pluginFileName);
- if (!absolutePath.isEmpty())
- return absolutePath;
- }
- }
-
- if (qmlImportTrace())
- qDebug() << "QDeclarativeImportDatabase::resolvePlugin: Could not resolve plugin" << baseName
- << "in" << qmldirPath;
-
- return QString();
-}
-
-/*!
- \internal
-
- Returns the result of the merge of \a baseName with \a dir and the platform suffix.
-
- \table
- \header \i Platform \i Valid suffixes
- \row \i Windows \i \c .dll
- \row \i Unix/Linux \i \c .so
- \row \i AIX \i \c .a
- \row \i HP-UX \i \c .sl, \c .so (HP-UXi)
- \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so
- \endtable
-
- Version number on unix are ignored.
-*/
-QString QDeclarativeImportDatabase::resolvePlugin(QDeclarativeTypeLoader *typeLoader,
- const QString &qmldirPath, const QString &qmldirPluginPath,
- const QString &baseName)
-{
-#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
- QStringList()
-# ifdef QT_DEBUG
- << QLatin1String("d.dll") // try a qmake-style debug build first
-# endif
- << QLatin1String(".dll"));
-#else
-
-# if defined(Q_OS_DARWIN)
-
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
- QStringList()
-# ifdef QT_DEBUG
- << QLatin1String("_debug.dylib") // try a qmake-style debug build first
- << QLatin1String(".dylib")
-# else
- << QLatin1String(".dylib")
- << QLatin1String("_debug.dylib") // try a qmake-style debug build after
-# endif
- << QLatin1String(".so")
- << QLatin1String(".bundle"),
- QLatin1String("lib"));
-# else // Generic Unix
- QStringList validSuffixList;
-
-# if defined(Q_OS_HPUX)
-/*
- See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
- "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
- the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
- */
- validSuffixList << QLatin1String(".sl");
-# if defined __ia64
- validSuffixList << QLatin1String(".so");
-# endif
-# elif defined(Q_OS_AIX)
- validSuffixList << QLatin1String(".a") << QLatin1String(".so");
-# elif defined(Q_OS_UNIX)
- validSuffixList << QLatin1String(".so");
-# endif
-
- // Examples of valid library names:
- // libfoo.so
-
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
-# endif
-
-#endif
-}
-
-/*!
- \internal
-*/
-QStringList QDeclarativeImportDatabase::pluginPathList() const
-{
- return filePluginPath;
-}
-
-/*!
- \internal
-*/
-void QDeclarativeImportDatabase::setPluginPathList(const QStringList &paths)
-{
- filePluginPath = paths;
-}
-
-/*!
- \internal
-*/
-void QDeclarativeImportDatabase::addPluginPath(const QString& path)
-{
- if (qmlImportTrace())
- qDebug().nospace() << "QDeclarativeImportDatabase::addPluginPath: " << path;
-
- QUrl url = QUrl(path);
- if (url.isRelative() || url.scheme() == QLatin1String("file")
- || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path
- QDir dir = QDir(path);
- filePluginPath.prepend(dir.canonicalPath());
- } else {
- filePluginPath.prepend(path);
- }
-}
-
-/*!
- \internal
-*/
-void QDeclarativeImportDatabase::addImportPath(const QString& path)
-{
- if (qmlImportTrace())
- qDebug().nospace() << "QDeclarativeImportDatabase::addImportPath: " << path;
-
- if (path.isEmpty())
- return;
-
- QUrl url = QUrl(path);
- QString cPath;
-
- if (url.isRelative() || url.scheme() == QLatin1String("file")
- || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path
- QDir dir = QDir(path);
- cPath = dir.canonicalPath();
- } else {
- cPath = path;
- cPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
- }
-
- if (!cPath.isEmpty()
- && !fileImportPath.contains(cPath))
- fileImportPath.prepend(cPath);
-}
-
-/*!
- \internal
-*/
-QStringList QDeclarativeImportDatabase::importPathList() const
-{
- return fileImportPath;
-}
-
-/*!
- \internal
-*/
-void QDeclarativeImportDatabase::setImportPathList(const QStringList &paths)
-{
- fileImportPath = paths;
-}
-
-/*!
- \internal
-*/
-bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
-{
- if (qmlImportTrace())
- qDebug().nospace() << "QDeclarativeImportDatabase::importPlugin: " << uri << " from " << filePath;
-
-#ifndef QT_NO_LIBRARY
- QFileInfo fileInfo(filePath);
- const QString absoluteFilePath = fileInfo.absoluteFilePath();
-
- bool engineInitialized = initializedPlugins.contains(absoluteFilePath);
- bool typesRegistered = qmlEnginePluginsWithRegisteredTypes()->contains(absoluteFilePath);
-
- if (typesRegistered) {
- Q_ASSERT_X(qmlEnginePluginsWithRegisteredTypes()->value(absoluteFilePath) == uri,
- "QDeclarativeImportDatabase::importExtension",
- "Internal error: Plugin imported previously with different uri");
- }
-
- if (!engineInitialized || !typesRegistered) {
- if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(tr("File name case mismatch for \"%1\"").arg(absoluteFilePath));
- errors->prepend(error);
- }
- return false;
- }
- QPluginLoader loader(absoluteFilePath);
-
- if (!loader.load()) {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(loader.errorString());
- errors->prepend(error);
- }
- return false;
- }
-
- QObject *instance = loader.instance();
- if (QDeclarativeTypesExtensionInterface *iface = qobject_cast<QDeclarativeExtensionInterface *>(instance)) {
-
- const QByteArray bytes = uri.toUtf8();
- const char *moduleId = bytes.constData();
- if (!typesRegistered) {
-
- // XXX thread this code should probably be protected with a mutex.
- qmlEnginePluginsWithRegisteredTypes()->insert(absoluteFilePath, uri);
- iface->registerTypes(moduleId);
- }
- if (!engineInitialized) {
- // things on the engine (eg. adding new global objects) have to be done for every
- // engine.
- // XXX protect against double initialization
- initializedPlugins.insert(absoluteFilePath);
-
- QDeclarativeExtensionInterface *eiface =
- qobject_cast<QDeclarativeExtensionInterface *>(instance);
- if (eiface) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- ep->typeLoader.initializeEngine(eiface, moduleId);
- }
- }
- } else {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(loader.errorString());
- errors->prepend(error);
- }
- return false;
- }
- }
-
- return true;
-#else
- return false;
-#endif
-}
-
-QT_END_NAMESPACE