Document qmltc tool

Add initial qmltc tool documentation with introduction,
compilation process picture, description and limitations

To simplify the description, we can consider some simple
application. The same app can additionally become a test
scenario for qmltc and a showcase of its capabilities

Task-number: QTBUG-84368
Pick-to: 6.3
Change-Id: If6d586a8c68f48d17133b25170d0fff627e2066c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Andrei Golubev 2021-12-13 17:12:46 +01:00
parent 7361545622
commit de30f10aeb
10 changed files with 871 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,47 @@
set(application_name tst_qmltc_examples)
#[[
#! [qmltc-app-name]
# Use "my_qmltc_example" as an application name:
set(application_name my_qmltc_example)
#! [qmltc-app-name]
]]
qt_internal_add_test(${application_name}
SOURCES
tst_qmltc_examples.cpp
colorpicker.h colorpicker.cpp
LIBRARIES
Qt::Core
Qt::Qml
Qt::Quick
Qt::QuickTemplates2Private # special
Qt::Gui
)
#! [qmltc-add-qml-module]
# Create a CMake target, add C++ source files, link libraries, etc...
# Make the application into a proper QML module:
qt6_add_qml_module(${application_name}
VERSION 1.0
URI QmltcExample
QML_FILES
myApp.qml
MyButton.qml
MySlider.qml
)
#! [qmltc-add-qml-module]
#! [qmltc-compile-to-cpp]
# (qmltc-specific) Link *private* libraries that correspond to QML modules:
target_link_libraries(${application_name} PRIVATE Qt::QmlPrivate Qt::QuickPrivate)
# Compile qml files (listed in FILES) to C++ using qmltc and add these files to
# the application binary:
qt6_target_compile_qml_to_cpp(${application_name}
FILES
myApp.qml
MyButton.qml
MySlider.qml
)
#! [qmltc-compile-to-cpp]

View File

@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick
Rectangle {
id: button
property alias text: textItem.text
signal clicked()
readonly property color constantColor: "#63ACBE"
color: mouseArea.pressed ? Qt.lighter(constantColor) : constantColor
width: textItem.implicitWidth + 5
height: textItem.implicitHeight + 5
radius: 10
Text {
id: textItem
font.pixelSize: 22
color: "black"
anchors.centerIn: button
}
MouseArea {
id: mouseArea
anchors.fill: button
anchors.margins: -5
onClicked: function(event) { button.clicked(); }
}
}

View File

@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick
import QtQuick.Templates as T // we cannot use QQC2 (yet), but we can use its backend
T.Slider {
id: control
// QQC2-specific begin
implicitWidth: Math.max(control.implicitBackgroundWidth + control.leftInset
+ control.rightInset,
control.implicitHandleWidth + control.leftPadding
+ control.rightPadding)
implicitHeight: Math.max(control.implicitBackgroundHeight + control.topInset
+ control.bottomInset,
control.implicitHandleHeight + control.topPadding
+ control.bottomPadding)
padding: 6
// QQC2-specific end
background: Rectangle {
x: control.leftPadding
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: control.availableWidth
height: implicitHeight
radius: 2
border.color: "black"
color: "#F9F3EC"
Rectangle {
width: control.visualPosition * parent.width
height: parent.height
color: "#63ACBE"
radius: 2
}
}
handle: Rectangle {
x: control.leftPadding + control.visualPosition * (control.availableWidth - width)
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 26
implicitHeight: 26
radius: 13
color: control.pressed ? Qt.lighter("#63ACBE") : "#63ACBE"
border.color: Qt.darker("#63ACBE")
}
}

View File

@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "colorpicker.h"
#include <QtCore/qlogging.h>
void MyColorPicker::setEncodedColor(double value)
{
if (value < 0.0 || !(value < 1.0)) {
qWarning("Bad value, %f, cannot get color from it!", value);
return;
}
m_encodedColor = value;
}
QBindable<double> MyColorPicker::bindableEncodedColor()
{
return QBindable<double>(&m_encodedColor);
}
QColor MyColorPicker::decodeColor()
{
const double encodedValue = m_encodedColor;
constexpr int rgbFirst = 0;
constexpr int rgbLast = 256 * 256 * 256;
const QRgb rgb = rgbFirst + (rgbLast - rgbFirst) * encodedValue;
return QColor(rgb);
}

View File

