summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativeengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativeengine.cpp')
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp122
1 files changed, 73 insertions, 49 deletions
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 1a40857..2f0ec24 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -69,8 +69,6 @@
#include "qdeclarativelist_p.h"
#include "qdeclarativetypenamecache_p.h"
-#include <qfxperf_p_p.h>
-
#include <QtCore/qmetaobject.h>
#include <QScriptClass>
#include <QNetworkReply>
@@ -220,7 +218,6 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr
// XXX When the above a done some better way, that way should also be
// XXX used to add Qt.Sound class.
-
//types
qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4));
qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4));
@@ -1377,9 +1374,10 @@ struct QDeclarativeEnginePrivate::ImportedNamespace {
QList<int> majversions;
QList<int> minversions;
QList<bool> isLibrary;
- QList<QString> qmlDirContent;
+ QList<QDeclarativeDirComponents> qmlDirComponents;
- bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return)
+ bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return,
+ QUrl *base = 0)
{
for (int i=0; i<urls.count(); ++i) {
int vmaj = majversions.at(i);
@@ -1399,23 +1397,22 @@ struct QDeclarativeEnginePrivate::ImportedNamespace {
}
QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml"));
- QString qmldircontent = qmlDirContent.at(i);
+ QDeclarativeDirComponents qmldircomponents = qmlDirComponents.at(i);
bool typeWasDeclaredInQmldir = false;
- if (!qmldircontent.isEmpty()) {
+ if (!qmldircomponents.isEmpty()) {
const QString typeName = QString::fromUtf8(type);
-
- QDeclarativeDirParser qmldirParser;
- qmldirParser.setUrl(url);
- qmldirParser.setSource(qmldircontent);
- qmldirParser.parse();
-
- foreach (const QDeclarativeDirParser::Component &c, qmldirParser.components()) { // ### TODO: cache the components
+ foreach (const QDeclarativeDirParser::Component &c, qmldircomponents) {
if (c.typeName == typeName) {
typeWasDeclaredInQmldir = true;
if (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 (url_return)
- *url_return = url.resolved(QUrl(c.fileName));
+ *url_return = candidate;
return true;
}
}
@@ -1436,6 +1433,11 @@ struct QDeclarativeEnginePrivate::ImportedNamespace {
}
};
+static bool greaterThan(const QString &s1, const QString &s2)
+{
+ return s1 > s2;
+}
+
class QDeclarativeImportsPrivate {
public:
QDeclarativeImportsPrivate() : ref(1)
@@ -1450,22 +1452,22 @@ public:
QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded;
- QString importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine) {
+ QDeclarativeDirComponents importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine) {
QFile file(absoluteFilePath);
QString dir = QFileInfo(file).path();
- QString qmldircontent;
+ QString filecontent;
if (file.open(QFile::ReadOnly)) {
- qmldircontent = QString::fromUtf8(file.readAll());
+ filecontent = QString::fromUtf8(file.readAll());
if (qmlImportTrace())
qDebug() << "QDeclarativeEngine::add: loaded" << absoluteFilePath;
}
+ QDeclarativeDirParser qmldirParser;
+ qmldirParser.setSource(filecontent);
+ qmldirParser.parse();
if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) {
qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath);
- QDeclarativeDirParser qmldirParser;
- qmldirParser.setSource(qmldircontent);
- qmldirParser.parse();
foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) {
QDir pluginDir(dir + QDir::separator() + plugin.path);
@@ -1481,7 +1483,7 @@ public:
}
}
}
- return qmldircontent;
+ return qmldirParser.components();
}
QString resolvedUri(const QString &dir_arg, QDeclarativeEngine *engine)
@@ -1513,6 +1515,8 @@ public:
// add fileImportPath last, this is *not* search order.
paths += QDeclarativeEnginePrivate::get(engine)->fileImportPath;
+ qSort(paths.begin(), paths.end(), greaterThan); // Ensure subdirs preceed their parents.
+
QString stableRelativePath = dir;
foreach( QString path, paths) {
if (dir.startsWith(path)) {
@@ -1528,9 +1532,9 @@ public:
- bool add(const QUrl& base, const QString &qmldircontentnetwork, const QString& uri_arg, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, QDeclarativeEngine *engine)
+ bool add(const QUrl& base, const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri_arg, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, QDeclarativeEngine *engine, QString *errorString)
{
- QString qmldircontent = qmldircontentnetwork;
+ QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork;
QString uri = uri_arg;
QDeclarativeEnginePrivate::ImportedNamespace *s;
if (prefix.isEmpty()) {
@@ -1563,11 +1567,11 @@ public:
paths += applicationDirPath;
paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath;
- #if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
+#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
- #else
+#else
QString builtinPath;
- #endif
+#endif
if (!builtinPath.isEmpty())
paths += builtinPath;
@@ -1582,24 +1586,57 @@ public:
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, engine);
- qmldircontent = importExtension(absoluteFilePath, uri, engine);
+ qmldircomponents = importExtension(absoluteFilePath, uri, engine);
break;
}
}
+ if (!found) {
+ found = QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin);
+ if (!found) {
+ if (errorString) {
+ bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), 0, 0);
+ if (anyversion)
+ *errorString = QDeclarativeEngine::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin);
+ else
+ *errorString = QDeclarativeEngine::tr("module \"%1\" is not installed").arg(uri_arg);
+ }
+ return false;
+ }
+ }
} else {
- if (importType == QDeclarativeScriptParser::Import::File && qmldircontent.isEmpty()) {
+ if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) {
QUrl importUrl = base.resolved(QUrl(uri + QLatin1String("/qmldir")));
QString localFileOrQrc = toLocalFileOrQrc(importUrl);
if (!localFileOrQrc.isEmpty()) {
+ QString dir = toLocalFileOrQrc(base.resolved(QUrl(uri)));
+ if (dir.isEmpty() || !QDir().exists(dir)) {
+ if (errorString)
+ *errorString = QDeclarativeEngine::tr("\"%1\": no such directory").arg(uri_arg);
+ return false; // local import dirs must exist
+ }
uri = resolvedUri(toLocalFileOrQrc(base.resolved(QUrl(uri))), engine);
- qmldircontent = importExtension(localFileOrQrc,
+ qmldircomponents = importExtension(localFileOrQrc,
uri,
engine);
if (uri.endsWith(QLatin1Char('/')))
uri.chop(1);
+ } else {
+ if (prefix.isEmpty()) {
+ // directory must at least exist for valid import
+ QString localFileOrQrc = toLocalFileOrQrc(base.resolved(QUrl(uri)));
+ if (localFileOrQrc.isEmpty() || !QDir().exists(localFileOrQrc)) {
+ if (errorString) {
+ if (localFileOrQrc.isEmpty())
+ *errorString = QDeclarativeEngine::tr("import \"%1\" has no qmldir and no namespace").arg(uri);
+ else
+ *errorString = QDeclarativeEngine::tr("\"%1\": no such directory").arg(uri);
+ }
+ return false;
+ }
+ }
}
}
@@ -1613,7 +1650,7 @@ public:
s->majversions.prepend(vmaj);
s->minversions.prepend(vmin);
s->isLibrary.prepend(importType == QDeclarativeScriptParser::Import::Library);
- s->qmlDirContent.prepend(qmldircontent);
+ s->qmlDirComponents.prepend(qmldircomponents);
return true;
}
@@ -1633,7 +1670,7 @@ public:
}
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))
+ if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base))
return true;
if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) {
// qualified, and only 1 url
@@ -1643,16 +1680,7 @@ public:
}
-
- /* now comes really nasty code. It makes "private" types load in the remote case, but
- it does this by breaking the import order. This must go. Instead private types must
- be marked private in the qmldir. */
- if (url_return) {
- *url_return = base.resolved(QUrl(QString::fromUtf8(type + ".qml")));
- return true;
- } else {
- return false;
- }
+ return false;
}
QDeclarativeEnginePrivate::ImportedNamespace *findNamespace(const QString& type)
@@ -1722,12 +1750,10 @@ static QDeclarativeTypeNameCache *cacheForNamespace(QDeclarativeEngine *engine,
return cache;
}
-QDeclarativeTypeNameCache *QDeclarativeEnginePrivate::Imports::cache(QDeclarativeEngine *engine) const
+void QDeclarativeEnginePrivate::Imports::cache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const
{
const QDeclarativeEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
- QDeclarativeTypeNameCache *cache = new QDeclarativeTypeNameCache(engine);
-
for (QHash<QString,QDeclarativeEnginePrivate::ImportedNamespace* >::ConstIterator iter = d->set.begin();
iter != d->set.end(); ++iter) {
@@ -1743,8 +1769,6 @@ QDeclarativeTypeNameCache *QDeclarativeEnginePrivate::Imports::cache(QDeclarativ
}
cacheForNamespace(engine, set, cache);
-
- return cache;
}
/*
@@ -1986,12 +2010,12 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString
The base URL must already have been set with Import::setBaseUrl().
*/
-bool QDeclarativeEnginePrivate::addToImport(Imports* imports, const QString &qmldircontentnetwork, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const
+bool QDeclarativeEnginePrivate::addToImport(Imports* imports, const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, QString *errorString) const
{
QDeclarativeEngine *engine = QDeclarativeEnginePrivate::get(const_cast<QDeclarativeEnginePrivate *>(this));
if (qmlImportTrace())
qDebug().nospace() << "QDeclarativeEngine::addToImport " << imports << " " << uri << " " << vmaj << '.' << vmin << " " << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") << " as " << prefix;
- bool ok = imports->d->add(imports->d->base,qmldircontentnetwork, uri,prefix,vmaj,vmin,importType, engine);
+ bool ok = imports->d->add(imports->d->base,qmldircomponentsnetwork, uri,prefix,vmaj,vmin,importType, engine, errorString);
return ok;
}