Solved More then one qmldir file?
-
Hello,
it seems not possible to have multiple directories with a qmldir file in each. Here's a short Test:
My file structure looks like this:Colors1\ Colors1.qml qmldir Colors2\ Colors2.qml qmldir main.qml
And the contents of the files:
Colors1/Colors1.qml:pragma Singleton import QtQuick 2.0 QtObject { property color background: "black" }
Colors1/qmldir:
singleton Colors1 Colors1.qml
Colors2/Colors2.qml:
pragma Singleton import QtQuick 2.0 QtObject { property color foreground: "red" }
Colors2/qmldir:
singleton Colors2 Colors2.qml
main.qml:
import QtQuick 2.6 import QtQuick.Controls 1.5 import "." // this import is needed cause of QTBUG-34418 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("QrcTest") color: Colors1.background Text { anchors.centerIn: parent color: Colors2.foreground text: "Hello world!" } }
When I run this project it outputs the error:
qrc:/main.qml:15: ReferenceError: Colors2 is not defined
When I remove Colors1.qrc from RESOURCES definition in project and run the project again (with a forced rebuild before) it outputs the Error:
qrc:/main.qml:11: ReferenceError: Colors1 is not defined
which is correct but Color2 is now defined and works as expected.
Isn't it possible to have multiple qmldir files in one project? -
How are your resources organized? Are you using aliases/prefixes, or multiple .qrc files? Could you paste the contents of the .qrc file? I would expect you to import "Colors1" and "Colors2". If you can access the singleton(s) via import "." then the problem might be in the resource tree, which doesn't reflect the directory tree on the file system? Perhaps one qmldir file quietly overrides the other?
-
@jpnurmi Oh, yes I forgot the qrc files. In each of Colors1/Colors2 I have a colors1.qrc or colors2.qrc respectively.
colors1.qrc:<RCC> <qresource prefix="/"> <file>Colors1.qml</file> <file>qmldir</file> </qresource> </RCC>
colors2.qrc
<RCC> <qresource prefix="/"> <file>Colors2.qml</file> <file>qmldir</file> </qresource> </RCC>
So no aliases nor prefixes.
One overrides the other is what I think too. I noticed it's also not possible to have multiple qrc files with the same name. They override each other no matter in which directory they are. (I think it's a bug in qmake.)
The problem with qmldir files is that I can't rename them.
Is there a workaround? Perhaps with modules? -
You have two
.qrc
files that both have aqmldir
file with prefix/
. Thus, you have two instances of:/qmldir
.Either you will have to specify the prefixes (*):
Colors1/colors1.qrc:
<RCC> <qresource prefix="/Colors1"> <file>Colors1.qml</file> <file>qmldir</file> </qresource> </RCC>
Colors2/colors2.qrc:
<RCC> <qresource prefix="/Colors2"> <file>Colors2.qml</file> <file>qmldir</file> </qresource> </RCC>
Or alternatively, you get unique names if you have those listed in the same
.qrc
like this:/colors.qrc:
<RCC> <qresource prefix="/"> <file>Colors1/Colors1.qml</file> <file>Colors1/qmldir</file> <file>Colors2/Colors2.qml</file> <file>Colors2/qmldir</file> </qresource> </RCC>
Furthermore, in QML, you will import "Colors1" and "Colors2", respectively.
(*) The name of the directory where a
.qrc
file is located at build time does not matter. -
@jpnurmi I just tested your first alternative. I had to add the import statements for the new prefixes but now it works. Thanks! I never played with prefixes cause I didn't really know what they are good for.
My first approach was to import them as modules but it didn't work cause of the subdirectories. Do you know how to turn Colors1/Colors2 into modules which get imported like that:import Colors1 1.0
-
You could register the modules from C++, for example by using
qmlRegisterSingletonType()
for the singletons:int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterSingletonType(QUrl("qrc:/Colors1/Colors1.qml"), "Colors1", 1, 0, "Colors1"); qmlRegisterSingletonType(QUrl("qrc:/Colors2/Colors2.qml"), "Colors2", 1, 0, "Colors2"); QQmlApplicationEngine engine; engine.load("qrc:/main.qml"); return app.exec(); }
-
@jpnurmi OK that works as well. Thanks again!
I tried the qml way with a qmldir like that:module Colors1 singleton Colors1 1.0 Colors1.qml
That didn't work. I don't know why but the module wasn't found.
I would prefer that way cause it looks much cleaner and I wanted to keep it in qml.
Do you know the reason for the error:qrc:/main.qml:11: ReferenceError: Colors1 is not defined
-
So, quoted imports work for paths and URLs, and paths can be relative to the .qml file that contains the import. However, in order to import a QML module by its name instead, the QML engine must be able to locate the module in one of its import paths. You can add import paths using
QQmlEngine::addImportPath()
.Notice that this is the path that contains the module directory ie. not the module directory itself but its parent directory. In other words, a directory where the QML engine can locate a sub-directory by the name of the imported module.
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.addImportPath("qrc:/"); // if that's where the ColorsN folders are engine.load(...); return app.exec(); }
-
@jpnurmi With addImportPath it runs without error, but QtCreator still complains about the missing module Colors1 (Qml module not found (Colors1)). I added the line
QML_IMPORT_PATH = Colors1
but it didn't help. Even though the hint popup window which pops up when I hover the mouse pointer over the underlined import Colors1 1.0 line shows the correct import path.
-
Similarly to that
QQmlEngine::addImportPath()
should point to the path that contains the module directory, I'd assume the same for the Qt Creator'sQML_IMPORT_PATH
qmake variable. So perhaps something likeQML_IMPORT_PATH = $$PWD
orQML_IMPORT_PATH = .
? -
@jpnurmi All right, now everything works w/o any error. Thank you very much! I didn't know that it's so complicated and confusing.
To summarize:
If the goal is to have more than one qmldir files and everything should be stored in the resource system:
(Keep in mind getting it running has nothing to do with making QtCreator happy!)
To get it running:- A qrc file listing one of the qmldir files has to have a unique prefix. The name of the prefix doesn't matter, it even doesn't have to match the name of the containing directory! The prefix is the name of the module getting imported!
- The qmldir file doesn't even have to contain a line defining the name of the module!
To make QtCreator happy:
- The name of the module to be imported has to be equal to the name of the directory the qmldir file lives in
- The QML_IMPORT_PATH (BTW: QML2_IMPORT_PATH doesn't work at all.) has to point to the parent of that directory.
Example:
Directory structure (The uppercase letters at the end of "Colors"/"colors" are just to show which names have to match and which don't. It should work without these letters as well.):ColorsA colorsB.qrc ColorsC.qml qmldir qml.qrc main.qml Test.pro
colorsB.qrc:
<RCC> <qresource prefix="/ColorsA"> <file>ColorsC.qml</file> <file>qmldir</file> </qresource> </RCC>
ColorsC.qml:
pragma Singleton import QtQuick 2.0 QtObject { property color background: "black" }
qmldir:
module ColorsA singleton ColorsD 1.0 ColorsC.qml
qml.qrc:
<RCC> <qresource prefix="/"> <file>main.qml</file> </qresource> </RCC>
main.qml:
import QtQuick.Controls 1.0 import ColorsA 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Test") color: ColorsD.background }
... QML_IMPORT_PATH = . ...