Fix QML import paths in Qt resources.
authorAaron McCarthy <aaron.mccarthy@nokia.com>
Mon, 23 Jul 2012 00:59:30 +0000 (10:59 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 27 Jul 2012 01:29:12 +0000 (03:29 +0200)
Allow adding qrc: urls as import paths.
Store an import path of the form :/import/path as qrc:/import/path
which is expected by other parts of the code.

Update documentation for QQmlEngine::addImportPath() to explicitly
state what types of paths are supported.

Add auto tests to check that importing a module from a Qt resource
works.

Change-Id: If0e75c75078a608b20d7a5c4080bccf6241e97f6
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
src/qml/qml/qqmlengine.cpp
src/qml/qml/qqmlimport.cpp
src/qml/qml/qqmltypeloader.cpp
tests/auto/qml/qrcqml/data/imports/QrcImport/Imported.qml [new file with mode: 0644]
tests/auto/qml/qrcqml/data/imports/QrcImport/qmldir [new file with mode: 0644]
tests/auto/qml/qrcqml/data/importtest.qml [new file with mode: 0644]
tests/auto/qml/qrcqml/qrcqml.qrc
tests/auto/qml/qrcqml/tst_qrcqml.cpp

index 580aaf4..f9b261b 100644 (file)
@@ -1610,7 +1610,13 @@ void QQmlEnginePrivate::dereferenceScarceResources()
 /*!
   Adds \a path as a directory where the engine searches for
   installed modules in a URL-based directory structure.
-  The \a path may be a local filesystem directory or a URL.
+
+  The \a path may be a local filesystem directory, a
+  \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
+  \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
+
+  The \a path will be converted into canonical form before it
+  is added to the import path list.
 
   The newly added \a path will be first in the importPathList().
 
index 55c07ac..20da154 100644 (file)
@@ -1536,6 +1536,11 @@ void QQmlImportDatabase::addImportPath(const QString& path)
 
     if (url.scheme() == QLatin1String("file")) {
         cPath = QQmlFile::urlToLocalFileOrQrc(url);
+    } else if (path.startsWith(QLatin1Char(':'))) {
+        // qrc directory, e.g. :/foo
+        // need to convert to a qrc url, e.g. qrc:/foo
+        cPath = QStringLiteral("qrc") + path;
+        cPath.replace(Backslash, Slash);
     } else if (url.isRelative() ||
                (url.scheme().length() == 1 && QFile::exists(path)) ) {  // windows path
         QDir dir = QDir(path);
index 1d70706..c66cd28 100644 (file)
@@ -1633,6 +1633,11 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path)
         // qrc resource
         QFileInfo fileInfo(path);
         return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
+    } else if (path.count() > 3 && path.at(3) == QLatin1Char(':') &&
+               path.startsWith(QLatin1String("qrc"), Qt::CaseInsensitive)) {
+        // qrc resource url
+        QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path));
+        return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
     }
     int lastSlash = path.lastIndexOf(QLatin1Char('/'));
     QStringRef dirPath(&path, 0, lastSlash);
diff --git a/tests/auto/qml/qrcqml/data/imports/QrcImport/Imported.qml b/tests/auto/qml/qrcqml/data/imports/QrcImport/Imported.qml
new file mode 100644 (file)
index 0000000..c2ef0a6
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+    property string tokenProperty: "bar"
+}
diff --git a/tests/auto/qml/qrcqml/data/imports/QrcImport/qmldir b/tests/auto/qml/qrcqml/data/imports/QrcImport/qmldir
new file mode 100644 (file)
index 0000000..8eb1fa5
--- /dev/null
@@ -0,0 +1 @@
+Imported 1.0 Imported.qml
diff --git a/tests/auto/qml/qrcqml/data/importtest.qml b/tests/auto/qml/qrcqml/data/importtest.qml
new file mode 100644 (file)
index 0000000..dd45bd8
--- /dev/null
@@ -0,0 +1,5 @@
+import QrcImport 1.0
+
+Imported {
+    tokenProperty: "foo"
+}
index 4ee303a..9ab0565 100644 (file)
@@ -1,19 +1,21 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
-    <file>data/main.qml</file>
-    <file>data/SameDir.qml</file>
-    <file>data/SubDir.qml</file>
-</qresource>
-<qresource>
-    <!-- unspecified prefix seems to mean '/' -->
-    <file alias="main.qml">data/main2.qml</file>
-    <file alias="SameDir.qml">data/SameDir2.qml</file>
-</qresource>
-<qresource prefix="/search">
-    <file alias="main.qml">data/main3.qml</file>
-    <file alias="SameDir.qml">data/SameDir3.qml</file>
-</qresource>
-<qresource prefix="/search/data">
-    <file alias="SubDir.qml">data/SubDir.qml</file>
-</qresource>
+<RCC>
+    <qresource prefix="/">
+        <file>data/main.qml</file>
+        <file>data/SameDir.qml</file>
+        <file>data/SubDir.qml</file>
+        <file alias="main.qml">data/main2.qml</file>
+        <file alias="SameDir.qml">data/SameDir2.qml</file>
+        <file alias="importtest.qml">data/importtest.qml</file>
+    </qresource>
+    <qresource prefix="/search">
+        <file alias="main.qml">data/main3.qml</file>
+        <file alias="SameDir.qml">data/SameDir3.qml</file>
+    </qresource>
+    <qresource prefix="/search/data">
+        <file alias="SubDir.qml">data/SubDir.qml</file>
+    </qresource>
+    <qresource prefix="/imports">
+        <file alias="QrcImport/Imported.qml">data/imports/QrcImport/Imported.qml</file>
+        <file alias="QrcImport/qmldir">data/imports/QrcImport/qmldir</file>
+    </qresource>
 </RCC>
index a09c908..37a7e78 100644 (file)
@@ -57,6 +57,8 @@ public:
 private slots:
     void basicLoad_data();
     void basicLoad();
+    void qrcImport_data();
+    void qrcImport();
 };
 
 tst_qrcqml::tst_qrcqml()
@@ -101,6 +103,35 @@ void tst_qrcqml::basicLoad()
     delete o;
 }
 
+void tst_qrcqml::qrcImport_data()
+{
+    QTest::addColumn<QString>("importPath");
+    QTest::addColumn<QString>("token");
+
+    QTest::newRow("qrc path")
+        << ":/imports"
+        << "foo";
+
+    QTest::newRow("qrc url")
+        << "qrc:/imports"
+        << "foo";
+}
+
+void tst_qrcqml::qrcImport()
+{
+    QFETCH(QString, importPath);
+    QFETCH(QString, token);
+
+    QQmlEngine e;
+    e.addImportPath(importPath);
+    QQmlComponent c(&e, QUrl("qrc:///importtest.qml"));
+    QVERIFY(c.isReady());
+    QObject *o = c.create();
+    QVERIFY(o);
+    QCOMPARE(o->property("tokenProperty").toString(), token);
+    delete o;
+}
+
 QTEST_MAIN(tst_qrcqml)
 
 #include "tst_qrcqml.moc"