How can I organize QML files into nested folders? - qt

I have a sample project at https://github.com/jh3010-qt-questions/qml_location
If my hierarchy looks like:
$ tree qml_location/
qml_location/
├── MyDeepComponent.qml
├── MyDeepComponentForm.ui.qml
├── main.cpp
├── main.qml
├── qml.qrc
└── qml_location.pro
Then I can write main.qml like:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
MyDeepComponent {}
}
and it will work.
However, I would like to organize some QML files into a folder hierarchy and not have them all at the same level.
For example, if I move to:
$ tree qml_location/
qml_location/
├── main.cpp
├── main.qml
├── qml
│   ├── MyDeepComponent.qml
│   ├── MyDeepComponentForm.ui.qml
│   └── more
│   ├── MyDeeperComponent.qml
│   └── MyDeeperComponentForm.ui.qml
├── qml.qrc
└── qml_location.pro
and have a main.qml that looks like:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window
{
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
MyDeepComponent {}
MyDeeperComponent {}
}
}
Qt Creator tells me that MyDeepComponent and MyDeeperComponent are Unknown.
When I try to run, I get the error: MyDeepComponent is not a type
What can I do so this will work?
One caveat, I do not want to place a special or additional import at the top of main.qml. Is this still possible?
qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>qml/MyDeepComponent.qml</file>
<file>qml/MyDeepComponentForm.ui.qml</file>
<file>qml/more/MyDeeperComponent.qml</file>
<file>qml/more/MyDeeperComponentForm.ui.qml</file>
</qresource>
</RCC>
qml_location.pro
QT += quick
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

This answer doesn't meet the requirement of no imports, but it is worth mentioning anyway that it can be solved with a couple of imports at the top of main.qml.
https://github.com/jh3010-qt-questions/qml_location/tree/import_solution
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import "qml"
import "qml/more"
Window
{
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
MyDeepComponent
{
}
MyDeeperComponent
{
}
}
}

You can do something like this:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window
{
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
Loader {
source: "qrc:/qml/MyDeepComponent.qml"
}
Loader {
source: "qrc:/qml/more/MyDeeperComponent.qml"
}
}
}
Though I'm not quite sure why you would want to. Might help to describe the problem you are trying to solve?

https://github.com/jh3010-qt-questions/qml_location/tree/create_object_solution
createObject can be used to load the component directly into the Column.
main.qml looks like:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window
{
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property var componentNames: [ "qml/more/MyDeeperComponent.qml", "qml/MyDeepComponent.qml" ]
function generateObjects()
{
function generateOneObject( name )
{
var component
var componentObject
function finishCreation()
{
componentObject = component.createObject( contentColumn );
}
component = Qt.createComponent( `qrc:/${name}` )
if ( component.status === Component.Ready )
{
finishCreation()
}
else
{
component.statusChanged.connect( finishCreation );
}
}
for ( var index in componentNames )
{
generateOneObject( componentNames[ index ] )
}
}
Component.onCompleted: {
generateObjects()
}
Column
{
id: contentColumn
}
}

Another solution is to move main.qml into the qml folder. This allows main.qml to find MyDeepComponent because they are siblings. To find MyDeeperComponent, main.qml can import the "more" directory.
This solution in represented in the all_in_one_solution branch.
directory structure
$ tree qml_location/
qml_location/
├── main.cpp
├── qml
│   ├── MyDeepComponent.qml
│   ├── MyDeepComponentForm.ui.qml
│   ├── main.qml
│   └── more
│   ├── MyDeeperComponent.qml
│   └── MyDeeperComponentForm.ui.qml
├── qml.qrc
├── qml_location.pro
└── qml_location.pro.user
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
qml.qrc
<RCC>
<qresource prefix="/">
<file>qml/main.qml</file>
<file>qml/MyDeepComponent.qml</file>
<file>qml/MyDeepComponentForm.ui.qml</file>
<file>qml/more/MyDeeperComponent.qml</file>
<file>qml/more/MyDeeperComponentForm.ui.qml</file>
</qresource>
</RCC>
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import "more"
Window
{
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
MyDeepComponent
{
}
MyDeeperComponent
{
}
}
}

