summaryrefslogtreecommitdiff
path: root/src/ivicore/doc/src/examples-qface-ivi-climate.qdoc
blob: d14ea50d274abf7e7f9cf5c185f7d744584c8781 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/****************************************************************************
**
** Copyright (C) 2018 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the QtIvi module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL-QTAS$
** Commercial License Usage
** Licensees holding valid commercial Qt Automotive Suite 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 ivicore/qface-ivi-climate
\brief This Example shows how to use the Qt IVI Generator.
\ingroup qtivicore-examples
\title Qt IVI Generator Climate Example
\image examples_qface_ivi_climate.png

\section1 Introduction

This shows an example of using the Qt IVI Generator to build a new component. Based on a single
qface IDL file, it will generate:

\list
\li a shared library with the front-end code
\li a back-end simulator plugin
\li a demo application showing the current model values
\endlist

\section1 The IDL File

The IDL file used in the example represents a simplified climate control interface. It contains a
single interface and a couple of enumerated types.

Lets first look at a more minimal version of the same QFace IDL file:

\code
module Example.IVI.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 \e module we want to describe. The \e module acts as a namespace,
because the IDL file can contain multiple interfaces.

\code
module Example.IVI.Climate 1.0;
\endcode

The most important part is the definition of the \e interface.

\code
interface ClimateControl {
    bool airConditioning;
    int fanSpeedLevel;
    RecirculationMode recirculationMode;
    AirflowDirection airflowDirections;
}
\endcode

In this case, we define an \e interface named \b ClimateControl consisting of a few properties it
should offer. Every property definition needs to contain at least a type and a name. Most of the
basic types are builtin and can be found in the \l {QFace IDL syntax} {reference}. The last two
properties are more special as they use custom types, which are defined after the \e 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 \e enum and all the values it supports, including the numeric value
of each individual item. The second definition is similar, but using the type \e flag.

The complete reference for the IDL syntax is available \l {QFace IDL syntax}{here}.

\section2 Documentation and Annotations

In the previous section we walked through a simplified version of the example's IDL file. The
full \l {ivicore/qface-ivi-climate/example-ivi-climate.qface} {IDL file} also contains a lot of
documentation comments and annotations.

Comments starting with \e /** define documentation statements and can be converted into common
documentation languages 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
providing a key-value store. Which annotations are supported is defined by the generation template.

Here's an overview of all the annotations used in this example and what they do:

\table
\row
    \li \code {@config: {zoned: true}} \endcode
    \li indicates the interface supports different zones
\row
    \li \code {@config: {qml_type: "UiClimateControl"}} \endcode
    \li the component name when used from QML
\row
    \li \code {@config: {id: "example.qtivi.ClimateControl/1.0"}} \endcode
    \li indicates the id used for matching backend plugins
\row
    \li \code {@config_simulator: { range:[0, 50] }} \endcode
    \li range of valid values for number type properties
\row
    \li \code
    {@config_simulator: { minimum: 0 }}
    {@config_simulator: { maximum: 50 }} \endcode
    \li minimum and maximum values for number type properties.
    \note \c {range} annotation is a shortcut to specifying both minimum and
    maximum values.
\row
    \li \code {@config_simulator: { domain: ["cold", "mild", "warm" ] }} \endcode
    \li list of valid values for properties
\row
    \li \code {@config: {interfaceBuilder: "echoInterfaceBuilder"}} \endcode
    \li indicates 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 in to the IDL file, but keeping
them separate can improve readability.

Highlights:
\table
\row
    \li
    \code
    Example.IVI.Climate.ClimateControl:
        config_simulator:
            zones: { left : FrontLeft, right : FrontRight, rear: Rear }
    \endcode
    \li the names of the supported zones
\row
    \li
    \code
    Example.IVI.Climate.ClimateControl#recirculationMode:
        config_simulator:
            default: RecirculationMode.RecirculationOff
    \endcode
    \li the default value assigned to the property in the simulator backend plugin.
\endtable


\section1 Frontend library

What the IDL file is and what it contains, was described in the previous section. Now we want to
use the ivigenerator to generate a shared library containing a C++ implementation of our module and
its interface.

For this, the \e frontend template is used. This will generate a class derived from \c
{QIviAbstractZonedFeature} including all the specified properties. The generated library will use
the \l {Dynamic Backend System} from QtIviCore and by that provide an easy way to change the
behavior implementations. More on that in the \l {Backend Simulator Plugin} section.

In order to call the autogenerator for our shared library, the qmake project file needs to use the
\e ivigenerator qmake feature. The following snippet shows how it can be added:

\snippet ../../../../examples/ivicore/qface-ivi-climate/frontend/frontend.pro 1

By adding \e ivigenerator to the \e CONFIG variable, the \e ivigenerator feature file will be
loaded and interpret the \e QFACE_SOURCES variable similar to \e SOURCES variable of normal qmake
projects.
Activating the qmake feature using the \e CONFIG variable has the disadvantage that it doesn't
report any errors if the feature is not available. Because of this, it is encouraged to use the
following additional code to report errors:

\snippet ../../../../examples/ivicore/qface-ivi-climate/frontend/frontend.pro 0

The other part of the project file is a normal library setup which is supposed to work on
Linux, macOS and Windows.

\section1 Backend Simulator Plugin

As mentioned above, the \e frontend library will use the \l {Dynamic Backend System}. This means
that for the library to provide some functionality, we also need a \e backend plugin. A mockup
version of the backend plugin called "Simulator Backend" can be generated using the \e
backend_simulator template from the same IDL file as the \e frontend library. The qmake integration
works in the same way, but it is using the \e QFACE_FORMAT variable to tell the ivigenerator to use
a different generation template.

\snippet ../../../../examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro 2

As we want to generate a plugin instead of a plain library, we need to instrument qmake to do so by
adding \e plugin to the \e CONFIG variable. For the plugin to compile correctly it needs to get the
backend interface header from the previously created library. As this header is also generated, it
is not part of our source tree, but part of the build tree. We do this by adding it to the include
path using the following construct:

\snippet ../../../../examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro 1

The \e backend_simulator template will make use of the \b @config_simulator annotations explained
above. This means the generated backend will provide the default values defined in the annotations
and check the boundaries of new values using the \e minimum/maximum or \e range annotations.

Using the \e zones annotations the generated backend will provide individual values for every zone
and communicate the available zones to the frontend library. More about how to work with zones can
be seen in 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.

As we do not provide a QML plugin, the application needs to link to the generated frontend library
and call the \e {ClimateModule::registerTypes} and \e {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 name we provided to \e
{ClimateModule::registerQmlTypes}. Afterwards the interface can be instantiated like any other
QML item.

\snippet ../../../../examples/ivicore/qface-ivi-climate/demo/main.qml 0
\dots 0

As our application doesn't know about the existence of our backend plugin, we need to put this
plugin in a folder where our application searches for plugins. By default Qt either search in the
\b plugins folder within Qt's installation directory or in the current working directory of the
application. For QtIvi plugins to be found, they need to be provided within a \b qtivi sub-folder.
This is achieved automatically by adding the following line to our backend project file:

\snippet ../../../../examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro 0

*/