How do I make my own directory in QT QML? - qt

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();
}

Related

Qt5 QML module is not installed

I'm confused about modules in Qt QML. I've read all the docs, but it doesn't make clear some basic ideas.
I understand that i can put a bunch of QML files into a directory and add a qmldir file to describe an identified module. When i do this and adjust the QML_IMPORT_PATH, QtCreator is happy and stops underlining the import ModuleName 1.0 line.
So creator is happy, but it does not work. I get module is not installed.
my questions are:
what does it mean by "installed". I have directory of files, but i haven't "installed" them anywhere.
should i be building/compiling the module to make a DLL/.so ?
does the module QML files go into the resources of the main app, otherwise where are they to be found?
my main.qml file is part of the app resources, how does the app locate the resources of the module at runtime.
Sorry, for all these questions, but the basics of these modules is just not clear. I don't understand if a "module" is just the sharing of files or is it a compiled unit.
thanks for any help.
I'll try to answer your questions:
I think installed means they are located in the proper paths, so
that they can be found at runtime
You should not necessarily create/build a QmlExtensionPlugin for that purpose. You can also use as a module plain QML files in one
directory with a qmldir describing this module. It is a matter of
distributing your code. With QmlExtensionPlugin you provide the
module compiled, if you want to hide the code.
The modules can be in resources system or as files on disk, it is up to you.
The app looks for modules in predefined paths - in your app's directory, in Qt plugins path, in QML2_IMPORT_PATH, in directories that you added using engine->addImportPath()
There are a bunch of things that can lead to a module not being loaded. You can check the following:
Module identifier in qmldir should be the same as the directory
name, where the module actually resides. For example if your module
has module identifier module Test.Module in qmldir, your module's
relative path must be Test/Module.
If it is a QML extension
plugin (shared library), make sure that plugin's directory name is
the same as plugin's name.
export QML2_IMPORT_PATH (make sure there is 2 in the name) env variable to point to directory containing your module. There is also a QQmlEngine::addImportPath method, which adds the directory to the list to lookup for plugins.
If it is a qml extension plugin (shared library), then there might be missing dependencies for it. You can check it by Dependency Walker on Windows or ldd command on Linux.
Setting QT_PLUGIN_PATH runtime variable may help to load plugins. It should point to a directory containing you plugin's directory, not the plugin's directory itself.
You can also enable traces to see what's going on while plugins are loaded for better understanding of the problem - export QT_DEBUG_PLUGINS=1 and QML_IMPORT_TRACE=1 environment variables
You can also read this link:
https://doc.qt.io/qt-5/qtqml-modules-identifiedmodules.html
In my case (I have all QML files in qrc resources) worked to add qmldir to resources also and call method addImportPath("qrc:/") of QQmlApplicationEngine.
My main.cpp looks like:
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Important parts of my .pro file looks like:
RESOURCES += qml.qrc \
MyModule/mymodule.qrc
QML_IMPORT_PATH += $$PWD
My qmldir:
module MyModule
MyItem 2.0 MyItem20.qml
MyItem 2.1 MyItem21.qml
My qrc:
<RCC>
<qresource prefix="/MyModule">
<file>MyItem20.qml</file>
<file>MyItem21.qml</file>
<file>qmldir</file>
</qresource>
</RCC>
And finally my main.qml:
import QtQuick 2.5
import QtQuick.Window 2.2
import MyModule 2.0
Window {
visible: true
width: 640
height: 480
MyItem {
anchors.fill: parent
}
}
QtCreator is happy (not underlining components and imports) and module is loaded.
Hope this helps.
I want to expand on arxarian's answer - which I think is the best technique for integrating modules - but couldn't fit those thoughts in a comment, so here's a new answer.
It's important to first understand that qml modules and their associated resources are runtime entities and are assumed to separately exist at some location relative to the executable unless they're included in the application resources. By including them in the resources, they are still runtime entities, but they exist under the qrc:/ root path within the application binary. This hiding of the modules is the primary reason why I think this is the best technique, unless you want your modules to be open to revision after deployment, or to be independently deployable as precompiled plugins (i.e., in the resource storage of a dynamically linked library).
So here's my explanation of the important elements of arxarian's answer:
engine.addImportPath("qrc:/"); is needed in the C++ code prior to loading the qml to instruct the engine to look for qml modules in the application resource storage.
RESOURCES += MyModule/mymodule.qrc is needed in the project (.pro) file to add the module's files to the application resource storage.
QML_IMPORT_PATH += $$PWD in the project file tells Qt Creator to look for the module starting from the root of the project source tree. In my case I had to set this to a subdirectory (e.g., "ui/modules") because my module directories started there. The import path should include the root(s) beneath all module directories. As far as I can tell, this instruction is only for the Qt Creator IDE and does not impact the build - that's why #1 is needed.
The contents of the qmldir file is as is standard for all qml modules, but it's inclusion in the module's .qrc resource file is not intuitive until you think about what's happening with runtime storage. It needs to be in the .qrc so that it is included in the application resource storage, so that the engine can find it at runtime to define the module. <qresource prefix="/MyModule"> in the module's .qrc file defines the module subdirectory relative to the qrc:/ root in the application resource storage.
The import MyModule <version> statement in qml is now setup for success. On startup the engine will have located the module in its directory under qrc:/, parsed the qmldir file there to define the module and established the name and version from those entries.
Hopefully this helps others understand what's going on, and please let me know if I've misunderstood anything.
A similar issue cost me a bit of time so I just post it here to perhaps save the next guy some effort.
My problem was that an invisible character had sneaked into the module name. Probably through copy and paste. Here my issue:
Example error output:
MyEngine failed to load component
qrc:/qml/main.qml:53 Type MyComponent unavailable
file:///Users/<pathToProject>/MyProject/qml/MyModule/MyComponent.qml:-1 No such file or directory
It all looks fine and the path displayed is indeed the correct one. So what is wrong?
Now, copy that path to a Terminal window:
file:///Users/<pathToProject>/MyProject/qml/MyModule/<feff>MyComponent.qml
There it is, the:
"<feff>"
Solved the issue by manually retyping the component name in the qmldir file, and thus effectively deleting the invisible character.
I had the same problem and have now fixed it. I found a QML plugin for iOS. There are several things that need to be taken care of:
1. The plugin pro file needs an addition:
uri = IosTestPulgin
# this for error:
# static plugin for module “QtQuick” with name “IosTestPulgin”
# has no metadata URI
QMAKE_MOC_OPTIONS += -Muri=$$uri
# thanks from:https://github.com/wang-bin/QtAV/issues/368
2. The QML plugin qmldir file needs an additional line like this:
classname IosqmlpluginPlugin
# for ERROR: Plugin iostestqmlplugin is missing a classname entry,
# please add one to the qmldir file.
# look for qt document http://doc.qt.io/qt-5.6/qtqml-modules-qmldir.html
3 The client project pro file needs an addition like this:
ios {
IOSTestPlugin_BUNDLE.files += $$files($$[QT_INSTALL_QML]/IosTestPulgin/qmldir)
IOSTestPlugin_BUNDLE.path = IosTestPulgin
QMAKE_BUNDLE_DATA += IOSTestPlugin_BUNDLE
}
# for ios error: module is not installed
# this means external qml static plugin must add the plugin dir by manual
# in the app root dir

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.

