Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativeimport.cpp
index 539f1b8..8bdcef9 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** 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.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 #include <private/qdeclarativetypenamecache_p.h>
 #include <private/qdeclarativeengine_p.h>
 
-#ifdef Q_OS_SYMBIAN
-#include "private/qcore_symbian_p.h"
-#endif
-
 QT_BEGIN_NAMESPACE
 
 DEFINE_BOOL_CONFIG_OPTION(qmlImportTrace, QML_IMPORT_TRACE)
@@ -98,6 +94,7 @@ public:
         int minversion;
         bool isLibrary;
         QDeclarativeDirComponents qmlDirComponents;
+        QDeclarativeDirScripts qmlDirScripts;
     };
     QList<Data> imports;
 
@@ -116,12 +113,13 @@ public:
 
     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, QDeclarativeScriptParser::Import::Type importType, 
+             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);
@@ -203,29 +201,60 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
          ++iter) {
 
         const QDeclarativeImportedNamespace &set = *iter.value();
-        QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
         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)
+            if (module) {
+                QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
                 import.modules.append(QDeclarativeTypeModuleVersion(module, data.minversion));
+            }
 
-            QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(data.uri.toUtf8(), data.majversion, 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);
-                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);
-                }
-                import.moduleApi = a;
+                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;
 }
 
 /*!
@@ -363,9 +392,11 @@ QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate()
         delete s;
 }
 
-bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri, 
-                                                 QDeclarativeImportDatabase *database, 
-                                                 QDeclarativeDirComponents* components, QList<QDeclarativeError> *errors)
+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()) {
@@ -391,13 +422,6 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
         foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser->plugins()) {
 
             QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name);
-#if defined(QT_LIBINFIX) && defined(Q_OS_SYMBIAN)
-            if (resolvedFilePath.isEmpty()) {
-                // In case of libinfixed build, attempt to load libinfixed version, too.
-                QString infixedPluginName = plugin.name + QLatin1String(QT_LIBINFIX);
-                resolvedFilePath = database->resolvePlugin(dir, plugin.path, infixedPluginName);
-            }
-#endif
             if (!resolvedFilePath.isEmpty()) {
                 if (!database->importPlugin(resolvedFilePath, uri, errors)) {
                     if (errors) {
@@ -426,6 +450,8 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
 
     if (components)
         *components = qmldirParser->components();
+    if (scripts)
+        *scripts = qmldirParser->scripts();
 
     return true;
 }
@@ -463,13 +489,14 @@ 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, 
+                                     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()) {
@@ -481,7 +508,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
     }
     QString url = uri;
     bool versionFound = false;
-    if (importType == QDeclarativeScriptParser::Import::Library) {
+    if (importType == QDeclarativeScript::Import::Library) {
 
         Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries
 
@@ -500,14 +527,20 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
             if (fi.isFile()) {
                 found = true;
 
-                url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+                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, errors))
+                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;
@@ -518,9 +551,13 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
             if (fi.isFile()) {
                 found = true;
 
-                url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+                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, errors))
+                if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
                     return false;
                 break;
             }
@@ -537,9 +574,12 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
                 if (!absoluteFilePath.isEmpty()) {
                     found = true;
                     QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1);
-                    url = QLatin1String("file://") + absolutePath;
+                    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, errors))
+                    if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
                         return false;
                     break;
                 }
@@ -549,7 +589,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
         if (QDeclarativeMetaType::isModule(uri, vmaj, vmin))
             versionFound = true;
 
-        if (!versionFound && qmldircomponents.isEmpty()) {
+        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))
@@ -561,7 +601,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
             return false;
         }
     } else {
-        if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) {
+        if (importType == QDeclarativeScript::Import::File && qmldircomponents.isEmpty()) {
             QString importUrl = resolveLocalUrl(base, uri + Slash_qmldir);
             QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl);
             if (!localFileOrQrc.isEmpty()) {
@@ -579,7 +619,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
                 if (uri.endsWith(Slash))
                     uri.chop(1);
                 if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) {
-                    if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errors))
+                    if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,&qmldirscripts,errors))
                         return false;
                 }
             } else {
@@ -605,16 +645,18 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
         url = resolveLocalUrl(base, url);
     }
 
-    if (!versionFound && vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) {
-        QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin();
+    if (!versionFound && (vmaj > -1) && (vmin > -1) && !qmldircomponents.isEmpty()) {
         int lowest_min = INT_MAX;
         int highest_min = INT_MIN;
-        for (; it != qmldircomponents.end(); ++it) {
-            if (it->majorVersion == vmaj) {
-                lowest_min = qMin(lowest_min, it->minorVersion);
-                highest_min = qMax(highest_min, it->minorVersion);
+
+        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.
@@ -628,13 +670,44 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
     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 == QDeclarativeScriptParser::Import::Library;
+    data.isLibrary = importType == QDeclarativeScript::Import::Library;
     data.qmlDirComponents = qmldircomponents;
+    data.qmlDirScripts = scripts.values();
+
     s->imports.prepend(data);
 
     return true;
@@ -760,38 +833,13 @@ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e)
 
 #ifndef QT_NO_SETTINGS
     QString installImportsPath =  QLibraryInfo::location(QLibraryInfo::ImportsPath);
-
-#if defined(Q_OS_SYMBIAN)
-    // Append imports path for all available drives in Symbian
-    if (installImportsPath.at(1) != QChar(QLatin1Char(':'))) {
-        QString tempPath = installImportsPath;
-        if (tempPath.at(tempPath.length() - 1) != QDir::separator()) {
-            tempPath += QDir::separator();
-        }
-        RFs& fs = qt_s60GetRFs();
-        TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData()));
-        TFindFile finder(fs);
-        TInt err = finder.FindByDir(tempPathPtr, tempPathPtr);
-        while (err == KErrNone) {
-            QString foundDir(reinterpret_cast<const QChar *>(finder.File().Ptr()),
-                             finder.File().Length());
-            foundDir = QDir(foundDir).canonicalPath();
-            addImportPath(foundDir);
-            err = finder.Find();
-        }
-    } else {
-        addImportPath(installImportsPath);
-    }
-#else
     addImportPath(installImportsPath);
-#endif
-
 #endif // QT_NO_SETTINGS
 
     // env import paths
     QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
     if (!envImportPath.isEmpty()) {
-#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+#if defined(Q_OS_WIN)
         QLatin1Char pathSep(';');
 #else
         QLatin1Char pathSep(':');
@@ -824,14 +872,14 @@ QDeclarativeImportDatabase::~QDeclarativeImportDatabase()
 */
 bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb, 
                                     const QString& uri, const QString& prefix, int vmaj, int vmin, 
