aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2011-07-15 17:19:17 +1000
committerQt by Nokia <qt-info@nokia.com>2011-08-30 13:18:28 +0200
commit7ab665fe61b4fe28fdb141fa66509b3addd55623 (patch)
tree3478c4a2c0f9fc22247cf6a9136bf1f1a2c81b36 /src/declarative/qml
parent275149f704436fc1115fb337a5803e86f7fce9cf (diff)
Cache QML import directories and qmldir files.
Also a little less toUtf8(). Change-Id: Iefb255fad9e27553f29b184418e66ce317f1cd89 Reviewed-on: http://codereview.qt.nokia.com/3748 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com> Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp3
-rw-r--r--src/declarative/qml/qdeclarativedirparser.cpp35
-rw-r--r--src/declarative/qml/qdeclarativedirparser_p.h8
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp132
-rw-r--r--src/declarative/qml/qdeclarativeimport_p.h3
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp2
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h2
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp125
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h10
-rw-r--r--src/declarative/qml/v4/qdeclarativev4compiler_p.h1
10 files changed, 225 insertions, 96 deletions
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index a597d1b3ce..0f78b0c960 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -2950,11 +2950,10 @@ bool QDeclarativeCompiler::completeComponentBuild()
aliasObject = compileState->aliasingObjects.next(aliasObject))
COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
- QDeclarativeV4Compiler::Expression expr;
+ QDeclarativeV4Compiler::Expression expr(unit->imports());
expr.component = compileState->root;
expr.ids = &compileState->ids;
expr.importCache = output->importCache;
- expr.imports = unit->imports();
QDeclarativeV4Compiler bindingCompiler;
diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp
index ba7aca038d..6798870b53 100644
--- a/src/declarative/qml/qdeclarativedirparser.cpp
+++ b/src/declarative/qml/qdeclarativedirparser.cpp
@@ -41,8 +41,10 @@
#include "private/qdeclarativedirparser_p.h"
#include "qdeclarativeerror.h"
+#include <private/qdeclarativeglobal_p.h>
#include <QtCore/QTextStream>
+#include <QtCore/QFile>
#include <QtCore/QtDebug>
QT_BEGIN_NAMESPACE
@@ -66,6 +68,16 @@ void QDeclarativeDirParser::setUrl(const QUrl &url)
_url = url;
}
+QString QDeclarativeDirParser::fileSource() const
+{
+ return _filePathSouce;
+}
+
+void QDeclarativeDirParser::setFileSource(const QString &filePath)
+{
+ _filePathSouce = filePath;
+}
+
QString QDeclarativeDirParser::source() const
{
return _source;
@@ -92,6 +104,23 @@ bool QDeclarativeDirParser::parse()
_plugins.clear();
_components.clear();
+ if (_source.isEmpty() && !_filePathSouce.isEmpty()) {
+ QFile file(_filePathSouce);
+ if (!QDeclarative_isFileCaseCorrect(_filePathSouce)) {
+ QDeclarativeError error;
+ error.setDescription(QString::fromUtf8("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(_url.toString()).arg(_filePathSouce));
+ _errors.prepend(error);
+ return false;
+ } else if (file.open(QFile::ReadOnly)) {
+ _source = QString::fromUtf8(file.readAll());
+ } else {
+ QDeclarativeError error;
+ error.setDescription(QString::fromUtf8("module \"%1\" definition \"%2\" not readable").arg(_url.toString()).arg(_filePathSouce));
+ _errors.prepend(error);
+ return false;
+ }
+ }
+
QTextStream stream(&_source);
int lineNumber = 0;
@@ -157,7 +186,7 @@ bool QDeclarativeDirParser::parse()
QString::fromUtf8("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
- Component entry(sections[1], sections[2], -1, -1);
+ Component entry(sections[1].toUtf8(), sections[2], -1, -1);
entry.internal = true;
_components.append(entry);
} else if (sections[0] == QLatin1String("typeinfo")) {
@@ -173,7 +202,7 @@ bool QDeclarativeDirParser::parse()
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
- const Component entry(sections[0], sections[1], -1, -1);
+ const Component entry(sections[0].toUtf8(), sections[1], -1, -1);
_components.append(entry);
} else if (sectionCount == 3) {
const QString &version = sections[1];
@@ -191,7 +220,7 @@ bool QDeclarativeDirParser::parse()
const int minorVersion = version.mid(dotIndex + 1).toInt(&validVersionNumber);
if (validVersionNumber) {
- const Component entry(sections[0], sections[2], majorVersion, minorVersion);
+ const Component entry(sections[0].toUtf8(), sections[2], majorVersion, minorVersion);
_components.append(entry);
}
diff --git a/src/declarative/qml/qdeclarativedirparser_p.h b/src/declarative/qml/qdeclarativedirparser_p.h
index d40833ac45..a5df5b44fe 100644
--- a/src/declarative/qml/qdeclarativedirparser_p.h
+++ b/src/declarative/qml/qdeclarativedirparser_p.h
@@ -70,6 +70,9 @@ public:
QUrl url() const;
void setUrl(const QUrl &url);
+ QString fileSource() const;
+ void setFileSource(const QString &filePath);
+
QString source() const;
void setSource(const QString &source);
@@ -95,11 +98,11 @@ public:
Component()
: majorVersion(0), minorVersion(0), internal(false) {}
- Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion)
+ Component(const QByteArray &typeName, const QString &fileName, int majorVersion, int minorVersion)
: typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion),
internal(false) {}
- QString typeName;
+ QByteArray typeName;
QString fileName;
int majorVersion;
int minorVersion;
@@ -129,6 +132,7 @@ private:
QList<QDeclarativeError> _errors;
QUrl _url;
QString _source;
+ QString _filePathSouce;
QList<Component> _components;
QList<Plugin> _plugins;
#ifdef QT_CREATOR
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index a28428ca24..89b6814ade 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -71,7 +71,7 @@ Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores
class QDeclarativeImportedNamespace
{
public:
- QStringList uris;
+ QList<QByteArray> uris;
QStringList urls;
QList<int> majversions;
QList<int> minversions;
@@ -79,16 +79,16 @@ public:
QList<QDeclarativeDirComponents> qmlDirComponents;
- bool find_helper(int i, const QByteArray& type, int *vmajor, int *vminor,
+ bool find_helper(QDeclarativeTypeLoader *typeLoader, 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,
+ bool find(QDeclarativeTypeLoader *typeLoader, const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
QUrl* url_return, QUrl *base = 0, QList<QDeclarativeError> *errors = 0);
};
class QDeclarativeImportsPrivate {
public:
- QDeclarativeImportsPrivate();
+ QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader);
~QDeclarativeImportsPrivate();
bool importExtension(const QString &absoluteFilePath, const QString &uri,
@@ -111,6 +111,7 @@ public:
QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded;
QDeclarativeImportedNamespace unqualifiedset;
QHash<QString,QDeclarativeImportedNamespace* > set;
+ QDeclarativeTypeLoader *typeLoader;
};
/*!
@@ -134,8 +135,8 @@ QDeclarativeImports::operator =(const QDeclarativeImports &copy)
return *this;
}
-QDeclarativeImports::QDeclarativeImports()
-: d(new QDeclarativeImportsPrivate)
+QDeclarativeImports::QDeclarativeImports(QDeclarativeTypeLoader *typeLoader)
+ : d(new QDeclarativeImportsPrivate(typeLoader))
{
}
@@ -166,7 +167,7 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
const QDeclarativeImportedNamespace &set = d->unqualifiedset;
for (int ii = set.uris.count() - 1; ii >= 0; --ii) {
- const QByteArray uri = set.uris.at(ii).toUtf8(); // XXX sigh
+ const QByteArray uri = set.uris.at(ii);
int majversion = set.majversions.at(ii);
int minversion = set.minversions.at(ii);
QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(uri, majversion);
@@ -180,7 +181,7 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
const QDeclarativeImportedNamespace &set = *iter.value();
QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
for (int ii = set.uris.count() - 1; ii >= 0; --ii) {
- const QByteArray uri = set.uris.at(ii).toUtf8(); // XXX sigh
+ const QByteArray uri = set.uris.at(ii);
int majversion = set.majversions.at(ii);
int minversion = set.minversions.at(ii);
QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(uri, majversion);
@@ -261,21 +262,18 @@ bool QDeclarativeImports::resolveType(QDeclarativeImportedNamespace* ns, const Q
QDeclarativeType** type_return, QUrl* url_return,
int *vmaj, int *vmin) const
{
- return ns->find(type,vmaj,vmin,type_return,url_return);
+ return ns->find(d->typeLoader,type,vmaj,vmin,type_return,url_return);
}
-bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, int *vmajor, int *vminor,
+bool QDeclarativeImportedNamespace::find_helper(QDeclarativeTypeLoader *typeLoader, 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);
+ int vmaj = data.majversion;
+ int vmin = data.minversion;
if (vmaj >= 0 && vmin >= 0) {
- QByteArray qt = uris.at(i).toUtf8();
- qt += '/';
- qt += type;
-
+ QString qt = data.uri + QLatin1Char('/') + type;
QDeclarativeType *t = QDeclarativeMetaType::qmlType(qt,vmaj,vmin);
if (t) {
if (vmajor) *vmajor = vmaj;
@@ -286,18 +284,16 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i
}
}
- 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) {
+ if (c.typeName == type) {
typeWasDeclaredInQmldir = true;
// importing version -1 means import ALL versions
if ((vmaj == -1) || (c.majorVersion == vmaj && vmin >= c.minorVersion)) {
+ QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml"));
QUrl candidate = url.resolved(QUrl(c.fileName));
if (c.internal && base) {
if (base->resolved(QUrl(c.fileName)) != candidate)
@@ -318,8 +314,9 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i
if (!typeWasDeclaredInQmldir && !isLibrary.at(i)) {
// XXX search non-files too! (eg. zip files, see QT-524)
- QFileInfo f(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url));
- if (f.exists()) {
+ QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml"));
+ QString file = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (!typeLoader->absoluteFilePath(file).isEmpty()) {
if (base && *base == url) { // no recursion
if (typeRecursionDetected)
*typeRecursionDetected = true;
@@ -333,8 +330,8 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i
return false;
}
-QDeclarativeImportsPrivate::QDeclarativeImportsPrivate()
-: ref(1)
+QDeclarativeImportsPrivate::QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader)
+ : ref(1), typeLoader(loader)
{
}
@@ -348,50 +345,24 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
QDeclarativeImportDatabase *database,
QDeclarativeDirComponents* components, QList<QDeclarativeError> *errors)
{
- QFile file(absoluteFilePath);
- QString filecontent;
- if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) {
+ const QDeclarativeDirParser *qmldirParser = typeLoader->qmlDirParser(absoluteFilePath);
+ if (qmldirParser->hasError()) {
if (errors) {
- QDeclarativeError error;
- error.setDescription(QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath));
- errors->prepend(error);
- }
- return false;
- } else if (file.open(QFile::ReadOnly)) {
- filecontent = QString::fromUtf8(file.readAll());
- if (qmlImportTrace())
- qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: "
- << "loaded " << absoluteFilePath;
- } else {
- if (errors) {
- QDeclarativeError error;
- error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath));
- errors->prepend(error);
+ for (int i = 0; i < qmldirParser->errors().size(); ++i)
+ errors->prepend(qmldirParser->errors().at(i));
}
return false;
}
- QDir dir = QFileInfo(file).dir();
- QUrl url = QUrl::fromLocalFile(absoluteFilePath);
-
- QDeclarativeDirParser qmldirParser;
- qmldirParser.setSource(filecontent);
- qmldirParser.setUrl(url);
- // propagate any errors reported by the parser back up to the typeloader.
- if (qmldirParser.parse()) {
- if (errors) {
- for (int i = 0; i < qmldirParser.errors().size(); ++i) {
- errors->prepend(qmldirParser.errors().at(i));
- }
- }
- return false;
- }
+ if (qmlImportTrace())
+ qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: "
+ << "loaded " << absoluteFilePath;
if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) {
qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath);
-
- foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) {
+ QDir dir = QFileInfo(absoluteFilePath).dir();
+ foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser->plugins()) {
QString resolvedFilePath = database->resolvePlugin(dir, plugin.path, plugin.name);
#if defined(QT_LIBINFIX) && defined(Q_OS_SYMBIAN)
@@ -410,7 +381,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
QDeclarativeError poppedError = errors->takeFirst();
QDeclarativeError error;
error.setDescription(QDeclarativeImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(poppedError.description()));
- error.setUrl(url);
+ error.setUrl(QUrl::fromLocalFile(absoluteFilePath));
errors->prepend(error);
}
return false;
@@ -419,7 +390,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
if (errors) {
QDeclarativeError error;
error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name));
- error.setUrl(url);
+ error.setUrl(QUrl::fromLocalFile(absoluteFilePath));
errors->prepend(error);
}
return false;
@@ -428,7 +399,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
}
if (components)
- *components = qmldirParser.components();
+ *components = qmldirParser->components();
return true;
}
@@ -488,11 +459,11 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
url.replace(QLatin1Char('.'), QLatin1Char('/'));
bool found = false;
QString dir;
+ QString qmldir;
// step 1: search for extension with fully encoded version number
- if (!found) {
- foreach (const QString &p, database->fileImportPath) {
- dir = p+QLatin1Char('/')+url;
+ 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();
@@ -509,9 +480,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
}
// step 2: search for extension with encoded version major
- if (!found) {
- foreach (const QString &p, database->fileImportPath) {
- dir = p+QLatin1Char('/')+url;
+ 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();
@@ -532,14 +502,13 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
foreach (const QString &p, database->fileImportPath) {
dir = p+QLatin1Char('/')+url;
+ qmldir = dir+QLatin1String("/qmldir");
- QFileInfo fi(dir+QLatin1String("/qmldir"));
- const QString absoluteFilePath = fi.absoluteFilePath();
-
- if (fi.isFile()) {
+ QString absoluteFilePath = typeLoader->absoluteFilePath(qmldir);
+ if (!absoluteFilePath.isEmpty()) {
found = true;
-
- url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+ QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(QLatin1Char('/')));
+ url = QUrl::fromLocalFile(absolutePath).toString();
uri = resolvedUri(dir, database);
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
return false;
@@ -564,7 +533,6 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
return false;
}
} else {
-
if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) {
QUrl importUrl = base.resolved(QUrl(uri + QLatin1String("/qmldir")));
QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl);
@@ -583,7 +551,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
uri = resolvedUri(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))), database);
if (uri.endsWith(QLatin1Char('/')))
uri.chop(1);
- if (QFile::exists(localFileOrQrc)) {
+ if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) {
if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errors))
return false;
}
@@ -633,7 +601,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
}
}
- s->uris.prepend(uri);
+ s->uris.prepend(uri.toUtf8());
s->urls.prepend(url);
s->majversions.prepend(vmaj);
s->minversions.prepend(vmin);
@@ -672,7 +640,7 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *
}
QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower)
if (s) {
- if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors))
+ if (s->find(typeLoader,unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors))
return true;
if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) {
// qualified, and only 1 url
@@ -689,16 +657,16 @@ QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const Q
return set.value(type);
}
-bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
+bool QDeclarativeImportedNamespace::find(QDeclarativeTypeLoader *typeLoader, const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return,
QUrl* url_return, QUrl *base, QList<QDeclarativeError> *errors)
{
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 (find_helper(typeLoader, 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 (find_helper(typeLoader, j, type, vmajor, vminor, 0, 0, base)) {
if (errors) {
QString u1 = urls.at(i);
QString u2 = urls.at(j);
@@ -872,7 +840,6 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const
// 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;
@@ -1122,5 +1089,4 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt
#endif
}
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeimport_p.h b/src/declarative/qml/qdeclarativeimport_p.h
index fe9404d9b2..d3e4933f8b 100644
--- a/src/declarative/qml/qdeclarativeimport_p.h
+++ b/src/declarative/qml/qdeclarativeimport_p.h
@@ -68,11 +68,12 @@ class QDir;
class QDeclarativeImportedNamespace;
class QDeclarativeImportsPrivate;
class QDeclarativeImportDatabase;
+class QDeclarativeTypeLoader;
class QDeclarativeImports
{
public:
- QDeclarativeImports();
+ QDeclarativeImports(QDeclarativeTypeLoader *);
QDeclarativeImports(const QDeclarativeImports &);
~QDeclarativeImports();
QDeclarativeImports &operator=(const QDeclarativeImports &);
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index da7be11545..bd4b935483 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -504,7 +504,7 @@ const QString &QDeclarativeType::elementName() const
return d->m_elementName;
}
-QByteArray QDeclarativeType::qmlTypeName() const
+const QByteArray &QDeclarativeType::qmlTypeName() const
{
return d->m_name;
}
diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h
index ca1d869850..239b7ca480 100644
--- a/src/declarative/qml/qdeclarativemetatype_p.h
+++ b/src/declarative/qml/qdeclarativemetatype_p.h
@@ -137,7 +137,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeType
{
public:
QByteArray typeName() const;
- QByteArray qmlTypeName() const;
+ const QByteArray &qmlTypeName() const;
const QString &elementName() const;
QByteArray module() const;
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index 6bda993038..6b9dfc11bc 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -51,9 +51,70 @@
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
+#include <QtCore/qdiriterator.h>
+
+#if defined (Q_OS_UNIX)
+#include <sys/types.h>
+#include <dirent.h>
+#endif
QT_BEGIN_NAMESPACE
+
+/*
+Returns the set of QML files in path (qmldir, *.qml, *.js). The caller
+is responsible for deleting the returned data.
+*/
+#if defined (Q_OS_UNIX)
+static QStringHash<bool> *qmlFilesInDirectory(const QString &path)
+{
+ QByteArray name(QFile::encodeName(path));
+ DIR *dd = opendir(name);
+ if (!dd)
+ return 0;
+
+ struct dirent *result;
+ union {
+ struct dirent d;
+ char b[offsetof (struct dirent, d_name) + NAME_MAX + 1];
+ } u;
+
+ QStringHash<bool> *files = new QStringHash<bool>;
+ while (readdir_r(dd, &u.d, &result) == 0 && result != 0) {
+ if (!strcmp(u.d.d_name, "qmldir")) {
+ files->insert(QLatin1String("qmldir"), true);
+ continue;
+ }
+ int len = strlen(u.d.d_name);
+ if (len < 4)
+ continue;
+ if (!strcmp(u.d.d_name+len-4, ".qml") || !strcmp(u.d.d_name+len-3, ".js"))
+ files->insert(QFile::decodeName(u.d.d_name), true);
+ }
+
+ closedir(dd);
+ return files;
+}
+#else
+static QStringHash<bool> *qmlFilesInDirectory(const QString &path)
+{
+ QDirIterator dir(path, QDir::Files);
+ if (!dir.hasNext())
+ return 0;
+ QStringHash<bool> *files = new QStringHash<bool>;
+ while (dir.hasNext()) {
+ dir.next();
+ QString fileName = dir.fileName();
+ if (fileName == QLatin1String("qmldir")
+ || fileName.endsWith(QLatin1String(".qml"))
+ || fileName.endsWith(QLatin1String(".js")))
+ files->insert(fileName, true);
+ }
+ return files;
+}
+#endif
+
+
/*!
\class QDeclarativeDataBlob
\brief The QDeclarativeDataBlob encapsulates a data request that can be issued to a QDeclarativeDataLoader.
@@ -723,6 +784,60 @@ QDeclarativeQmldirData *QDeclarativeTypeLoader::getQmldir(const QUrl &url)
}
/*!
+Returns the absolute filename of path via a directory cache for files named
+"qmldir", "*.qml", "*.js"
+Returns a empty string if the path does not exist.
+*/
+QString QDeclarativeTypeLoader::absoluteFilePath(const QString &path)
+{
+ if (path.isEmpty())
+ return QString();
+ if (path.at(0) == QLatin1Char(':')) {
+ // qrc resource
+ QFileInfo fileInfo(path);
+ return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
+ }
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ QStringRef dirPath(&path, 0, lastSlash);
+
+ StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length()));
+ if (!fileSet) {
+ QHashedString dirPathString(dirPath.toString());
+ StringSet *files = qmlFilesInDirectory(dirPathString);
+ m_importDirCache.insert(dirPathString, files);
+ fileSet = m_importDirCache.value(dirPathString);
+ }
+ if (!(*fileSet))
+ return QString();
+
+ QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(path.constData()+lastSlash+1, path.length()-lastSlash-1)) ? path : QString();
+ if (absoluteFilePath.length() > 2 && absoluteFilePath.at(0) != QLatin1Char('/') && absoluteFilePath.at(1) != QLatin1Char(':'))
+ absoluteFilePath = QFileInfo(absoluteFilePath).absoluteFilePath();
+
+ return absoluteFilePath;
+}
+
+/*!
+Return a QDeclarativeDirParser for absoluteFilePath. The QDeclarativeDirParser may be cached.
+*/
+const QDeclarativeDirParser *QDeclarativeTypeLoader::qmlDirParser(const QString &absoluteFilePath)
+{
+ QDeclarativeDirParser *qmldirParser;
+ QDeclarativeDirParser **val = m_importQmlDirCache.value(absoluteFilePath);
+ if (!val) {
+ qmldirParser = new QDeclarativeDirParser;
+ qmldirParser->setFileSource(absoluteFilePath);
+ qmldirParser->setUrl(QUrl::fromLocalFile(absoluteFilePath));
+ qmldirParser->parse();
+ m_importQmlDirCache.insert(absoluteFilePath, qmldirParser);
+ } else {
+ qmldirParser = *val;
+ }
+
+ return qmldirParser;
+}
+
+/*!
Clears cached information about loaded files, including any type data, scripts
and qmldir information.
*/
@@ -734,17 +849,21 @@ void QDeclarativeTypeLoader::clearCache()
(*iter)->release();
for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter)
(*iter)->release();
+ qDeleteAll(m_importDirCache);
+ qDeleteAll(m_importQmlDirCache);
m_typeCache.clear();
m_scriptCache.clear();
m_qmldirCache.clear();
+ m_importDirCache.clear();
+ m_importQmlDirCache.clear();
}
QDeclarativeTypeData::QDeclarativeTypeData(const QUrl &url, QDeclarativeTypeLoader::Options options,
QDeclarativeTypeLoader *manager)
-: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_typesResolved(false),
- m_compiledData(0), m_typeLoader(manager)
+: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_imports(manager), m_typesResolved(false),
+ m_compiledData(0), m_typeLoader(manager)
{
}
@@ -1104,7 +1223,7 @@ void QDeclarativeScriptData::clear()
QDeclarativeScriptBlob::QDeclarativeScriptBlob(const QUrl &url, QDeclarativeTypeLoader *loader)
: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeParser::Object::ScriptBlock::None),
- m_scriptData(0), m_typeLoader(loader)
+ m_imports(loader), m_scriptData(0), m_typeLoader(loader)
{
}
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 1ca6f8c9c2..a090f255f8 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -62,6 +62,7 @@
#include <private/qdeclarativescriptparser_p.h>
#include <private/qdeclarativedirparser_p.h>
#include <private/qdeclarativeimport_p.h>
+#include "private/qhashedstring_p.h"
#include <private/qv8_p.h>
@@ -202,14 +203,23 @@ public:
QDeclarativeScriptBlob *getScript(const QUrl &);
QDeclarativeQmldirData *getQmldir(const QUrl &);
+
+ QString absoluteFilePath(const QString &path);
+ const QDeclarativeDirParser *qmlDirParser(const QString &absoluteFilePath);
+
private:
typedef QHash<QUrl, QDeclarativeTypeData *> TypeCache;
typedef QHash<QUrl, QDeclarativeScriptBlob *> ScriptCache;
typedef QHash<QUrl, QDeclarativeQmldirData *> QmldirCache;
+ typedef QStringHash<bool> StringSet;
+ typedef QStringHash<StringSet*> ImportDirCache;
+ typedef QStringHash<QDeclarativeDirParser*> ImportQmlDirCache;
TypeCache m_typeCache;
ScriptCache m_scriptCache;
QmldirCache m_qmldirCache;
+ ImportDirCache m_importDirCache;
+ ImportQmlDirCache m_importQmlDirCache;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeTypeLoader::Options)
diff --git a/src/declarative/qml/v4/qdeclarativev4compiler_p.h b/src/declarative/qml/v4/qdeclarativev4compiler_p.h
index bf53fef940..292519b066 100644
--- a/src/declarative/qml/v4/qdeclarativev4compiler_p.h
+++ b/src/declarative/qml/v4/qdeclarativev4compiler_p.h
@@ -74,6 +74,7 @@ public:
struct Expression
{
+ Expression(const QDeclarativeImports &imp) : imports(imp) {}
QDeclarativeParser::Object *component;
QDeclarativeParser::Object *context;
QDeclarativeParser::Property *property;