aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Shalayel <sami.shalayel@qt.io>2025-02-18 16:34:19 +0100
committerSami Shalayel <sami.shalayel@qt.io>2025-03-07 14:24:58 +0000
commit3d18d15d382d1f020920236c9370789e6ccf1f39 (patch)
treefda2946c42c3876fc6c7ff81cb6c421a314bddb5
parent7b4837d3e34a206ccbd3b921e65f1401b09066ee (diff)
doc: document how to write modern QML Modules
Add two documents on how to write modern QML Modules, one for porting to qt_add_qml_module and one for modernizing QML Modules created with qt_add_qml_module. Fixes: QTBUG-133547 Change-Id: Ieb1f23d6600b17bfa8a949633e1e9192004804d0 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> (cherry picked from commit 45f024c54086eed57851725932168dc8cd7bd633) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 16296160b2663d2d167374ff219aa499272886b1) (cherry picked from commit 36375f88409bcf839efa6fdf66ee3f586342ad54) Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/doc/src/qt6-changes.qdoc2
-rw-r--r--src/qml/doc/src/qt6-modernize-qml-modules.qdoc95
-rw-r--r--src/qml/doc/src/qt6-port-to-qt-add-qml-module.qdoc188
3 files changed, 284 insertions, 1 deletions
diff --git a/src/qml/doc/src/qt6-changes.qdoc b/src/qml/doc/src/qt6-changes.qdoc
index 92f78c0e88..1deff94f59 100644
--- a/src/qml/doc/src/qt6-changes.qdoc
+++ b/src/qml/doc/src/qt6-changes.qdoc
@@ -257,5 +257,5 @@
\endlist
-
+ \sa {Modern QML modules}, {Port QML modules to CMake}
*/
diff --git a/src/qml/doc/src/qt6-modernize-qml-modules.qdoc b/src/qml/doc/src/qt6-modernize-qml-modules.qdoc
new file mode 100644
index 0000000000..cc21f2b9bc
--- /dev/null
+++ b/src/qml/doc/src/qt6-modernize-qml-modules.qdoc
@@ -0,0 +1,95 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt6-modernize-qml-modules.html
+\title Modern QML modules
+\brief Modernize your QML modules.
+
+QML modules have become more powerful and easier to use in Qt 6.
+The following sections describe how to modernize QML modules that already use \l qt_add_qml_module.
+
+See also \l{Port QML modules to CMake} on how to port a QML module to the
+\l qt_add_qml_module CMake API.
+
+\section1 Use qt_standard_project_setup
+\l qt_standard_project_setup sets up \l{Qt CMake policies} needed for modern QML modules, among
+other things. To modernize your QML module and follow best practices, call
+\l qt_standard_project_setup in the project's top-level \c CMakeLists.txt file before any
+\l qt_add_qml_module call:
+\badcode
+qt_standard_project_setup(REQUIRES 6.8)
+\endcode
+
+\section1 Use the new standard resource path prefix
+The standard resource path for QML modules moved from \c{:/} to \c{:/qt/qml} with \l{QTP0001}. Don't
+use custom resource prefixes nor extend import paths in the engine.
+Remove all \c RESOURCE_PREFIX arguments from all \l qt_add_qml_module calls, as well as all calls to
+\l{QQmlEngine::addImportPath} or similar.
+Change all qrc paths in your C++ and QML code to use the new resource path prefix:
+\badcode
+// C++ usages like:
+QUrl someUrl("qrc:/MyQmlModule/MyResource1.png");
+// need to be changed to
+QUrl someUrl("qrc:/qt/qml/MyQmlModule/MyResource1.png");
+
+// QML usages like:
+":/MyQmlModule/MyResource1.png"
+// need to be changed to
+":/qt/qml/MyQmlModule/MyResource1.png"
+\endcode
+
+See also \l{Using the Qt Resource System with QML}.
+
+\section1 Use loadFromModule to load your QML files
+
+With the default import path, you can use the \c loadFromModule methods, like \l
+QQmlApplicationEngine::loadFromModule, \l QQuickView::loadFromModule, or
+\l QQmlComponent::loadFromModule, for example.
+
+Use \c loadFromModule to load your QML file, for example:
+\badcode
+engine.load(QUrl(QStringLiteral("qrc:/MyQmlModule/Main.qml")));
+// becomes
+engine.loadFromModule("MyQmlModule", "Main");
+\endcode
+
+\section1 Replace OUTPUT_DIRECTORY and IMPORT_PATH with DEPENDENCIES TARGET
+Avoid setting an \c IMPORT_PATH in the \l qt_add_qml_module. Instead, use \c{DEPENDENCIES TARGET}
+to declare dependencies to other QML modules that can't be found in the current import path.
+
+Using \c{DEPENDENCIES TARGET} also eliminates the need for the \c QT_QML_OUTPUT_DIRECTORY CMake
+variable and the \c OUTPUT_DIRECTORY argument to \l qt_add_qml_module, so remove their
+definitions and usages.
+
+For example:
+\badcode
+### in the CMakeLists.txt file defining the dependent QML module:
+# don't set QT_QML_OUTPUT_DIRECTORY and remove lines like these:
+set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/qml)
+
+qt_add_qml_module(MyThirdPartyQmlLibraryDependency
+ URI MyThirdPartyQmlLibraryDependency
+ ....
+ # custom output paths are obsolete due to DEPENDENCIES TARGET below, so remove:
+ OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/qml
+}
+
+### in the CMakeLists.txt file defining the QML module that uses the dependency:
+qt_add_qml_module(MyQmlLibrary
+ URI MyQmlModule
+ ...
+ # replace import paths like these:
+ IMPORT_PATH ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/qml
+ # with:
+ DEPENDENCIES TARGET MyThirdPartyQmlLibraryDependency
+}
+\endcode
+
+\note You might need to call \c{add_subdirectory()} before calling \l qt_add_qml_module in your
+CMakeLists.txt for \c {DEPENDENCIES TARGET} to find the target.
+
+For more information on how to declare module dependencies, see \l{Declaring module dependencies}.
+
+\sa {Changes to Qt QML}, {Port QML modules to CMake}
+*/
diff --git a/src/qml/doc/src/qt6-port-to-qt-add-qml-module.qdoc b/src/qml/doc/src/qt6-port-to-qt-add-qml-module.qdoc
new file mode 100644
index 0000000000..97c1f0d916
--- /dev/null
+++ b/src/qml/doc/src/qt6-port-to-qt-add-qml-module.qdoc
@@ -0,0 +1,188 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt6-port-to-qt-add-qml-module.html
+\title Port QML modules to CMake
+\brief Port your QML modules to the qt_add_qml_module CMake API.
+
+QML modules have become more powerful and easier to use in Qt 6. The following sections describe
+how to port QML modules to the \l qt_add_qml_module CMake API.
+
+See also \l{Modern QML modules} on how to modernize a QML module that already uses \l
+qt_add_qml_module.
+
+\section1 Identify issues to fix
+
+Use \l qmllint to support you through the process.
+
+Each QML module defined with \l qt_add_qml_module has a \c{_qmllint} CMake target that you can
+use to identify potential issues or improvements. For a QML module called \c MyQmlLibrary use
+\c{MyQmlLibrary_qmllint}, for example. To run \l qmllint on all QML modules, use \c
+{all_qmllint}.
+
+The warning categories of \l qmllint that hint at QML module issues are:
+\list
+ \li \l{Warnings occurred while importing}{[import]}
+ \li \l{Unused imports}{[unused-imports]}
+ \li \l{Unresolved type}{[unresolved-type]}
+ \li \l{Unresolved Alias}{[unresolved-alias]}
+ \li \l{Missing enum entry}{[missing-enum-entry]}
+ \li \l{Missing property}{[missing-property]}
+ \li \l{Missing type}{[missing-type]}
+\endlist
+
+\section1 Prepare the project for qt_add_qml_module
+
+\section2 Make qt_add_qml_module available in CMake
+
+To make \l qt_add_qml_module available in CMake, add \c Core and \c Qml to your \c find_package
+call in the project's top-level \c CMakeLists.txt file:
+\badcode
+find_package(Qt6 REQUIRED COMPONENTS Core Qml)
+\endcode
+
+\section2 Use qt_standard_project_setup
+
+\l qt_standard_project_setup sets up \l{Qt CMake policies} needed for \l qt_add_qml_module, among
+other things.
+
+Call \l qt_standard_project_setup in the project's top-level \c CMakeLists.txt file
+before any \l qt_add_qml_module call:
+\badcode
+qt_standard_project_setup(REQUIRES 6.8)
+\endcode
+
+\section1 Use qt_add_qml_module
+
+\l qt_add_qml_module is the CMake function that takes care of generating QML modules. It
+automatically generates \c qmldir and \c qmltypes files, and sets up tooling like \l qmlcachegen
+or \l qmllint.
+
+QML modules can be added to both executable and library targets in CMake. QML modules attached
+to the executable target can't be used or linked by other executables, while QML modules attached
+to library targets can.
+
+\section2 Add a QML module to your executable target
+In this case, the source files of the QML module are treated as part of the executable itself,
+rather than being compiled into a separate library. This means neither a module nor plugin library
+for this module is created—--the module is fully integrated into the executable. As a result, the
+module is tied to that specific program and cannot be reused by other executables or libraries.
+
+To add a QML module to your executable, in your \c CMakeLists.txt:
+\badcode
+# pre-existing:
+qt_add_executable(MyApp main.cpp)
+
+# add this
+qt_add_qml_module(MyApp
+ URI MyAppModule
+ QML_FILES
+ Main.qml # and possibly more .qml files
+)
+\endcode
+
+The \c Main.qml should start with an upper case letter so that it can be instantiated by
+\c loadFromModule methods like \l{QQmlApplicationEngine::loadFromModule} or
+\l{QQmlComponent::loadFromModule}.
+Also, the QML module URI should be different from the target name to avoid name clashes
+in the build folder.
+
+\section2 Add a QML module to your library target
+To add a QML module to your library, in your \c CMakeLists.txt:
+\badcode
+qt_add_qml_module(MyQmlLibrary
+ URI MyQmlModule
+ QML_FILES MyQmlComponent1.qml MyQmlComponent2.qml...
+ SOURCES MyCppComponent1.h MyCppComponent1.cpp MyCppComponent2.h MyCppComponent2.cpp...
+ RESOURCES MyResource1.png MyResource2.png...
+)
+\endcode
+
+\l qt_add_qml_module creates a \c SHARED library via \l qt_add_library if the \c
+MyQmlLibrary target does not exist yet, like in this example.
+
+\note Your QML module URI should be different from the target name to avoid name clashes in the
+build folder.
+
+\section1 Use loadFromModule to load your QML files
+
+Use \c loadFromModule to load your QML file, for example:
+\badcode
+engine.load(QUrl(QStringLiteral("qrc:/MyQmlModule/Main.qml")));
+// becomes
+engine.loadFromModule("MyQmlModule", "Main");
+\endcode
+
+\section1 Remove handwritten qmldir files
+
+\l qt_add_qml_module automatically generates \c qmldir files. If you have singletons in
+your \c qmldir, declare them in your \c CMakeLists.txt before the \l qt_add_qml_module call with:
+\badcode
+set_source_files_properties(MySingleton.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
+\endcode
+
+Delete the handwritten \c qmldir after that.
+
+\section1 Remove qmltypes files generated by qmlplugindump
+
+\l qt_add_qml_module auto-generates \c qmltypes files when all your types are using
+\l{Registering C++ Types with the QML Type System}{declarative type registration}, which removes
+the need to generate \c qmltypes files by hand using tools like \c qmlplugindump.
+
+To achieve that, remove manual calls to \c qmlRegisterType and its variants. Then,
+\l{Registering C++ Types with the QML Type System}{register your types declaratively} by using
+\l QML_ELEMENT, for example:
+\badcode
+// add this header
+#include <QtQml/qqmlregistrations.h>
+
+class MyComponent: public QObject {
+ Q_OBJECT
+
+ // add this line to register MyComponent as 'MyComponent' in QML.
+ QML_ELEMENT
+ ....
+};
+\endcode
+
+See \l{Registering C++ Types with the QML Type System} on how to handle more complicated
+registration cases like foreign type registration.
+
+Delete the handwritten \c qmltypes files after that.
+
+\section1 Remove handwritten type registration plugins
+
+\l qt_add_qml_module can generate a \l {Creating C++ Plugins for QML}{QML module plugin}
+automatically for you. You don't need a handwritten plugin if your plugin's only task is to do type
+registration. Remove the plugin altogether if switching to declarative type registration did remove
+all the code from your plugin.
+
+Make sure that you \e remove the \c NO_PLUGIN, \c NO_PLUGIN_OPTIONAL, \c
+NO_CREATE_PLUGIN_TARGET, and \c NO_GENERATE_PLUGIN_SOURCE arguments from \l qt_add_qml_module to
+allow automatic plugin generation.
+
+\section1 Remove qrc files
+
+\l qt_add_qml_module automatically generates \c qrc files. To list resources in the \c qrc files,
+like images or sound files, add them to \l{qt_add_qml_module}'s \c RESOURCES argument.
+You can find the Module's resources under \c{:/qt/qml/MyQmlLibraryModule/}.
+
+\section1 Replace directory imports with QML module imports
+
+Replace directory imports with QML module imports. For example,
+\badcode
+import "content" // contains SomeType.qml
+// becomes
+import MyQmlModule // contains SomeType.qml
+
+SomeType {
+ ...
+}
+\endcode
+
+Note that files inside a QML module automatically import their own QML module. You can remove the
+self-imports.
+
+\sa {Changes to Qt QML}, {Modern QML modules}
+*/