EDIT: I'm reading your part of the question where you state that you don't want an import at the top. I don't think this is possible, without throwing a bunch of addImportPath in your main (for each folder that you are to create) or heavy fiddling with qrc-aliases. Leaving the rest of the answer for a future visitor or for if you change your mind ;-)
You can use a qmldir file to make them available in a namespace of choice. But there is a bit of a learning curve. The qmldir file has to be situated in folder which resembles the namespace.
For example if you want to use MyApplication as namespace, you have to put the qmldir file in a folder "MyApplication" (within the qml import path). If you want MyOrg.application1 as namespace, you have to put qmldir in "MyOrg/application1".
For your situation, I choose the first option. I would make a separate qrc file for the importable qml files, which is also needed if you want to easily put all qml files in a "qml" folder:
qml/qml.qrc:
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/qml/MyApplication">
<file>MyDeepComponent.qml</file>
<file>MyDeepComponentForm.ui.qml</file>
<file>more/MyDeeperComponent.qml</file>
<file>more/MyDeeperComponentForm.ui.qml</file>
<file>qmldir</file>
</qresource>
</RCC>
A simple qmldir would look something like this:
module MyApplication
MyDeepComponent 1.0 MyDeepComponent.qml
MyDeeperComponent 1.0 more/MyDeeperComponent.qml
You can see that I used a prefix, such that the files don't have to move. If you are to go to great heights with the app and want a MyApplication 2.0 namespace, you can use the prefix /qml/MyApplication.2

Related

Import QML Components from Custom QML Library

I have created a library to store custom QML components that I am making for an application. I am using Pyside6 with python. This is what the basic directory looks like:
library
| |__CustomComponents
| |__Components1
| |__CustomComponent1.qml
|
|__test
|__MainComponent
|__main.py
|__Main.qml
library and test are on the same level. I want to be able to access the CustomComponent1.qml file for use in the Main.qml, but how would I go about writing an import statement for that in Python? Also, to be able to import Components1 as a module, is the qmldir file all I need to have there? It would be neat if there is a command I can use to generate the files I need to make a module.
Edit: Possible to use QQuickView and QQmlApplicationEngine together?
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView);
newWidget = newWidget()
view.rootContext().setContextProperty("headerWidget", headerWidget)
qml_file = os.fspath(Path(__file__).resolve().parent / 'Main.qml')
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Error:
sys.exit(-1)
view.show()
You have to use qmldir to indicate that there is a module in that folder and for it to be used it must be in the list of imports of the engine and for this you must use the addImportPath method.
├── library
│   └── CustomComponents
│   └── Components1
│   ├── CustomComponent1.qml
│   └── qmldir
└── test
└── MainComponent
├── main.py
└── main.qml
CustomComponent1.qml
import QtQuick
Rectangle{
id: root
width: 100
height: 100
color: "salmon"
}
qmldir
module Components1
CustomComponent1 CustomComponent1.qml
main.py
import os
from pathlib import Path
import sys
from PySide6.QtCore import QCoreApplication, Qt, QUrl
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
CURRENT_DIRECTORY = Path(__file__).resolve().parent
LIBRARY_DIR = CURRENT_DIRECTORY.parents[1] / "library" / "CustomComponents"
def main():
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.addImportPath(os.fspath(LIBRARY_DIR))
url = QUrl.fromLocalFile(os.fspath(CURRENT_DIRECTORY / "main.qml"))
def handle_object_created(obj, obj_url):
if obj is None and url == obj_url:
QCoreApplication.exit(-1)
engine.objectCreated.connect(
handle_object_created, Qt.ConnectionType.QueuedConnection
)
engine.load(url)
sys.exit(app.exec())
if __name__ == "__main__":
main()
main.qml
import QtQuick
import QtQuick.Window
import Components1
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
CustomComponent1{
}
}
QQuickView
In the case of QQuickView, it has an engine so you must use that one, so the changes are:
main.py
import os
from pathlib import Path
import sys
from PySide6.QtCore import QCoreApplication, Qt, QUrl
from PySide6.QtGui import QGuiApplication
from PySide6.QtQuick import QQuickView
CURRENT_DIRECTORY = Path(__file__).resolve().parent
LIBRARY_DIR = CURRENT_DIRECTORY.parents[1] / "library" / "CustomComponents"
def main():
app = QGuiApplication(sys.argv)
view = QQuickView()
view.engine().addImportPath(os.fspath(LIBRARY_DIR))
url = QUrl.fromLocalFile(os.fspath(CURRENT_DIRECTORY / "main.qml"))
def handle_status_changed(status):
if status == QQuickView.Error:
QCoreApplication.exit(-1)
view.statusChanged.connect(
handle_status_changed, Qt.ConnectionType.QueuedConnection
)
view.setSource(url)
view.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
main.qml
import QtQuick
import Components1
Rectangle {
width: 640
height: 480
CustomComponent1{
}
}

