aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlimport_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlimport_p.h')
-rw-r--r--src/qml/qml/qqmlimport_p.h125
1 files changed, 115 insertions, 10 deletions
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 33f5eaf04a..946f36b398 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -44,7 +44,9 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtCore/qstringlist.h>
+#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlerror.h>
+#include <QtQml/qqmlfile.h>
#include <private/qqmldirparser_p.h>
#include <private/qqmltype_p.h>
#include <private/qstringhash_p.h>
@@ -174,16 +176,6 @@ public:
QQmlImportDatabase *importDb, const QString &uri, const QString &prefix,
const QString &qmldirIdentifier, const QString &qmldirUrl, QList<QQmlError> *errors);
- enum LocalQmldirResult {
- QmldirFound,
- QmldirNotFound,
- QmldirInterceptedToRemote
- };
-
- LocalQmldirResult locateLocalQmldir(
- QQmlImportDatabase *, const QString &uri, QTypeRevision version,
- QString *qmldirFilePath, QString *url);
-
void populateCache(QQmlTypeNameCache *cache) const;
struct ScriptReference
@@ -225,6 +217,13 @@ class Q_QML_PRIVATE_EXPORT QQmlImportDatabase
public:
enum PathType { Local, Remote, LocalOrRemote };
+ enum LocalQmldirResult {
+ QmldirFound,
+ QmldirNotFound,
+ QmldirInterceptedToRemote,
+ QmldirRejected
+ };
+
QQmlImportDatabase(QQmlEngine *);
~QQmlImportDatabase();
@@ -239,12 +238,18 @@ public:
void setPluginPathList(const QStringList &paths);
void addPluginPath(const QString& path);
+ template<typename Callback>
+ LocalQmldirResult locateLocalQmldir(
+ const QString &uri, QTypeRevision version, const Callback &callback);
+
static QTypeRevision lockModule(const QString &uri, const QString &typeNamespace,
QTypeRevision version, QList<QQmlError> *errors);
private:
friend class QQmlImportsPrivate;
friend class QQmlPluginImporter;
+
+ QString absoluteFilePath(const QString &path) const;
void clearDirCache();
struct QmldirCache {
@@ -266,6 +271,106 @@ private:
QQmlEngine *engine;
};
+template<typename Callback>
+QQmlImportDatabase::LocalQmldirResult QQmlImportDatabase::locateLocalQmldir(
+ const QString &uri, QTypeRevision version, const Callback &callback)
+{
+ // Check cache first
+
+ LocalQmldirResult result = QmldirNotFound;
+ QmldirCache *cacheHead = nullptr;
+ {
+ QmldirCache **cachePtr = qmldirCache.value(uri);
+ if (cachePtr) {
+ cacheHead = *cachePtr;
+ QmldirCache *cache = cacheHead;
+ while (cache) {
+ if (cache->version == version) {
+ if (cache->qmldirFilePath.isEmpty())
+ return QmldirNotFound;
+ if (callback(cache->qmldirFilePath, cache->qmldirPathUrl))
+ return QmldirFound;
+ result = QmldirRejected;
+ }
+ cache = cache->next;
+ }
+ }
+ }
+
+ // Do not try to construct the cache if it already had any entries for the URI.
+ // Otherwise we might duplicate cache entries.
+ if (result != QmldirNotFound)
+ return result;
+
+ const bool hasInterceptors = !engine->urlInterceptors().isEmpty();
+
+ // Interceptor might redirect remote files to local ones.
+ QStringList localImportPaths = importPathList(hasInterceptors ? LocalOrRemote : Local);
+
+ // Search local import paths for a matching version
+ const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(
+ uri, localImportPaths, version);
+
+ for (QString qmldirPath : qmlDirPaths) {
+ if (hasInterceptors) {
+ const QUrl intercepted = engine->interceptUrl(
+ QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
+ QQmlAbstractUrlInterceptor::QmldirFile);
+ qmldirPath = QQmlFile::urlToLocalFileOrQrc(intercepted);
+ if (result != QmldirInterceptedToRemote
+ && qmldirPath.isEmpty()
+ && !QQmlFile::isLocalFile(intercepted)) {
+ result = QmldirInterceptedToRemote;
+ }
+ }
+
+ QString qmldirAbsoluteFilePath = absoluteFilePath(qmldirPath);
+ if (!qmldirAbsoluteFilePath.isEmpty()) {
+ QString url;
+ const QString absolutePath = qmldirAbsoluteFilePath.left(
+ qmldirAbsoluteFilePath.lastIndexOf(u'/') + 1);
+ if (absolutePath.at(0) == u':') {
+ url = QStringLiteral("qrc") + absolutePath;
+ } else {
+ url = QUrl::fromLocalFile(absolutePath).toString();
+ // This handles the UNC path case as when the path is retrieved from the QUrl it
+ // will convert the host name from upper case to lower case. So the absoluteFilePath
+ // is changed at this point to make sure it will match later on in that case.
+ if (qmldirAbsoluteFilePath.startsWith(QStringLiteral("//"))) {
+ qmldirAbsoluteFilePath = QUrl::fromLocalFile(qmldirAbsoluteFilePath)
+ .toString(QUrl::RemoveScheme);
+ }
+ }
+
+ QmldirCache *cache = new QmldirCache;
+ cache->version = version;
+ cache->qmldirFilePath = qmldirAbsoluteFilePath;
+ cache->qmldirPathUrl = url;
+ cache->next = cacheHead;
+ qmldirCache.insert(uri, cache);
+ cacheHead = cache;
+
+ if (result != QmldirFound) {
+ result = callback(qmldirAbsoluteFilePath, url)
+ ? QmldirFound
+ : QmldirRejected;
+ }
+
+ // Do not return here. Rather, construct the complete cache for this URI.
+ }
+ }
+
+ // Nothing found? Add an empty cache entry to signal that for further requests.
+ if (result == QmldirNotFound) {
+ QmldirCache *cache = new QmldirCache;
+ cache->version = version;
+ cache->next = cacheHead;
+ qmldirCache.insert(uri, cache);
+ }
+
+ return result;
+}
+
void qmlClearEnginePlugins();// For internal use by qmlClearRegisteredProperties
QT_END_NAMESPACE