How can I organize files under the qml.qrc folder in Qt Creator?

If I have a bunch of resources (images, fonts, etc.) in different folders under my qml.qrc file, is there a way to organize this within Qt Creator?
For example, if I have the following in my qml.qrc file:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>pages/MainPage.qml</file>
<file>pages/NewContactPage.qml</file>
<file>images/plus.png</file>
<file>images/minus.png</file>
<file>images/exit.png</file>
</qresource>
</RCC>
It will show up as a long list in Qt Creator, like this:
Resources
qml.qrc
/
main.qml
pages/MainPage.qml
pages/NewContactPage.qml
images/plus.png
images/minus.png
images/exit.png
Since this list can get really long over the duration of the project, it would be nice if these were organized better and split into folders like they are in my directory. Any ideas?
Actually, I'd highly recommend that non .qml assets to be put in a different resource file altogether, because large files will gut application build times. What happens is even a tiny change to a qml source will result in recompilation of the entire resource file. If assets are in a different resource file they are not continuously recompiled.
This will also effectively achieve organization in addition to significantly improving build times.
I just discovered an awesome way to do it. What's weird is that nobody else suggested it, when it's so completely trivial. Perhaps it didn't work in old versions of Qt/Qt Creator but now it does.
Here it is:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>test/test.txt</file>
</qresource>
</RCC>
The test dir needs to exist and needs to contain test.txt.
No need for creating separate <qresource> tags with different prefixes. No need for alias attributes.
The files are cleanly organized in the filesystem and in the project explorer and you can access them from code with clean paths like :/test/test.txt.
(this screenshot is of a project that has some extra files as well - ignore those)
Bonus: You can rightclick on the "test" folder in the project explorer in Qt Creator and choose "Add new...", this does put the newly created file in the right place in the filesystem. Unfortunately it doesn't appear in the qrc subtree in the project explorer, only in a separate "Other files" subtree. You need to rightclick "qrc.qml" in the project explorer and choose "Add existing files" to make the file appear in the qrc subtree like it should. So it's a bit buggy/messy but when you learn how to use it, it's workable.
Bonus 2: You can import (add) an existing file/dir (which reside in any (sub-)sub-dir of the qrc file) and the right XML syntax will be generated, resulting in the right tree structure in the project explorer.
What I think doesn't work well:
Creating a file from Qt Creator from File -> New file or project (or Ctrl-N). This doesn't let you put the file in an arbitrary dir in the filesystem, only in the root project dir.
Files that you've put in subdirs aren't included in Qt Creator's project-wide search (Ctrl+Shift+F).
Edit: I just noticed the OP is doing exactly what I suggest. In that case, he probably is using an older Qt Creator version. Mine is 4.1.0.
If you want to use qrc files but don't like paths like "images/icons/images/icons/icon.png/" use alias as described here
<qresource prefix="/images">
<file alias="cut.png">images/cut.png</file>
</qresource>
With alias you can use your file by neatly writing /images/cut-img.png instead of /images/images/cut.png
From the Qt documentation: The Qt Resource System
By default, resources are accessible in the application under the same file name as they have in the source tree, with a :/ prefix, or by a URL with a qrc scheme.
It is also possible to specify a path prefix for all files in the .qrc file using the qresource tag's prefix attribute:
this example show how to do it:
<RCC>
<qresource prefix="/pages">
<file >pages/MainPage.qml</file>
</qresource>
<qresource prefix="/images">
<file >images/plus.png</file>
</qresource>
</RCC>
Another nice way to view your project files / folders as they appear on your File System is to do this:
Open your project
Click on the drop down menu which is above your project name, as demonstrated in the image below:
Done, now you can see your files and folders as they appear on your FS

