src/declarative/qml/qdeclarativeimport.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/declarative/qml/qdeclarativeimport.cpp	Thu Jul 22 16:41:55 2010 +0100
@@ -0,0 +1,922 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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;
+}
+
+typedef QMap<QString, QString> StringStringMap;
+Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri
+
+class QDeclarativeImportedNamespace 
+{
+public:
+    QStringList uris;
+    QStringList urls;
+    QList<int> majversions;
+    QList<int> minversions;
+    QList<bool> isLibrary;
+    QList<QDeclarativeDirComponents> qmlDirComponents;
+
+
+    bool find_helper(int i, const QByteArray& type, int *vmajor, int *vminor,
+                                 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);
+};
+
+class QDeclarativeImportsPrivate {
+public:
+    QDeclarativeImportsPrivate();
+    ~QDeclarativeImportsPrivate();
+
+    bool importExtension(const QString &absoluteFilePath, const QString &uri, 
+                         QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components, 
+                         QString *errorString);
+
+    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);
+    bool find(const QByteArray& type, int *vmajor, int *vminor, 
+              QDeclarativeType** type_return, QUrl* url_return, QString *errorString);
+
+    QDeclarativeImportedNamespace *findNamespace(const QString& type);
+
+    QUrl base;
+    int ref;
+
+    QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded;
+    QDeclarativeImportedNamespace unqualifiedset;
+    QHash<QString,QDeclarativeImportedNamespace* > set;
+};
+
+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() 
+: d(new QDeclarativeImportsPrivate)
+{
+}
+
+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)
+{
+    d->base = url;
+}
+
+/*!
+  Returns the base URL to be used for all relative file imports added.
+*/
+QUrl QDeclarativeImports::baseUrl() const
+{
+    return d->base;
+}
+
+static QDeclarativeTypeNameCache *
+cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespace &set, 
+                  QDeclarativeTypeNameCache *cache)
+{
+    if (!cache)
+        cache = new QDeclarativeTypeNameCache(engine);
+
+    QList<QDeclarativeType *> types = QDeclarativeMetaType::qmlTypes();
+
+    for (int ii = 0; ii < set.uris.count(); ++ii) {
+        QByteArray base = set.uris.at(ii).toUtf8() + '/';
+        int major = set.majversions.at(ii);
+        int minor = set.minversions.at(ii);
+
+        foreach (QDeclarativeType *type, types) {
+            if (type->qmlTypeName().startsWith(base) &&
+                type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) &&
+                type->availableInVersion(major,minor))
+            {
+                QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length()));
+
+                cache->add(name, type);
+            }
+        }
+    }
+
+    return cache;
+}
+
+void QDeclarativeImports::cache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const
+{
+    const QDeclarativeImportedNamespace &set = d->unqualifiedset;
+
+    for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.begin();
+         iter != d->set.end(); ++iter) {
+
+        QDeclarativeTypeNameCache::Data *d = cache->data(iter.key());
+        if (d) {
+            if (!d->typeNamespace)
+                cacheForNamespace(engine, *(*iter), d->typeNamespace);
+        } else {
+            QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0);
+            cache->add(iter.key(), nc);
+            nc->release();
+        }
+    }
+
+    cacheForNamespace(engine, set, cache);
+}
+bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, int *vmajor, int *vminor,
+                                 QDeclarativeType** type_return, QUrl* url_return,
+                                 QUrl *base, bool *typeRecursionDetected)
+{
+    int vmaj = majversions.at(i);
+    int vmin = minversions.at(i);
+
+    QByteArray qt = uris.at(i).toUtf8();
+    qt += '/';
+    qt += 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;
+    }
+
+    QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml"));
+    QDeclarativeDirComponents qmldircomponents = qmlDirComponents.at(i);
+
+    bool typeWasDeclaredInQmldir = false;
+    if (!qmldircomponents.isEmpty()) {
+        const QString typeName = QString::fromUtf8(type);
+        foreach (const QDeclarativeDirParser::Component &c, qmldircomponents) {
+            if (c.typeName == typeName) {
+                typeWasDeclaredInQmldir = true;
+
+                // importing version -1 means import ALL versions
+                if ((vmaj == -1) || (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion))) {
+                    QUrl candidate = url.resolved(QUrl(c.fileName));
+                    if (c.internal && base) {
+                        if (base->resolved(QUrl(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  && !isLibrary.at(i)) {
+        // XXX search non-files too! (eg. zip files, see QT-524)
+        QFileInfo f(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url));
+        if (f.exists()) {
+            if (base && *base == url) { // no recursion
+                if (typeRecursionDetected)
+                    *typeRecursionDetected = true;
+            } else {
+                if (url_return)
+                    *url_return = url;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+QDeclarativeImportsPrivate::QDeclarativeImportsPrivate() 
+: ref(1)
+{
+}
+
+QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate()
+{
+    foreach (QDeclarativeImportedNamespace* s, set.values())
+        delete s;
+}
+
+bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri, 
+                                                  QDeclarativeImportDatabase *database, 
+                                                  QDeclarativeDirComponents* components, QString *errorString) 
+{
+    QFile file(absoluteFilePath);
+    QString filecontent;
+    if (file.open(QFile::ReadOnly)) {
+        filecontent = QString::fromUtf8(file.readAll());
+        if (qmlImportTrace())
+            qDebug() << "QDeclarativeImportDatabase::add: loaded" << absoluteFilePath;
+    } else {
+        if (errorString)
+            *errorString = QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath);
+        return false;
+    }
+    QDir dir = QFileInfo(file).dir();
+
+    QDeclarativeDirParser qmldirParser;
+    qmldirParser.setSource(filecontent);
+    qmldirParser.parse();
+
+    if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) {
+        qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath);
+
+
+        foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) {
+
+            QString resolvedFilePath = database->resolvePlugin(dir, plugin.path, plugin.name);
+
+            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);
+                    return false;
+                }
+            } else {
+                if (errorString)
+                    *errorString = QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name);
+                return false;
+            }
+        }
+    }
+
+    if (components)
+        *components = qmldirParser.components();
+
+    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( QString path, paths) {
+        if (dir.startsWith(path)) {
+            stableRelativePath = dir.mid(path.length()+1);
+            break;
+        }
+    }
+    stableRelativePath.replace(QLatin1Char('/'), QLatin1Char('.'));
+    stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('.'));
+    return stableRelativePath;
+}
+
+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)
+{
+    QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork;
+    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;
+    if (importType == QDeclarativeScriptParser::Import::Library) {
+        url.replace(QLatin1Char('.'), QLatin1Char('/'));
+        bool found = false;
+        QString dir;
+
+
+        foreach (const QString &p, database->fileImportPath) {
+            dir = p+QLatin1Char('/')+url;
+
+            QFileInfo fi(dir+QLatin1String("/qmldir"));
+            const QString absoluteFilePath = fi.absoluteFilePath();
+
+            if (fi.isFile()) {
+                found = true;
+
+                url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+                uri = resolvedUri(dir, database);
+                if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString))
+                    return false;
+                break;
+            }
+        }
+
+        if (!found) {
+            found = QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin);
+            if (!found) {
+                if (errorString) {
+                    bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1);
+                    if (anyversion)
+                        *errorString = 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);
+                }
+                return false;
+            }
+        }
+    } else {
+
+        if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) {
+            QUrl importUrl = base.resolved(QUrl(uri + QLatin1String("/qmldir")));
+            QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl);
+            if (!localFileOrQrc.isEmpty()) {
+                QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
+                if (dir.isEmpty() || !QDir().exists(dir)) {
+                    if (errorString)
+                        *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg);
+                    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))
+                        return false;
+                }
+            } else {
+                if (prefix.isEmpty()) {
+                    // directory must at least exist for valid import
+                    QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
+                    if (localFileOrQrc.isEmpty() || !QDir().exists(localFileOrQrc)) {
+                        if (errorString) {
+                            if (localFileOrQrc.isEmpty())
+                                *errorString = QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri);
+                            else
+                                *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri);
+                        }
+                        return false;
+                    }
+                }
+            }
+        }
+
+        url = base.resolved(QUrl(url)).toString();
+        if (url.endsWith(QLatin1Char('/')))
+            url.chop(1);
+    }
+
+    if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) {
+        QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin();
+        for (; it != qmldircomponents.end(); ++it) {
+            if (it->majorVersion > vmaj || (it->majorVersion == vmaj && it->minorVersion >= vmin))
+                break;
+        }
+        if (it == qmldircomponents.end()) {
+            *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin);
+            return false;
+        }
+    }
+
+    s->uris.prepend(uri);
+    s->urls.prepend(url);
+    s->majversions.prepend(vmaj);
+    s->minversions.prepend(vmin);
+    s->isLibrary.prepend(importType == QDeclarativeScriptParser::Import::Library);
+    s->qmlDirComponents.prepend(qmldircomponents);
+    return true;
+}
+
+bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
+                                      QUrl* url_return, QString *errorString)
+{
+    QDeclarativeImportedNamespace *s = 0;
+    int slash = type.indexOf('/');
+    if (slash >= 0) {
+        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);
+            return false;
+        }
+        int nslash = type.indexOf('/',slash+1);
+        if (nslash > 0) {
+            if (errorString)
+                *errorString = QDeclarativeImportDatabase::tr("- nested namespaces not allowed");
+            return false;
+        }
+    } else {
+        s = &unqualifiedset;
+    }
+    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))
+            return true;
+        if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) {
+            // qualified, and only 1 url
+            *url_return = QUrl(s->urls[0]+QLatin1Char('/')).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml")));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const QString& type)
+{
+    return set.value(type);
+}
+
+bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
+          QUrl* url_return, QUrl *base, QString *errorString)
+{
+    bool typeRecursionDetected = false;
+    for (int i=0; i<urls.count(); ++i) {
+        if (find_helper(i, type, vmajor, vminor, type_return, url_return, base, &typeRecursionDetected)) {
+            if (qmlCheckTypes()) {
+                // 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) {
+                            QString u1 = urls.at(i);
+                            QString u2 = urls.at(j);
+                            if (base) {
+                                QString b = base->toString();
+                                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");
+                                }
+                            }
+
+                            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));
+                        }
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+    }
+    if (errorString) {
+        if (typeRecursionDetected)
+            *errorString = QDeclarativeImportDatabase::tr("is instantiated recursively");
+        else
+            *errorString = QDeclarativeImportDatabase::tr("is not a type");
+    }
+    return false;
+}
+
+QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e)
+: engine(e)
+{
+    filePluginPath << QLatin1String(".");
+
+    // Search order is applicationDirPath(), $QML_IMPORT_PATH, QLibraryInfo::ImportsPath
+
+    addImportPath(QLibraryInfo::location(QLibraryInfo::ImportsPath));
+
+    // env import paths
+    QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
+    if (!envImportPath.isEmpty()) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+        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 QDeclarativeImportDatabase::addToImport(QDeclarativeImports* imports, 
+                                             const QDeclarativeDirComponents &qmldircomponentsnetwork, 
+                                             const QString& uri, const QString& prefix, int vmaj, int vmin, 
+                                             QDeclarativeScriptParser::Import::Type importType, 
+                                             QString *errorString) 
+{
+    if (qmlImportTrace())
+        qDebug().nospace() << "QDeclarativeImportDatabase::addToImport " << imports << " " << uri << " " 
+                           << vmaj << '.' << vmin << " " 
+                           << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") 
+                           << " as " << prefix;
+
+    bool ok = imports->d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, this, errorString);
+    return ok;
+}
+
+/*!
+  \internal
+
+  Using the given \a imports, the given (namespace qualified) \a type is resolved to either
+  a QDeclarativeImportedNamespace stored at \a ns_return,
+  a QDeclarativeType stored at \a type_return, or
+  a component located at \a url_return.
+
+  If any return pointer is 0, the corresponding search is not done.
+
+  \sa addToImport()
+*/
+bool QDeclarativeImportDatabase::resolveType(const QDeclarativeImports& imports, const QByteArray& type, 
+                                             QDeclarativeType** type_return, QUrl* url_return, int *vmaj, int *vmin,
+                                             QDeclarativeImportedNamespace** ns_return, QString *errorString) const
+{
+    QDeclarativeImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type));
+    if (ns) {
+        if (ns_return)
+            *ns_return = ns;
+        return true;
+    }
+    if (type_return || url_return) {
+        if (imports.d->find(type,vmaj,vmin,type_return,url_return, errorString)) {
+            if (qmlImportTrace()) {
+                if (type_return && *type_return && url_return && !url_return->isEmpty())
+                    qDebug() << "QDeclarativeImportDatabase::resolveType" << type << '=' << (*type_return)->typeName() << *url_return;
+                if (type_return && *type_return)
+                    qDebug() << "QDeclarativeImportDatabase::resolveType" << type << '=' << (*type_return)->typeName();
+                if (url_return && !url_return->isEmpty())
+                    qDebug() << "QDeclarativeImportDatabase::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 QDeclarativeImportDatabase::resolveTypeInNamespace(QDeclarativeImportedNamespace* ns, const QByteArray& type, 
+                                                        QDeclarativeType** type_return, QUrl* url_return, 
+                                                        int *vmaj, int *vmin) const
+{
+    return ns->find(type,vmaj,vmin,type_return,url_return);
+}
+
+/*!
+  \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(const QDir &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)
+                resolvedPath = qmldirPath.absoluteFilePath(qmldirPluginPath);
+            else
+                resolvedPath = qmldirPath.absolutePath();
+        } else {
+            resolvedPath = pluginPath;
+        }
+
+        // hack for resources, should probably go away
+        if (resolvedPath.startsWith(QLatin1Char(':')))
+            resolvedPath = QCoreApplication::applicationDirPath();
+
+        QDir dir(resolvedPath);
+        foreach (const QString &suffix, suffixes) {
+            QString pluginFileName = prefix;
+
+            pluginFileName += baseName;
+            pluginFileName += suffix;
+
+            QFileInfo fileInfo(dir, pluginFileName);
+
+            if (fileInfo.exists())
+                return fileInfo.absoluteFilePath();
+        }
+    }
+
+    if (qmlImportTrace())
+        qDebug() << "QDeclarativeImportDatabase::resolvePlugin: Could not resolve plugin" << baseName 
+                 << "in" << qmldirPath.absolutePath();
+
+    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
+  \row \i Symbian     \i \c .dll
+  \endtable
+
+  Version number on unix are ignored.
+*/
+QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, 
+                                                  const QString &baseName)
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+    return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,
+                         QStringList()
+# ifdef QT_DEBUG
+                         << QLatin1String("d.dll") // try a qmake-style debug build first
+# endif
+                         << QLatin1String(".dll"));
+#elif defined(Q_OS_SYMBIAN)
+    return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,
+                         QStringList()
+                         << QLatin1String(".dll")
+                         << QLatin1String(".qtplugin"));
+#else
+
+# if defined(Q_OS_DARWIN)
+
+    return resolvePlugin(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(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
+# endif
+
+#endif
+}
+
+QStringList QDeclarativeImportDatabase::pluginPathList() const
+{
+    return filePluginPath;
+}
+
+void QDeclarativeImportDatabase::setPluginPathList(const QStringList &paths)
+{
+    filePluginPath = paths;
+}
+
+void QDeclarativeImportDatabase::addPluginPath(const QString& path)
+{
+    if (qmlImportTrace())
+        qDebug() << "QDeclarativeImportDatabase::addPluginPath" << path;
+
+    QUrl url = QUrl(path);
+    if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) {
+        QDir dir = QDir(path);
+        filePluginPath.prepend(dir.canonicalPath());
+    } else {
+        filePluginPath.prepend(path);
+    }
+}
+
+void QDeclarativeImportDatabase::addImportPath(const QString& path)
+{
+    if (qmlImportTrace())
+        qDebug() << "QDeclarativeImportDatabase::addImportPath" << path;
+
+    if (path.isEmpty())
+        return;
+
+    QUrl url = QUrl(path);
+    QString cPath;
+
+    if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) {
+        QDir dir = QDir(path);
+        cPath = dir.canonicalPath();
+    } else {
+        cPath = path;
+    }
+
+    if (!cPath.isEmpty()
+        && !fileImportPath.contains(cPath))
+        fileImportPath.prepend(cPath);
+}
+
+QStringList QDeclarativeImportDatabase::importPathList() const
+{
+    return fileImportPath;
+}
+
+void QDeclarativeImportDatabase::setImportPathList(const QStringList &paths)
+{
+    fileImportPath = paths;
+}
+
+
+bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
+{
+    if (qmlImportTrace())
+        qDebug() << "QDeclarativeImportDatabase::importPlugin" << uri << "from" << filePath;
+
+    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) {
+        QPluginLoader loader(absoluteFilePath);
+
+        if (!loader.load()) {
+            if (errorString)
+                *errorString = loader.errorString();
+            return false;
+        }
+
+        if (QDeclarativeExtensionInterface *iface = qobject_cast<QDeclarativeExtensionInterface *>(loader.instance())) {
+
+            const QByteArray bytes = uri.toUtf8();
+            const char *moduleId = bytes.constData();
+            if (!typesRegistered) {
+
+                // ### 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.
+
+                // protect against double initialization
+                initializedPlugins.insert(absoluteFilePath);
+                iface->initializeEngine(engine, moduleId);
+            }
+        } else {
+            if (errorString)
+                *errorString = loader.errorString();
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+QT_END_NAMESPACE