qrc : cannot find file/directory issues - qt

I'm working on a project in which all .js and .qml files are stored in the Qt Resource file (.qrc). I've tried to import an external directory in a qml file. The external directory contains other .qml files for different purposes. I don't want to include these external directories into the .qrc file.
I get an error when I add the import path saying:
qrc:\example.qml : cannot find directory
Is there any way to include an external file or directory like this.

Found a solution in the Qt forum, http://qt-project.org/forums/viewthread/7047. For accessing any file outside QRC, use "absolute filepath" of the file.
For example:
In main.cpp file:
QString path = QDir::currentPath(); //path where the exec is present
If your file is in src/file.qml of exec folder, then you can access it like
(path += "/src/file.qml";), now path is the absolute file path for file.qml. You can access it in any of the QRC file.
QQuickView view;
view.rootContext()->setContextProperty("myFile", path);
view.setSource("qrc:/main.qml");
In main.qml file:
Loader
{
id: loadItem
source: myFile
}
Item
{
Component.onCompleted: loadItem.item
}

Related

How do I make my own directory in QT QML?

I'm trying to make a directory of a singleton QML File "All.qml" which I can import anywhere else into my project so that I can access its objects (namely the drawer). I made a qmldir file, in the same folder as the "All.qml", and even add the directory to the .qrc file.
The contents of the directory is as follows:
Module App.Drawer
singleton All 1.0 All.qml
But when I type in
import App.Drawer. 1.0
It says "module 'App.Drawer' not installed". I can't find any other way to access that drawer, as the project is huge with multiple folders and directories. Can anyone help me?
Also, this project has C++ integrated with it. I tried going and finding some file where maybe the other directories (there are other custom directories, which were made beforehand) have been installed, but couldn't find any.
You have to make sure that QEngine can find the qmldir file, and it has some specific requirements on where it will look.
First to make QEngine aware of the qmldir file you have to add an import path:
engine.addImportPath("qrc:/");
Your path may vary, read on:
The qmldir file has to placed in the folder structure dictated by module name. In your case it is <rootPath>/App/Drawer/qmldir. The "rootPath" is unknown to me, but let's assume you have the following in your qrc file:
<RCC>
<qresource prefix="/ProjectX/App/Drawer">
<file>Drawer.qml</file>
<file>qmldir</file>
</qresource>
</RCC>
Then "rootPath" is qrc:/ProjectX and the import call becomes:
engine.addImportPath("qrc:/ProjectX");
Also, the module declaration in qmldir should be the same as the folder structure where the qmldir file is placed. (And I think it should be lowercase)
module App.Drawer
singleton Drawer 1.0 Drawer.qml
If you want Qt Creator to also find the stuff you can use the QML2_IMPORT_PATH environment variable and set it to the correct folder using the same logic.
You can also place the files in the <Qt_installation_folder>/qml/App/Drawer but this means every project can use it and you have to keep it up-to-date during development, which might be overdone.
Edit
To see if your files are lined up correctly, you can add this debug code:
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}

Wrong work folder in Raspberry QtCreator

When I try to load a file by the relative path via QFile, gives file not found.
QFile file(fileName);
So I output the current work folder to find the problem like this:
qDebug()<<QDir(".").absolutePath();
Output: /home/username
qDebug()<<qApp->applicationDirPath();
Output: /home/username/program/testApp
The second one is the right path to the work folder. So I think QFile didn't load the file from the work folder but the Linux user folder ~. Why didn't QFile load the file refer to the work folder?
I guess this may be a bug in Raspberry's QtCreator. Because the QFile load file is working well if run in the console.
Use QStandardPaths to store data to your OS paths, in this way you would refer to consistent set of locations when you retrieve the file.
For instance:
auto path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QFile afile;
QString fileName = "/myfile.txt";
path += fileName;
afile.setFileName(path);

How can I add the qrc import path for qtquick plugin?