How to replace qt.conf?

I'm working on an embedded system. The directory /root/txpa/images/current/application/bin contains the file qt.conf, the content of which looks like this:
[Paths]
Prefix=/qtdir
Libraries=/qtdir/lib
/qtdir/lib/fonts is about the only thing in the path, and it contains several fonts of kind Vera. These are the only fonts in the system, and the app itself doesn't use them directly. Qt does.
I've been asked to remove qt.conf from its current directory, but if I do the app doesn't start (I suppose Qt can't find any fonts). How would i do this? I've read about Qt resource system, but I'm not sure how to go about doing this.
These are the steps I had to follow in order to resolve this problem:
First, create a qt_conf.qrc file that looks like this:
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/qt/etc/">
<file>qt.conf</file>
</qresource>
</RCC>
QLibraryInfo will load qt.conf from :/qt/etc/qt.conf using the resource system. That should explain the above qt_conf.qrc.
Second, copy the qt.conf file to the same directory as the qt_conf.qrc file (this can be changed, of course).
And finally, update the *.pro files, if any, and rebuild. The original qt.conf file can be removed from the directory that it was in.

How to convert .ui(user interface) files into .exe file in QT

I am a fresher in qt,i don't have much knowledge on qt, but i created some of file in qt for my application (regaurding to GUI format).I was created some .ui files in qt,but i wanted these files into .exe format.I think u had unerstand my problem,so please help me
uic (sometimes installed as uic-4) takes the .ui files and generates a C++ header file that you can inherit from. There are a few different ways you can work with the .ui files. See the manual for more information. Feel free to come back with specific questions.
Hallo Ram,
I think you are asking about the inclusion of .ui files within your .exe file.
If I am not wrong, then you need to include you .ui file within your projects specific resource file. It will be usually named .qrc in Qt projects.
The contents of .qrc file will look something like this:
<RCC>
<qresource prefix="/ui">
<file>ui/command/spiwidget.ui</file>
<file>ui/command/SPIMicroCommandWidget.ui</file>
<file>ui/command/utility/externdatawidget.ui</file>
<file>ui/sequencerwidget.ui</file>
<file>ui/command/watchdogwidget.ui</file>
<file>ui/command/utility/repdatawidget.ui</file>
<file>ui/command/core.png</file>
<file>ui/command/LastOpenedFiles.ui</file>
</qresource>
</RCC>
In the code above, you can see the inclusions for .ui and .png(image file) too.
After including it in .qrc file, you can use this resource in your .cpp code as follows:
QFile file(":ui/ui/command/LastOpenedFiles.ui");
Where :ui/ui/command is the path of to the .ui file being used.
Hope this explanation is useful to you!
Try using QtCreator (official IDE for Qt development). One way to use your *.ui file would bet to:
create *.h and *.cpp files containing a class that will load your widget structure.
add your new files to qt project file - *.pro
If your haven't used Qt Creator yet, then I suggest try it.
Create new project (ctrl+n) - Qt C++ Project / Qt Gui Application
Add new form to your project (ctrl+n) - Qt / Qt Designer Form Class
Look at files that where created by IDE. There is *.h file, *.cpp file and *.ui file.
Look into *.pro file, there are 3 sections SOURCES, HEADERS, FORMS
Here are some learning materials:
http://qt.nokia.com/services-partners/qt-in-education/qt-in-education-course-material

Resources