How to use QML Loader when the loaded component references another internal component

I have a repo at https://github.com/jh3010-qt-questions/qml_location/tree/loader_with_another_component
I am using Loader to load the MyDeeperComponent into main.qml's Column. However, MyDeeperComponent references another internal component called MySquare. When it loads, I get the error MySquare is not a type and the program quits. Of course, if I comment out MySquare from MyDeeperComponentForm.ui.qml, everything works and MyDeeperComponent loads successfully.
What needs to be changed so MyDeeperComponent can use MySquare and be dynamically loaded?
The directory structure is:
$ tree qml_location/
qml_location/
├── MySquare.qml
├── MySquareForm.ui.qml
├── main.cpp
├── main.qml
├── qml
│   └── more
│   ├── MyDeeperComponent.qml
│   └── MyDeeperComponentForm.ui.qml
├── qml.qrc
├── qml_location.pro
└── qml_location.pro.user
qml_location.pro
QT += quick
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = $$PWD/qml
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH = $$PWD/qml
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>qml/more/MyDeeperComponent.qml</file>
<file>qml/more/MyDeeperComponentForm.ui.qml</file>
<file>MySquare.qml</file>
<file>MySquareForm.ui.qml</file>
</qresource>
</RCC>
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window
{
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
MySquare {}
Loader {
source: "qrc:/qml/more/MyDeeperComponent.qml"
}
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath( "qrc:/qml" );
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
MySquare.qml
import QtQuick 2.4
MySquareForm {
}
MySquareForm.ui.qml
import QtQuick 2.4
Rectangle {
width: 40
height: 40
color: "blue"
}
Alternatively edit MyDeeperComponentForm.ui.qml by changing
MySquare {}
to
Loader {
source: "../../MySquare.qml"
}
or by adding (as already mentioned in the comments)
import "../.."
Note however, that your use case looks pretty weird from the dependency point of view... I suppose you are already familiar with different import mechanisms in QML but adding the link anyway for reference.

How to initialize a QML singleton?

I have a simple test project at https://github.com/jh3010-qt-questions/font_test which demonstrates the problem.
I have a label defined as:
Label // #1
{
text: "Pack my box with five dozen liquor jugs -- DEFAULT"
}
which should display with the default font (Art Brewery) defined in qtquickcontrols2.conf, but it is not.
However, if I add the Label:
Label // #2
{
font.family: Fonts.robotoBold.name
text: "Pack my box with five dozen liquor jugs -- Roboto Bold"
}
then, Label #1 will be drawn with the Art Brewery font.
What is happening is that the Fonts singleton is not being initialized unless there is at least one reference to it.
My question is: How can I initialize the singleton?
I have tried things like:
qmlRegisterSingletonType( QUrl( "file:///Users/jamesh/depot_qt/questions/font_test/assets/Fonts/Fonts.qml"), "Font", 1, 0, "Font" );
in my main.cpp, but it did not work.
My directory structure looks like:
$ tree font_test
font_test
├── README.md
├── assets
│   └── Fonts
│   ├── Art\ Brewery.ttf
│   ├── Fonts.qml
│   ├── Roboto-Bold.ttf
│   ├── Roboto-BoldItalic.ttf
│   ├── Roboto-Light.ttf
│   ├── Roboto-LightItalic.ttf
│   ├── Roboto-Medium.ttf
│   ├── Roboto-MediumItalic.ttf
│   ├── Roboto-Regular.ttf
│   ├── Roboto-RegularItalic.ttf
│   ├── RobotoMono-Bold.ttf
│   ├── RobotoMono-BoldItalic.ttf
│   ├── RobotoMono-Light.ttf
│   ├── RobotoMono-LightItalic.ttf
│   ├── RobotoMono-Medium.ttf
│   ├── RobotoMono-MediumItalic.ttf
│   ├── RobotoMono-Regular.ttf
│   ├── RobotoMono-RegularItalic.ttf
│   └── qmldir
├── font_test.pro
├── font_test.pro.user
├── main.cpp
├── main.qml
├── qml.qrc
└── qtquickcontrols2.conf
my qtquickcontrols2.conf is
[Controls]
Style=Material
[Material]
Primary=White
Foreground=#444444
Accent=Blue
Theme=Light
Font\Family=Art Brewery
[Universal]
Theme=System
my main.cpp is:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath( ":/" );
// qmlRegisterSingletonType( QUrl( "file:///Users/jamesh/depot_qt/questions/font_test/assets/Fonts/Fonts.qml"), "Font", 1, 0, "Font" );
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect( &engine,
&QQmlApplicationEngine::objectCreated,
&app,
[url](QObject *obj, const QUrl &objUrl )
{
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
my qml.qrc file is:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>qtquickcontrols2.conf</file>
</qresource>
<qresource prefix="/Fonts">
<file alias="qmldir">assets/Fonts/qmldir</file>
<file alias="Fonts.qml">assets/Fonts/Fonts.qml</file>
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Bold.ttf">assets/Fonts/Roboto-Bold.ttf</file>
<file alias="Roboto-BoldItalic.ttf">assets/Fonts/Roboto-BoldItalic.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-LightItalic.ttf">assets/Fonts/Roboto-LightItalic.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
<file alias="Roboto-MediumItalic.ttf">assets/Fonts/Roboto-MediumItalic.ttf</file>
<file alias="Roboto-Regular.ttf">assets/Fonts/Roboto-Regular.ttf</file>
<file alias="Roboto-RegularItalic.ttf">assets/Fonts/Roboto-RegularItalic.ttf</file>
<file alias="RobotoMono-Bold.ttf">assets/Fonts/RobotoMono-Bold.ttf</file>
<file alias="RobotoMono-BoldItalic.ttf">assets/Fonts/RobotoMono-BoldItalic.ttf</file>
<file alias="RobotoMono-Light.ttf">assets/Fonts/RobotoMono-Light.ttf</file>
<file alias="RobotoMono-LightItalic.ttf">assets/Fonts/RobotoMono-LightItalic.ttf</file>
<file alias="RobotoMono-Medium.ttf">assets/Fonts/RobotoMono-Medium.ttf</file>
<file alias="RobotoMono-MediumItalic.ttf">assets/Fonts/RobotoMono-MediumItalic.ttf</file>
<file alias="RobotoMono-Regular.ttf">assets/Fonts/RobotoMono-Regular.ttf</file>
<file alias="RobotoMono-RegularItalic.ttf">assets/Fonts/RobotoMono-RegularItalic.ttf</file>
</qresource>
</RCC>
my project file is:
QT += quick
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = $$PWD/assets
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES +=
My Fonts.qml file is:
pragma Singleton
import QtQuick 2.12
Item
{
readonly property FontLoader robotoBold: FontLoader { source: "qrc:/Fonts/Roboto-Bold.ttf" }
readonly property FontLoader robotoBoldItalic: FontLoader { source: "qrc:/Fonts/Roboto-BoldItalic.ttf" }
readonly property FontLoader robotoLight: FontLoader { source: "qrc:/Fonts/Roboto-Light.ttf" }
readonly property FontLoader robotoLightItalic: FontLoader { source: "qrc:/Fonts/Roboto-LightItalic.ttf" }
readonly property FontLoader robotoMedium: FontLoader { source: "qrc:/Fonts/Roboto-Medium.ttf" }
readonly property FontLoader robotoMediumItalic: FontLoader { source: "qrc:/Fonts/Roboto-MediumItalic.ttf" }
readonly property FontLoader robotoRegular: FontLoader { source: "qrc:/Fonts/Roboto-Regular.ttf" }
readonly property FontLoader robotoRegularItalic: FontLoader { source: "qrc:/Fonts/Roboto-RegularItalic.ttf" }
readonly property FontLoader robotoMonoBold: FontLoader { source: "qrc:/Fonts/RobotoMono-Bold.ttf" }
readonly property FontLoader robotoMonoBoldItalic: FontLoader { source: "qrc:/Fonts/RobotoMono-BoldItalic.ttf" }
readonly property FontLoader robotoMonoLight: FontLoader { source: "qrc:/Fonts/RobotoMono-Light.ttf" }
readonly property FontLoader robotoMonoLightItalic: FontLoader { source: "qrc:/Fonts/RobotoMono-LightItalic.ttf" }
readonly property FontLoader robotoMonoMedium: FontLoader { source: "qrc:/Fonts/RobotoMono-Medium.ttf" }
readonly property FontLoader robotoMonoMediumItalic: FontLoader { source: "qrc:/Fonts/RobotoMono-MediumItalic.ttf" }
readonly property FontLoader robotoMonoRegular: FontLoader { source: "qrc:/Fonts/RobotoMono-Regular.ttf" }
readonly property FontLoader robotoMonoRegularItalic: FontLoader { source: "qrc:/Fonts/RobotoMono-RegularItalic.ttf" }
readonly property FontLoader artBrewery: FontLoader { source: "qrc:/Fonts/Art Brewery.ttf" }
}
My qmldir inside of the assets/fonts folder is:
singleton Fonts 1.0 Fonts.qml
My main.qml is
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import Fonts 1.0
//import "qrc:/Fonts/"
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
spacing: 8
anchors.fill: parent
anchors.margins: 20
Label // #1
{
text: "Pack my box with five dozen liquor jugs -- DEFAULT"
}
// Label // #2
// {
// font.family: Fonts.robotoBold.name
// text: "Pack my box with five dozen liquor jugs -- Roboto Bold"
// }
// Label // #3
// {
// font.family: Fonts.robotoMonoRegular.name // Fonts.robotoRegular.name
// text: "Pack my box with five dozen liquor jugs -- Roboto Mono"
// }
// Label // #4
// {
// text: "Pack my box with five dozen liquor jugs -- Art Brewery"
// font.family: Fonts.artBrewery.name
// font.pixelSize: 36
// }
}
}
I am certain there is a better solution, but one thing that works is to find a way to reference the singleton once so everything is loaded.
I modified main.qml to:
...
...
...
title: qsTr("Hello World")
property var fontReference: Fonts.objectName
Column
...
...
...
I don't care about the fontReference property. I only need some way to get Fonts initialized. I am assuming there is C++ method I can call after the engine instance is created in main.cpp which will accomplish the same thing and may be considered the best practice in this situation.

How to import Qml plugins lib into another project?

I have a 2 qml files in a lib and I want to export those to another project and was unable to import in my QuickQmlTest project. I want to use those qml files from QmlPlugin lib in QuickQmlTest project. Is there any additional step I need to do ? I have a folder structure
QMLProject
|-- QmlPlugin -(it is lib)
|--QML
|--CustomButton.qml
|-- CustomPolygon.qml
|-- QuickQmlTest - (app)
My QmPlugins.pro looks like this
TEMPLATE = lib
TARGET = QmlPlugin
QT += qml quick
CONFIG += plugin c++11
TARGET = $$qtLibraryTarget($$TARGET)
HEADERS += \
MyPlugin.h
DISTFILES = qmldir \
CustomButton.qml \
CustomPolygon.qml
DESTDIR = $$PWD/lib
And I linked the generated dlls into to the QuickQmlTest.pro using
LIBS += -L$$PWD/../QmlPlugin/lib -lQmlPlugin
INCLUDEPATH += $$PWD/../QmlPlugin
MyPlugin.h
#include <QQmlExtensionPlugin>
#include <QtQml/qqml.h>
class MyItemModel: public QObject
{
Q_OBJECT
Q_PROPERTY(qreal roundingRadius READ roundingRadius WRITE setRoundingRadius)
public:
void setRoundingRadius(const qreal rounding)
{
roundingRadius_ = rounding;
}
qreal roundingRadius() const
{
return roundingRadius_;
}
private:
qreal roundingRadius_{8.0};
};
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char* uri)override
{
Q_ASSERT(uri == QLatin1String("Components"));
qmlRegisterType<MyItemModel>(uri, 1, 0, "MyItemModel");
}
};
in qmldir I have
module Components
Components 1.0 CustomButton.qml CustomPolygon.qml
plugin QmlPlugin
In the QuickQmlTest (app)
I want to use CustomButton.qml and CustomPolygon.qml in my main.qml
So my main.qml in QuickQmlTest app
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import Components 1.0 //To import the dll from lib
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
CustomPolygon
{
width:60
height:30
}
CustomButton
{
width:60
height:30
}
}
And also I want to see my Custom qml types(CustomButton and CustomPolygon) in Quick Design mode which I am unable to achieve.

