Qt Creator custom module naming issues with drag and drop
-
Using Qt 5.10.0, QtCreator 4.5.0, Qt5.10.0 MSVC2015 32bit compiler on Windows7 64bit
The Problem
After creating a custom module (all files autogenerated from File->New File or Project...->Qt->QtQuick UI File) and attempting to drag and drop associated qml files from outside the module (into some MainForm.ui.qml in another directory) the name of the object being placed in the MainForm is incorrect and said object cant be instantiated in the MainForm. This all worked fine when there was no module and all the main and object qml/ui.qml files were collocated.
Recreating the issue
Making the project - As far as the structure of the whole project this will take some time but all the qml files can more or less be whatever was autogenerated and the problem persists. I'm writing this in a way anyone can recreate it easily just in case.
In the QtCreator click File->New File or Project...->Application->Qt Quick Application. I named it MyApp, made with qmake, min version Qt 5.9, compiler Qt5.10.0 MSCV2015 32bit
From now on when I say add a new QtQuickUI file I mean File->New File or Project...->Qt->QtQuick UI File
Copy the contents of main.qml. Using the QtCreator Projects pane add a new QtQuickUI file to the folder where main.qml is located (under the resources folder for the project) named Main. It will tell you main.qml already exists, just override it. This will generate a Main.qml and Main.ui.qml for designer use. You'll have to delete the old main.qml from the qml.qrc file as well most likely. Paste the contents of main.qml from earlier into Main.qml.
Now in the same directory create a new QtQuickUI file named MyObject the same way. If you then open the MainForm.ui.qml in the Designer tab, and go to form editor you can drag and drop MyObject onto the MainForm from the designer library. Then switching to the text editor you can see MainForm.ui.qml contains a MyObject {} with various properties. Note that currently what is contained in MyObject.qml is actually "MyObjectForm{}". This is where the issue will arise when converting to a module.
In the MyObjectForm.ui.qml file I also threw down a text box just for testing purposes.
In main.cpp change the main.qml path the engine looks for to "qrc:/Main.qml" instead of with a lowercase main. Then in Main.qml add MainForm{} into Window{}, Window{andEverythingInIt} being what was copied from the old main.qml along with the imports required for it. If you run qmake, build and hit play you should see just a blank window with "Text" at some spot.
Making the module
Now, outside the creator, in the MyApp directory add a folder named Modules and in that a folder named Objects. Then in the Creator, right click on the qml.qrc file, add existing directory, and add the Modules folder. Then, outside the creator, move MyObject.qml and MyObjectForm.ui.qml to the Objects folder. Right click qml.qrc in the creator, Open in Editor, and rename the two files you just moved, appending Modules/Objects/ to the front. Then in the MyApp.pro file add "Modules" with the quotes to the QML_IMPORT_PATH variable. Also in main.cpp, before loading the Main.qml file add engine.addImportPath("../MyApp/Modules");. I had to hardcode the path because I haven't gotten anything else to work yet. I was hoping "qrc:/Modules" would work but it didn't. If you autogenerated the project with the designer the build folder/working directory will be in the same directory as MyApp by default so this path should work.Now from outside the creator go into the Modules/Objects folder and add a new file(with no extension) called qmldir. Open it in notepad or something and add the following:
module Modules.Objects MyObject 1.0 MyObject.qml
Rerun qmake and you should be able to type "import Objects 1.0" from in the MainForm.ui.qml, without the quotes. Now if you build and run it should all work as before.
Finally go into the Objects folder and add a folder named designer. In the designer folder add a new file named myobject.metainfo. I don't think the name matters, just the .metainfo part. In it place the following:
MetaInfo { Type { name: "Objects.MyObject" icon: "" ItemLibraryEntry { name: "MyObject" category: "Objects" libraryIcon: "" version: "1.0" requiredImport: "Objects" QmlSource { source: "../MyObject.qml" } } } }
Now if you open the MainForm.ui.qml in the designer you can drag and drop MyObject from the library pane! If you do that and look in MainForm.ui.qml using the text editor, what you will actually see created was MyObjectForm{} and until you manually rename that to remove "Form" off the name the code won't build and run successfully; even though the earlier collocated drag and drop managed to determine that the object should be named after MyObject.qml (MyObject{}) not what was within MyObject.qml(MyObjectForm{}).
So
Why is making a module using QtQuickUI files screwing up the naming scheme? Any ideas? Maybe Im using QtQuick incorrectly, but this all worked when the files were collocated so I'm going to say I believe this should all be possible. -
I fixed the issue by dropping the source string from the .metainfo files.
For anyone that cares I was following these instructions: http://doc.qt.io/qtcreator/creator-qml-modules-with-plugins.html and on step 5 I picked a random metainfo file when I searched the Qt folder for .metainfo, not the one they specifically chose (qtcharts.metainfo vs qtquickcontrols2.metainfo)
The qtcharts one was probably for some other type of module use where specifying the source does something I don't need, the qtquickcontrols2 ended up having the syntax I really wanted in the end. Eventually I found this example and found out dropping the source worked: https://forum.qt.io/topic/56207/how-to-load-custom-qml-controls-into-the-qml-designer