-                                    QDeclarativeScriptParser::Import::Type importType, 
+                                    QDeclarativeScript::Import::Type importType, 
                                     const QDeclarativeDirComponents &qmldircomponentsnetwork, 
                                     QList<QDeclarativeError> *errors)
 {
     if (qmlImportTrace())
         qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::addImport: " 
                            << uri << " " << vmaj << '.' << vmin << " " 
-                           << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") 
+                           << (importType==QDeclarativeScript::Import::Library? "Library" : "File") 
                            << " as " << prefix;
 
     return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errors);
@@ -908,7 +956,6 @@ QString QDeclarativeImportDatabase::resolvePlugin(QDeclarativeTypeLoader *typeLo
   \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.
@@ -924,11 +971,6 @@ QString QDeclarativeImportDatabase::resolvePlugin(QDeclarativeTypeLoader *typeLo
                          << QLatin1String("d.dll") // try a qmake-style debug build first
 # endif
                          << QLatin1String(".dll"));
-#elif defined(Q_OS_SYMBIAN)
-    return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
-                         QStringList()
-                         << QLatin1String(".dll")
-                         << QLatin1String(".qtplugin"));
 #else
 
 # if defined(Q_OS_DARWIN)
@@ -1076,7 +1118,7 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt
         if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) {
             if (errors) {
                 QDeclarativeError error;
-                error.setDescription(tr("File name case mismatch for \"%2\"").arg(absoluteFilePath));
+                error.setDescription(tr("File name case mismatch for \"%1\"").arg(absoluteFilePath));
                 errors->prepend(error);
             }
             return false;
@@ -1092,22 +1134,29 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt
             return false;
         }
 
-        if (QDeclarativeExtensionInterface *iface = qobject_cast<QDeclarativeExtensionInterface *>(loader.instance())) {
+        QObject *instance = loader.instance();
+        if (QDeclarativeTypesExtensionInterface *iface = qobject_cast<QDeclarativeExtensionInterface *>(instance)) {
 
             const QByteArray bytes = uri.toUtf8();
             const char *moduleId = bytes.constData();
             if (!typesRegistered) {
 
-                // ### this code should probably be protected with a mutex.
+                // 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.
-
-                // protect against double initialization
+                // things on the engine (eg. adding new global objects) have to be done for every 
+                // engine.  
+                // XXX protect against double initialization
                 initializedPlugins.insert(absoluteFilePath);
-                iface->initializeEngine(engine, moduleId);
+
+                QDeclarativeExtensionInterface *eiface = 
+                    qobject_cast<QDeclarativeExtensionInterface *>(instance);
+                if (eiface) {
+                    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+                    ep->typeLoader.initializeEngine(eiface, moduleId);
+                }
             }
         } else {
             if (errors) {