diff options
author | Dominik Holland <dominik.holland@qt.io> | 2021-09-16 16:00:07 +0200 |
---|---|---|
committer | Dominik Holland <dominik.holland@qt.io> | 2021-09-22 13:51:56 +0200 |
commit | fe874d5625c324e76f2beccb16b8036498c26165 (patch) | |
tree | 6c832a2f4b42fd0b0bc4f94b53f3f3087f4c90fa /examples/interfaceframework/qface-climate/doc | |
parent | 69377143cc5fab6cf68c892305252ef00c0a6d05 (diff) |
Refactor examples and its documentation
* Remove -if- in example names
* Replace _ in example names with -
* Move all related docs and images to the example folder
Pick-to: 6.2
Change-Id: I1fe38c7d4d735c48224c8bdf8622c701ab056070
Reviewed-by: Robert Griebl <robert.griebl@qt.io>
Diffstat (limited to 'examples/interfaceframework/qface-climate/doc')
-rw-r--r-- | examples/interfaceframework/qface-climate/doc/images/qface-climate.png | bin | 0 -> 39319 bytes | |||
-rw-r--r-- | examples/interfaceframework/qface-climate/doc/src/qface-climate.qdoc | 325 |
2 files changed, 325 insertions, 0 deletions
diff --git a/examples/interfaceframework/qface-climate/doc/images/qface-climate.png b/examples/interfaceframework/qface-climate/doc/images/qface-climate.png Binary files differnew file mode 100644 index 00000000..7c4f943c --- /dev/null +++ b/examples/interfaceframework/qface-climate/doc/images/qface-climate.png diff --git a/examples/interfaceframework/qface-climate/doc/src/qface-climate.qdoc b/examples/interfaceframework/qface-climate/doc/src/qface-climate.qdoc new file mode 100644 index 00000000..7cfc0ac1 --- /dev/null +++ b/examples/interfaceframework/qface-climate/doc/src/qface-climate.qdoc @@ -0,0 +1,325 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2019 Luxoft Sweden AB +** Copyright (C) 2018 Pelagicore AG +** 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$ +** +****************************************************************************/ + +/*! +\example interfaceframework/qface-climate +\brief This Example shows how to use the Qt Interface Framework Generator. +\ingroup qtinterfaceframework-examples +\title Qt Interface Framework Generator Climate Example +\image qface-climate.png + +\section1 Introduction + +This example shows you how you can use the Qt Interface Framework Generator to build a new component. Based on a +single QFace IDL file, the example generates: + +\list + \li a shared library with the frontend code + \li a backend simulator plugin + \li a demo application that shows the values in the current module +\endlist + +\section1 The IDL File + +The IDL file used in this example represents a simplified climate control interface that contains a +single interface and some enumerated types. + +Let's take a look at a minimal version of the same QFace IDL file: + +\code +module Example.If.Climate 1.0; + +interface ClimateControl { + bool airConditioning; + int fanSpeedLevel; + RecirculationMode recirculationMode; + AirflowDirection airflowDirections; +} + +enum RecirculationMode { + RecirculationOff = 0x0, + RecirculationOn = 0x1, + AutoRecirculation = 0x2 +} + +flag AirflowDirection { + Windshield = 1, + Dashboard = 2, + Floor = 4 +} +\endcode + +\section2 Walkthrough + +First, we need to define which \c module we want to describe. The \c module acts as a namespace, +because the IDL file can contain multiple interfaces. + +\code +module Example.If.Climate 1.0; +\endcode + +The most important part of the \c module is its \c interface definition. + +\code +interface ClimateControl { + bool airConditioning; + int fanSpeedLevel; + RecirculationMode recirculationMode; + AirflowDirection airflowDirections; +} +\endcode + +In this case, we define an \c interface named \b ClimateControl consisting of a few properties it +should offer. Each property definition must contain at least a type and a name. Most of the +basic types are built-in and can be found in the \l {QFace IDL syntax}. The last two properties +are special as they use custom types, that are defined after the \c interface definition. + +\code +enum RecirculationMode { + RecirculationOff = 0x0, + RecirculationOn = 0x1, + AutoRecirculation = 0x2 +} + +flag AirflowDirection { + Windshield = 1, + Dashboard = 2, + Floor = 4 +} +\endcode + +The first definition is an \c enum with all the values it supports, including the numeric value +of each individual item. The second definition is similar, but using the \c flag type. + +\section2 Comments and Annotations + +Compared to the minimal IDL we saw in the previous section, the full +\fileLink {examples/interfaceframework/qface-climate/example-climate.qface}{IDL file} contains a lot of comments +and annotations. + +Comments starting with \c /** define documentation statements and can be converted into +documentation markup like QDoc or Doxygen, by the generation template. + +\section3 Annotations + +Annotations are used to add additional information to the IDL statements. They are YAML fragments +that provide a key-value store. The generation template defines the supported annotations. + +Here's an overview of all the annotations used in this example and what they do: + +\table + \header + \li Annotation + \li Description + \row + \li \code + @config: {zoned: true} + \endcode + \li Specifies that the interface supports different zones. + \row + \li \code + @config: {qml_type: "UiClimateControl"} + \endcode + \li Specifies the component name when used from QML. + \row + \li \code + @config: {id: "example.interfaceframework.ClimateControl/1.0"} + \endcode + \li Specifies the ID used to match backend plugins. + \row + \li \code + @config_simulator: { range:[0, 50] } + \endcode + \li Specifies a range of valid values for numerical properties. + \note The \c {range} annotation used here is a shortcut to specify both minimum and + maximum values. + \row + \li + \code + @config_simulator: { minimum: 0; maximum: 50 } + \endcode + \li Specifies the minimum and maximum values for numerical properties. + + \row + \li \code + @config_simulator: { domain: ["cold", "mild", "warm" ] } + \endcode + \li Specifies a list of valid values for properties. + \row + \li \code + @config: {interfaceBuilder: "echoInterfaceBuilder"} + \endcode + \li Specifies that the plugin should use a custom function to generate the backend + instances. +\endtable + +In addition to the IDL file, a YAML file with the same basename is used to add extra +configurations. These configurations may also be added directly into the IDL file, but we choose +to keep them separate for readability. + +Some of these extra configurations are highlighted below: + +\table + \row + \li + \code + Example.If.Climate.ClimateControl: + config_simulator: + zones: { left : FrontLeft, right : FrontRight, rear: Rear } + \endcode + \li Defines the names for the supported zones. + \row + \li + \code + Example.If.Climate.ClimateControl#recirculationMode: + config_simulator: + default: RecirculationMode.RecirculationOff + \endcode + \li Specifies the default value assigned to a property in the simulator backend plugin. +\endtable + + +\section1 Frontend Library + +Now we want to use the Interface Framework Generator to generate a shared library that contains a C++ +implementation of our module and its interface. + +In this case, we use the \c frontend template, that generates a class derived from +\c {QIfAbstractZonedFeature} including all the specified properties. The generated library uses +the \l {Dynamic Backend System} from QtInterfaceFramework, providing an easy way to change the behavior +implementations. For more details, see \l {Backend Simulator Plugin}. + +To call the autogenerator for our shared library, it needs to be integrated into the build system. + +\e CMake: + +First the \c InterfaceFramework package needs to be found using \c find_package: + +\snippet interfaceframework/qface-climate/frontend/CMakeLists.txt 0 + +Afterwards we proceed to build a library and let the autogenerator extend this target with +the generated source code by invoking \l {qt6_ifcodegen_extend_target}. + +\snippet interfaceframework/qface-climate/frontend/CMakeLists.txt 1 + +\e qmake: + +The qmake project file needs to use the \c ifcodegen qmake feature. The snippet below shows how +to do this: + +\snippet interfaceframework/qface-climate/frontend/frontend.pro 1 + +By adding \c ifcodegen to the \c CONFIG variable, the \c ifcodegen feature file is loaded +and interprets the \c IFCODEGEN_SOURCES variable just like the \c SOURCES variable in normal qmake +projects. + +However, activating the qmake feature using the \c CONFIG variable has one disadvantage: it +doesn't report any errors if this feature is not available. But, you can use the following +additional code to report errors: + +\snippet interfaceframework/qface-climate/frontend/frontend.pro 0 + +The other part of the project file is a normal library setup which should work on Linux, macOS, +and Windows. + +\section1 Backend Simulator Plugin + +Since the \c frontend library uses the \l {Dynamic Backend System}, we need a corresponding +\c backend plugin, for the library to provide some functionality. To generate a mock version of +the backend plugin called "Simulator Backend", you can use the \c backend_simulator template from +the same IDL file as the \c frontend library. The build system integration works in the same way, but it +uses a different generation template. + +\e CMake: + +A plugin is defined and extended by calling the codegenerator, this time with the \c backend_simulator +template: + +\snippet interfaceframework/qface-climate/backend_simulator/CMakeLists.txt 2 + +\e qmake: + +As we want to generate a plugin instead of a plain library, we need to instruct qmake to do so by +adding \c plugin to the \c CONFIG variable. + +\snippet interfaceframework/qface-climate/backend_simulator/backend_simulator.pro 2 + +For the plugin to compile correctly it needs to get the backend interface header from the previously +created library. However, this header is not part of our source tree but the build tree, because it +is also generated. We provide this header by adding it to the include path using the following code: + +\e CMake: + +\snippet interfaceframework/qface-climate/backend_simulator/CMakeLists.txt 1 + +\e qmake: + +\snippet interfaceframework/qface-climate/backend_simulator/backend_simulator.pro 1 + +The \c backend_simulator template makes use of the \b @config_simulator annotations explained +\l{Annotations}{above}. This means that the generated backend provides the default values defined +in the annotations and checks the boundaries of new values using the \c minimum/maximum or \c range +annotations. + +Using the \c zones annotations, the generated backend provides individual values for every zone +and communicates the available zones to the frontend library. For more information, see the +\l {Climate Control QML Example}. + +\section1 Demo Application + +The demo application presents a simple QML interface with all the properties of the generated +interface. + +Since we do not provide a QML plugin, the application needs to link to the generated frontend +library and call the \c {ClimateModule::registerTypes} and \c {ClimateModule::registerQmlTypes} +methods that are generated in the module singleton to register all autogenerated interfaces and +types with the QML engine. + +In our QML application, we still need to import the module using the same module URI used +in the IDL file. Afterwards, the interface can be instantiated like a regular QML item. + +\snippet interfaceframework/qface-climate/demo/main.qml 0 +\dots 0 + +Our application doesn't know about our backend plugin, so, we need to put this plugin in the folder +where our application looks for plugins. By default, Qt looks in the \b plugins folder within its +installation directory or in the application's current working directory. For QtInterfaceFramework plugins to be +found, they need to be placed within a \b interfaceframework sub-folder. + +To make sure this is done automatically, we add the following line to our backend build system file: + +\e CMake: + +\snippet interfaceframework/qface-climate/backend_simulator/CMakeLists.txt 0 + +\e qmake: + +\snippet interfaceframework/qface-climate/backend_simulator/backend_simulator.pro 0 + +*/ |