@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qobject.h>
#include <QtCore/qproperty.h>
#include <QtQml/qqmlregistration.h>
#include <QtGui/qcolor.h>
class MyColorPicker : public QObject
{
Q_OBJECT
QML_ELEMENT
// Stores a value in the range [0, 1); myApp.qml type sets this with
// Math.random()
Q_PROPERTY(double encodedColor READ encodedColor WRITE setEncodedColor BINDABLE bindableEncodedColor)
QProperty<double> m_encodedColor{0.5};
public:
MyColorPicker(QObject *parent = nullptr) : QObject(parent) {}
double encodedColor() { return m_encodedColor; }
void setEncodedColor(double value);
QBindable<double> bindableEncodedColor();
// Returns a QColor "decoded" from encodedColor
Q_INVOKABLE QColor decodeColor();
};

View File

@ -0,0 +1,119 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick
import QmltcExample 1.0 // application's own QML module
Rectangle {
id: window
width: 640
height: 480
focus: true
color: "#F9F4EC"
readonly property color textColor: "#601A4A"
Row {
id: row
anchors.centerIn: window
spacing: 10
Column {
id: column
spacing: 5
Text {
text: "Hello, QML World!"
font.pixelSize: slider.value
color: textColor
}
MySlider {
id: slider
from: 20
value: 20
to: 30
}
}
Column {
spacing: 5
Text {
id: rndText
font.pixelSize: 25
color: textColor
}
Rectangle {
id: rndColorRect
height: 20
width: rndButton.width
color: "black"
MyColorPicker { // comes from C++
id: colorPicker
onEncodedColorChanged: rndColorRect.color = colorPicker.decodeColor()
}
}
MyButton {
id: rndButton
text: "PICK"
onClicked: function() {
var value = Math.random();
rndText.text = value.toFixed(rndButton.text.length - 2);
colorPicker.encodedColor = value;
}
}
}
}
}

View File

@ -0,0 +1,153 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
// Note: this file is published under a license that is different from a default
// test sources license. This is intentional to comply with default
// snippet license.
#include <QtGui/qguiapplication.h>
#include <QtCore/qtimer.h>
#include <QtTest/qtest.h>
#include <QtQuick/qquickwindow.h>
//! [qqmlcomponent-include]
#include <QtQml/qqmlcomponent.h>
//! [qqmlcomponent-include]
//! [qmltc-include]
#include "myapp.h" // include generated C++ header
//! [qmltc-include]
class tst_qmltc_examples : public QObject
{
Q_OBJECT
static constexpr int m_argc = 1;
static constexpr char *m_argv[] = { const_cast<char *>("tst_qmltc_examples") };
public:
tst_qmltc_examples(QObject *parent = nullptr) : QObject(parent) { }
private slots:
void app();
void appComponent();
};
#define CREATE_DUMMY_ARGC_ARGV() \
int argc = 1; \
char *argv[] = { const_cast<char *>("tst_qmltc_examples") };
void tst_qmltc_examples::app()
{
CREATE_DUMMY_ARGC_ARGV()
//! [qmltc-app-code]
QGuiApplication app(argc, argv);
app.setApplicationDisplayName(QStringLiteral("This example is powered by qmltc!"));
QQmlEngine e;
QQuickWindow window;
QScopedPointer<myApp> documentRoot(new myApp(&e));
documentRoot->setParentItem(window.contentItem());
window.setHeight(documentRoot->height());
window.setWidth(documentRoot->width());
// ...
//! [qmltc-app-code]
QTimer::singleShot(1000, &app, QGuiApplication::quit);
//! [qmltc-app-exec]
window.show();
app.exec();
//! [qmltc-app-exec]
}
void tst_qmltc_examples::appComponent()
{
CREATE_DUMMY_ARGC_ARGV()
//! [qqmlcomponent-app-code-0]
QGuiApplication app(argc, argv);
app.setApplicationDisplayName(QStringLiteral("This example is powered by QQmlComponent :("));
QQmlEngine e;
QQuickWindow window;
QQmlComponent component(&e);
component.loadUrl(QUrl(QStringLiteral("qrc:/QmltcExample/myApp.qml")));
//! [qqmlcomponent-app-code-0]
QVERIFY2(!component.isError(), qPrintable(component.errorString()));
//! [qqmlcomponent-app-code-1]
QScopedPointer<QObject> documentRoot(component.create());
QQuickItem *documentRootItem = qobject_cast<QQuickItem *>(documentRoot.get());
//! [qqmlcomponent-app-code-1]
QVERIFY(documentRootItem);
//! [qqmlcomponent-app-code-2]
documentRootItem->setParentItem(window.contentItem());
window.setHeight(documentRootItem->height());
window.setWidth(documentRootItem->width());
// ...
//! [qqmlcomponent-app-code-2]
QTimer::singleShot(1000, &app, QGuiApplication::quit);
window.show();
app.exec();
}
#undef CREATE_DUMMY_ARGC_ARGV
QTEST_APPLESS_MAIN(tst_qmltc_examples)
#include "tst_qmltc_examples.moc"

