diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2021-03-01 10:11:18 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-03-04 23:35:39 +0100 |
| commit | ce52c245aaccf3183ef4759882e25b51b539195a (patch) | |
| tree | 5229da9fac5299d95671e551bd2e513942b71d02 /src | |
| parent | 3881f0df3d115ba8e59a5cedea970f3b085aa84a (diff) | |
Add a "prefer" directive to qmldir
The argument is the path from which further files from the module should
be loaded. This allows us to load potentially pre-compiled files
from a resource contained in a plugin. The qmldir file has to be stored
outside the plugin in order for the QML engine to find it, but the QML
files can now be stored inside the plugin.
[ChangeLog][QtQml] You can now specify that QML files in a QML module
should be loaded from a different place than the directory where the
qmldir file is found. To do this, add a "prefer" directive to the qmldir
file. The most useful application of this is adding the QML files as
resources to a plugin, and using qmlcachegen to pre-compile them. You
can then add their path inside the resource file system as "prefer"
path in order to make the engine load the pre-compiled files. The plain
files should still be installed next to the qmldir file so that they
remain visible to tooling.
Change-Id: Ib281b39230621b3762432095a47fb499412cbaa6
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc | 16 | ||||
| -rw-r--r-- | src/qml/qml/qqmlimport.cpp | 14 | ||||
| -rw-r--r-- | src/qml/qml/qqmltypeloaderqmldircontent.cpp | 5 | ||||
| -rw-r--r-- | src/qml/qml/qqmltypeloaderqmldircontent_p.h | 1 | ||||
| -rw-r--r-- | src/qml/qmldirparser/qqmldirparser.cpp | 27 | ||||
| -rw-r--r-- | src/qml/qmldirparser/qqmldirparser_p.h | 2 |
6 files changed, 63 insertions, 2 deletions
diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc index 8f6aa0ae7c..95e8a179de 100644 --- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc +++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc @@ -296,6 +296,22 @@ designersupported The items of an unsupported plugin are not painted in the Qt Quick Designer, but they are still available as empty boxes and the properties can be edited. + \row + \li + \code +prefer <Path> + \endcode + + \li This property directs the QML engine to load any further files for this + module from <path>, rather than the current directory. This can be used + to load files compiled with qmlcachegen. + + For example, you can add a module's QML files as resources to a resource + path \c{:/my/path/MyModule/}. Then, add \c{prefer :/my/path/MyModule} to + the qmldir file in order to use the files in the resource system, rather + than the ones in the file system. If you then use qmlcachegen for those, + the pre-compiled files will be available to any clients of the module. + \endtable Each command in a \c qmldir file must be on a separate line. diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 535b6713ba..0016d4bcc4 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -654,8 +654,18 @@ bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) { - Q_ASSERT(resolvedUrl.endsWith(Slash)); - url = resolvedUrl; + + const QString preferredPath = qmldir.preferredPath(); + if (preferredPath.isEmpty()) { + Q_ASSERT(resolvedUrl.endsWith(Slash)); + url = resolvedUrl; + } else { + Q_ASSERT(preferredPath.endsWith(Slash)); + if (preferredPath.startsWith(u':')) + url = QStringLiteral("qrc") + preferredPath; + else + url = QUrl::fromLocalFile(preferredPath).toString(); + } qmlDirComponents = qmldir.components(); diff --git a/src/qml/qml/qqmltypeloaderqmldircontent.cpp b/src/qml/qml/qqmltypeloaderqmldircontent.cpp index 0eddf796d7..ca9f5fc80d 100644 --- a/src/qml/qml/qqmltypeloaderqmldircontent.cpp +++ b/src/qml/qml/qqmltypeloaderqmldircontent.cpp @@ -115,6 +115,11 @@ QString QQmlTypeLoaderQmldirContent::qmldirLocation() const return m_location; } +QString QQmlTypeLoaderQmldirContent::preferredPath() const +{ + return m_parser.preferredPath(); +} + bool QQmlTypeLoaderQmldirContent::designerSupported() const { return m_parser.designerSupported(); diff --git a/src/qml/qml/qqmltypeloaderqmldircontent_p.h b/src/qml/qml/qqmltypeloaderqmldircontent_p.h index f9b68f3410..11f98b5c63 100644 --- a/src/qml/qml/qqmltypeloaderqmldircontent_p.h +++ b/src/qml/qml/qqmltypeloaderqmldircontent_p.h @@ -81,6 +81,7 @@ public: QQmlDirImports imports() const; QString qmldirLocation() const; + QString preferredPath() const; bool designerSupported() const; diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp index 403c04b1e1..1dbf35f1d3 100644 --- a/src/qml/qmldirparser/qqmldirparser.cpp +++ b/src/qml/qmldirparser/qqmldirparser.cpp @@ -299,6 +299,28 @@ bool QQmlDirParser::parse(const QString &source) || sections[0] == QLatin1String("depends")) { if (!readImport(sections, sectionCount, Import::Default)) continue; + } else if (sections[0] == QLatin1String("prefer")) { + if (sectionCount < 2) { + reportError(lineNumber, 0, + QStringLiteral("prefer directive requires one argument, " + "but %1 were provided").arg(sectionCount - 1)); + continue; + } + + if (!_preferredPath.isEmpty()) { + reportError(lineNumber, 0, QStringLiteral( + "only one prefer directive may be defined in a qmldir file")); + continue; + } + + if (!sections[1].endsWith(u'/')) { + // Yes. People should realize it's a directory. + reportError(lineNumber, 0, QStringLiteral( + "the preferred directory has to end with a '/'")); + continue; + } + + _preferredPath = sections[1]; } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) const Component entry(sections[0], sections[1], QTypeRevision()); @@ -416,6 +438,11 @@ QStringList QQmlDirParser::classNames() const return _classNames; } +QString QQmlDirParser::preferredPath() const +{ + return _preferredPath; +} + QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component) { const QString output = QStringLiteral("{%1 %2.%3}") diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h index d71dbfe9dc..eabaceae91 100644 --- a/src/qml/qmldirparser/qqmldirparser_p.h +++ b/src/qml/qmldirparser/qqmldirparser_p.h @@ -160,6 +160,7 @@ public: QStringList typeInfos() const; QStringList classNames() const; + QString preferredPath() const; private: bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true); @@ -168,6 +169,7 @@ private: private: QList<QQmlJS::DiagnosticMessage> _errors; QString _typeNamespace; + QString _preferredPath; QMultiHash<QString,Component> _components; QList<Import> _dependencies; QList<Import> _imports; |