I have built a static Qt library and want to use it deploy my app with a standalone exe. After one day effort, I have known that the qtquick plugin can not be static include into exe.
I need copy some folders in qml folder to my exe directory to let the exe can show GUI.
So I want to know which file my exe need, I deleted files in those folders one by one to get it known. The real needed file is just a plugins.QMLTYPES file and a qmldir file.
And then I found the import path of QQmlApplicationEngine can be changed, I output the QQmlApplicationEngine.importPathList() and one of paths is just the qml folder in Qt installed path. So I think this is the place where Qt get the search path of plugins.QMLTYPES file and qmldir file.
If all I think is correct, I can just copy the folders I need into qrc file and use QQmlApplicationEngine.addImportPath("qrc:/foldersIwant") to let exe can import what it need on runtime. And because qrc is compiled into exe, I can get rid of those folders and let my exe standalone.
But after I do this in my code, app still can not find the files it need even the output of QQmlApplicationEngine.importPathList() has the path I put into and I have also checked my path according to Load qmldir from QRC file.
Here is the code:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath(QStringLiteral("qrc:/import/qtquick/"));
qDebug()<<engine.importPathList();
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
return app.exec();
}
Here is a part of my qrc file
Is there anything wrong in my deductive?
Further research:
I have add
engine.addImportPath(QDir::currentPath() + QDir::separator() + "custom");
and move all folders into custom folders, it can run successfully. And the exe which doesn't have this line can not run with custom folder. So I'm wondering the "search" behavior can not be applied to qrc file ?
Finally, I get the answer. The result shows all my thoughts are correct!
Below is what I had tried and you can just read the end to get the clear steps.
My aim is to compile a standalone qml2 application exe.
In qml1, I can build static Qt library and compile my app with it.
In qml2, the exe can be compiled in same way. But if I run it without Qt-Runtime. It just do not have any window shown on Windows OS (and also show nothing in other OS). I have googled so many informations and found this problem troubled many people since Qt5.0. Now it is Qt5.5, they still haven't repaired it. So I need copy folders in QT_INSTALLED_PREFIX/qml to the root directory of my app to let my app show GUI.
Althrough the problem will be solved in Qt5.6 (https://codereview.qt-project.org/#/c/114835/), I can't wait for so long (Qt5.6 will be released at the end of this year). So I decide to package the files by myself.
And I see this question by chance :Load qmldir from QRC file. It told me that qmldir file can be include into qrc file and the Qml engine can search into those directory. So I think, the QML files can also be included into qrc file.
But the first thing is to find where the qml2 be imported, when I looking into QQmlApplicationEngine's document, I found addImportPath function and I told myself that it must be the key of finding the import path. The document tells me everything:
QStringList QQmlEngine::importPathList()
const Returns the list of
directories where the engine searches for installed modules in a
URL-based directory structure.
For example, if /opt/MyApp/lib/imports is in the path, then QML that
imports com.mycompany.Feature will cause the QQmlEngine to look in
/opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
provided by that module. A qmldir file is required for defining the
type version mapping and possibly QML extensions plugins.
By default, the list contains the directory of the application
executable, paths specified in the QML2_IMPORT_PATH environment
variable, and the builtin Qml2ImportsPath from QLibraryInfo.
After I delete the Qml2ImportsPath in importPathList at runtime, I made a recurrence of the bugs that app do not show any GUI.
And the document of addImportPath tells my that it can accept qrc url. So I add all the files in qml just like the question described above. But I still cannot see any GUI.
After several days of thinking. I found the pic I posted in question do not have qmldir files! That's a bug of Qt Creator. I add files using Add Existing Directory... and set the filter to *, it still cannot include qmldir file. So I add it into qrc file by xml code.
When I think this time it must work, it just gave me nothing. Just when I was going to give up, a thought occurred : it won't waste me more time to check whether qrc:/import/qtquick/ is valid.
The result is false, there must be a mistake in my qrc usage. I change the prefix and save the qrc with Qt Creator. I found the qrc file cannot use the path like D:/Qt/Qt-5.5-static/qml/Qt/labs/folderlistmodel/plugins.qmltypes, it is changed by Qt Creator to Qt/labs/folderlistmodel/plugins.qmltypes. At this time, everything works perfect!
Thanks for you reading my story. Here is a conclusion of steps for solving this problem:
Copy all folders in QT_INSTALLED_PREFIX/qml to your project folder, it is good to put them under a parent folder not the root folder.
Write some code to get all files' relative path except the .lib files and
.prl files.
Create a new .qrc file and include it in .pro file. Include all files into this .qrc file. I wrote a small program to generate the xml.
Add the import path using addImportPath method of QQmlApplicationEngine.
Build and enjoy.

Qt linguist lupdate ignores qml files

When running lupdate none of the qsTr in the qml files are recognized. The resulting .ts file doesn't contain any translation context.
$ lupdate -verbose App.pro
Updating 'translations/en.ts'...
Found 0 source text(s) (0 new and 0 already existing)
The project should be set up correctly:
OTHER_FILES += \
content/main.qml
TRANSLATIONS += \
translations/en.ts
In the main.qml among other things:
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Open")
onTriggered: Qt.quit();
}
}
Menu {
title: qsTr("...")
MenuItem {
text: qsTr("About")
onTriggered: {
aboutApplicationDialog.open()
}
}
}
}
You can generate the translation file by running lupdate on QML file :
lupdate main.qml -ts main.ts
To get the .ts file by running lupdate on the project .pro file you can use a workaround. From the Qt documentation :
The lupdate tool extracts user interface strings from your
application. lupdate reads your application's .pro file to identify
which source files contain texts to be translated. This means your
source files must be listed in the SOURCES or HEADERS entry in the
.pro file. If your files are not listed the texts in them will not be
found.
However, the SOURCES variable is intended for C++ source files. If you
list QML or JavaScript source files there, the compiler tries to build
them as though they are C++ files. As a workaround, you can use an
lupdate_only{...} conditional statement so the lupdate tool sees the
.qml files but the C++ compiler ignores them.
If you specify your .qml files in the application like :
lupdate_only{
SOURCES = content/main.qml
}
When you run lupdate on the project .pro, the resulting .ts file will contain the QML translation context.
Note that you must stick to the brace style shown, using an alternate style such as e.g.
# DON'T USE, FAILS!
lupdate_only
{
SOURCES = content/main.qml
}
fails (at least on OS X 10.12 / Qt 5.7) with large amounts of compiler warnings and errors that are far from giving any hint at the actual problem, e.g.
clang: warning: <qml source file>: 'linker' input unused
clang: warning: argument unused during compilation: '-g'
clang: warning: argument unused during compilation: '-isysroot /Applications/Xcode_7.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk'
...
clang: error: no such file or directory: 'Page1.o'
clang: error: no such file or directory: 'Page1Form.ui.o'
Alternately, you can use a continuation character:
lupdate_only \
{
SOURCES = content/main.qml
}
As of Qt 5.8.0 no tricks are required in the .pro file anymore.
QML files can be listed once inside a .qrc Resource Container, and they will be picked up correctly by:
compiler
application at run-time
lupdate for translation
.pro file:
RESOURCES += application.qrc
.qrc is an XML file, usually managed via qtcreator without looking at its contents. More info about qrc files can be found here:
http://doc.qt.io/qt-5/qtquick-deployment.html#managing-resource-files-with-the-qt-resource-system
.qrc support was added to lupdate on 2016-10-25:
http://code.qt.io/cgit/qt/qttools.git/commit/?id=f2ebd51d96ad49eb826a4e37e67d506fffcbd40c
It didn't make it into Qt 5.7.1 release, but it will be available in 5.7.2 (if there ever is one).
Using lupdate_only seems like a viable solution.
However note that QtCreator will also pickup the qml files as source files, so now all qml files are listed duplicate when you navigate the project.
To avoid this I used a different approach where I update the translations through a shell script:
#!/bin/bash
../../5.5/gcc_64/bin/lupdate *.pro
for tr in *.ts
do
../../5.5/gvv_64/bin/lupdate *.qml -ts $ts
done

Empty translation files using QT internationalisation

I am using QT and trying to generate .ts translation files using the pylupdate4 command.
I marked the strings I needed to translate with
self.tr('example string')
Unfortuanetly, the generated .ts files are empty.
I am in the src folder of the project and generate my own .pro file, which is also in the src folder. It looks like this:
SOURCE = rob_gui.py
TRANSLATIONS = en.ts \
germ.ts
rob_gui.py is also in the src folder.
Why are the .ts files empty?

Resources