View File

@ -0,0 +1,223 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qtqml-tool-qmltc.html
\title QML Type Compiler
\brief A tool to compile QML types to C++ ahead of time.
The QML Type Compiler, \c qmltc, is a tool shipped with Qt to translate QML
types into C++ types that are \e{ahead-of-time} compiled as part of the user
code. Using qmltc can lead to better run-time performance due to more
optimization opportunities available to the compiler compared to a
QQmlComponent-based object creation. The qmltc is part of the Qt Quick Compiler
toolchain.
By design, qmltc outputs user-facing code. That code is supposed to be utilized
by the C++ application directly, otherwise you won't see any benefit. The
generated code essentially replaces QQmlComponent and its APIs to create objects
from QML documents. In order to enable qmltc:
\list
\li Create a \l{qt_add_qml_module}{proper QML module} for your application.
\li Invoke qmltc, for example, through the \l{qt_target_compile_qml_to_cpp}
{CMake API}.
\li \c{#include} the generated header file(s) in the application source
code.
\li Instantiate an object of the generated type.
\endlist
In this workflow qmltc usually runs during the build process. Thus, when qmltc
rejects a QML document (whether due to errors or warnings, or because of
constructs qmltc doesn't yet support), the build process will fail. This is
similar to how you receive qmllint errors when you enable the automatic
generation of linting targets during \l{qt_add_qml_module}{QML module creation}
and then attempt to "build" them to run the qmllint.
\warning qmltc is currently in a Tech Preview stage and might not compile an
arbitrary QML program (see \l{Known limitations} for more details). When qmltc
fails, nothing is generated as your application cannot sensibly use the qmltc
output. If your program contains errors (or unsolvable warnings), they should be
fixed to enable the compilation. The general rule is to adhere to the best
practices and follow \l{qmllint} advice.
\section2 Using qmltc in a QML application
From the build system perspective, adding qmltc compilation is not much
different from adding qml cache generation. Naively, the build process could be
described as:
\image qmltc-compilation-scheme.png
While the real compilation process is much trickier, this diagram captures the
core components that qmltc uses: the QML files themselves and qmldir with
qmltypes information. Simpler applications typically have rather primitive
qmldir yet, in general, qmldir could be complex, providing essential, nicely
packed type information that qmltc relies on to perform correct QML-to-C++
translation.
Nevertheless, adding an extra build step is not enough in qmltc case. The
application code must also be modified to use qmltc-generated classes instead of
QQmlComponent or its higher-level alternatives.
\section3 Compiling QML code with qmltc
Qt, starting from Qt 6, uses CMake to build its various components. User
projects can - and are encouraged to - also use CMake to build their components
using Qt. Adding out-of-the-box qmltc compilation support to your project would
require a CMake-driven build flow as well since this flow is centered around
proper QML modules and their infrastructure.
The easy way to add qmltc compilation is by using the dedicated
\l{qt_target_compile_qml_to_cpp}{CMake API} as part of a QML module creation for
the application. Consider a simple application directory structure:
\badcode
.
├── CMakeLists.txt
├── myspecialtype.h // C++ type exposed to QML
├── myspecialtype.cpp
├── myApp.qml // main QML page
├── MyButton.qml // custom UI button
├── MySlider.qml // custom UI slider
└── main.cpp // main C++ application file
\endcode
Then the CMake code would usually look similar to the following:
\snippet qmltc/CMakeLists.txt qmltc-app-name
\codeline
\snippet qmltc/CMakeLists.txt qmltc-add-qml-module
\codeline
\snippet qmltc/CMakeLists.txt qmltc-compile-to-cpp
\section3 Using the generated C++
Unlike in the case of QQmlComponent instantiation, the output of qmltc, being
C++ code, is used directly by the application. Generally, constructing a new
object in C++ is equivalent to creating a new object through
QQmlComponent::create(). Once created, the object could be manipulated from C++
or, for example, combined with QQuickWindow to be drawn on screen. Given a
\c{myApp.qml} file, the application code (in both cases) would typically look
like this:
\table 100 %
\header
\li Using QQmlComponent
\li Using qmltc-generated class
\row
\li \snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-include
\li \snippet qmltc/tst_qmltc_examples.cpp qmltc-include
\row
\li \snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-app-code-0
\codeline
\snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-app-code-1
\codeline
\snippet qmltc/tst_qmltc_examples.cpp qqmlcomponent-app-code-2
\codeline
\snippet qmltc/tst_qmltc_examples.cpp qmltc-app-exec
\li \snippet qmltc/tst_qmltc_examples.cpp qmltc-app-code
\codeline
\snippet qmltc/tst_qmltc_examples.cpp qmltc-app-exec
\endtable
\section2 QML engine
The generated code uses QQmlEngine to interact with dynamic parts of a QML
document - mainly the JavaScript code. For this to work, no special arrangements
are needed. Any QQmlEngine instance passed to the constructor of a
qmltc-generated class object should work correctly as does
\c{QQmlComponent(engine)}. This also means that you can use
\l{QQmlEngine}{QQmlEngine methods} that affect QML behavior. However, there are
caveats. Unlike QQmlComponent-based object creation, qmltc itself \e{does not}
rely on QQmlEngine when compiling the code to C++. For instance,
\c{QQmlEngine::addImportPath("/foo/bar/")} - normally resulting in an additional
import path to scan for - would be completely ignored by the ahead-of-time qmltc
procedure.
\note To add import paths to the qmltc compilation, consider using a relevant
argument of the \l{qt_target_compile_qml_to_cpp}{CMake command} instead.
Generally, you can think of it this way: QQmlEngine involves the application
process to run, while qmltc does not as it operates \e{before} your application
is even compiled. Since qmltc makes no attempt to introspect your application's
C++ source code, there is no way for it to know about certain kinds of QML
manipulations you, as a user, do. Instead of using QQmlEngine and related
run-time routines to expose types to QML, adding import paths, etc. you are,
practically, required to create \l{qt_add_qml_module}{well-behaving QML modules}
and use \l{Defining QML Types from C++}{declarative QML type registration}.
\warning Despite qmltc working closely with QQmlEngine and creating C++ code,
the generated classes cannot be further exposed to QML and used through
QQmlComponent.
\section2 Known limitations
Despite covering many common QML features, qmltc is still in the early stage of
development with many things yet to be supported. To name a few:
\list
\li Translation APIs (qsTr() and similar methods)
\li Inline components
\li Imported QML modules that consist of QML-defined types (such as
\c{QtQuick.Controls}). At present, you can reliably use \c{QtQml} and
\c{QtQuick} modules as well as any other QML module that \b{only} contains
C++ classes exposed to QML
\li Singleton QML types
\endlist
On top of this, there are some more fundamental peculiarities to consider:
\list
\li Qt's QML modules usually rely on C++ libraries to do the heavy lifting.
Often enough, these libraries do not provide public C++ API (since their
primary usage is through QML). For the users of qmltc, this means that their
apps need to link against private Qt libraries.
\li Due to the nature of qmltc code generation, QML plugins are unusable for
compilation purposes. Instead, QML modules - that use a plugin - have to
ensure that the plugin data is accessible at compile time. Such QML modules
would then have \e optional plugins. In most cases, the compile-time
information can be provided through a header file (with C++ declarations)
and linkable library (with C++ definitions). The user code is responsible
(usually through CMake) for including a path to the header file and linking
against the QML module library.
\endlist
Given the tech preview status of the compiler, you might also encounter bugs in
qmltc, in the generated code, or some other related part. We encourage you to
\l{https://bugreports.qt.io/}{submit a bug report} in this case.
*/

View File

@ -143,3 +143,8 @@ qt_internal_target_compile_qml_to_cpp(tst_qmltc_nodiskcache
FILES FILES
${qml_sources} ${qml_sources}
) )
# Add qmltc documentation example to the tests. This is not beautiful but allows
# to nicely test the documentation snippets automatically (and so making sure
# the code there is up-to-date)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/qml/doc/snippets/qmltc snippets)