QML import item from sibling folder

Suppose I have the following structure in my qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>Style.qml</file>
</qresource>
<qresource prefix="/components">
<file>Test.qml</file>
</qresource>
main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.0
import "components"
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Test {
color: "red"
}
}
Test.qml
import QtQuick 2.0
import ".."
Rectangle {
width: Style.test * 200
height: 200
}
Style.qml
import QtQuick 2.0
pragma Singleton
QtObject {
property real test: 1.0
}
I have for some time tried to import Style.qml from Test.qml with import "../" but I keep getting ReferenceError: Style is not defined
I know the import statement is the cause for this and I have tried a few different variants of what "might" work but the docs are lacking on this and I am stuck. Help appreciated.
With the following code, I have no errors, and see the expected visual result. I'd suggest including a more complete example, if you can't spot your problem from this working sample. Note that all paths I give here are relative from the "root" project directory (so e.g. main.cpp is a file in the "root", components/Test.qml is located in a "components" subdirectory):
main.cpp:
#include <QQmlApplicationEngine>
#include <QGuiApplication>
int main(int argc, char **argv) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine qAppEngine(QUrl("qrc:/main.qml"));
return app.exec();
}
main.qml
import "components"
Test {
}
components/Test.qml:
import ".."
Style {
}
Style.qml:
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 500
height: 500
color: "red"
}
Built with the following:
test.pro:
QT += quick qml
RESOURCES += test.qrc
SOURCES += main.cpp
test.qrc:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>main.qml</file>
<file>Style.qml</file>
<file>components/Test.qml</file>
</qresource>
</RCC>

Resources