Autogenerator usage

This page is about the usage of the QtIVI auto-generator.

Introduction

The Generator is a Python script that can be run manually or using the QMake Integration. This script uses QFace as the autogenerator framework which parses the IDL file, generates the domain-model (similar to AST) and then feeds it to the actual generator. Depending on the type of the generated project, different formats are specified.

Command line parameters

The generation is run using the following command:

$$[QT_HOST_BINS]/ivigenerator/generate.py --format=backend_simulator interface.qface out_dir

The options and parameters are:

--reload / --no-reload [optional]specifies whether the generator should keep track of the changes in the IDL file and update output on the fly (--no-reload by default)
-f, --format [frontend|backend_simulator|control_panel|backend_qtro|server_qtro|<folder>]see below
-A, --annotations <annotation-file>Merges the given annotation file with annotions already in the qface file and the implicit annotation file. The annotation files will be merged in the order they are passed to the generator. Providing a duplicate key in the YAML file will override the previously set value. This option can be used multiple times.
sourcePath or paths to the IDL source files. In case of multiple entries present, each one will be handled. In case a directory path is provided, it will be scanned for all the IDL files.
outputdirGeneration destination folder
--helpShow options and exit.

At the moment the generator is able to generate 5 kinds of projects given an interface IDL file based on the --format option value. These are:

frontend Generates a developer facing API using base classes from qtivicore and the Dynamic Backend System
backend_simulator Generates a simulation backend for the API generated by the "frontend" option. This backend serves as a mock implementation.
control_panel Generates a controller application, consisting of an UI and a C++ plugin, which communicates to the simulation backend generated from the same qface file using QtSimulator.
backend_qtro Generates a QtRemoteObjects based backend client for the API generated by the "frontend" option. This backend connects to a backend server.
server_qtro Generates a QtRemoteObjects based backend server stub for the API generated by the "frontend" option.
folder pathUses templates inside the folder. A YAML file with the same name as the folder (and .yaml extension) should provide a list of template files in the folder (see YAML format specification below).

YAML configuration

The Python script is responsible for parsing the input files and for the creation of a domain model. This domain model is passed as a context to the Jinja template engine. To control which files are generated, the "Generation YAML" can be used. In addition, an "Annotations YAML" can be used to add more information to the IDL file, which are generator specific.

Generation YAML

After the domain model tree has been created, this tree is traversed and each leaf of the domain model object tree (module, interface, structure, etc) is passed to a specific Jinja template defined by the configuration file. This file must be in YAML format and for every particular generation format its name is defined in the script. This file must have the following structure:

generate_rules:
    module_rules:
        -   dest_file:  "{{module.module_name|lower}}plugin.h"
          template_file:  "plugin.h.tpl"
    interface_rules:
        -   dest_file: '{{interface|lower}}backend.h'
          template_file: 'backend.h.tpl'
    struct_rules:

For every entity there is a list of templates needed to be called when traversing this entity in the domain model tree. Here, dest_file is a name of the file need to be created specified in the Jinja template language format: the value of the object property used in the name template will be processed and substituted into the template, thus forming the final name of the file to create. dest_file is a name of the template to be used. For the IVI generator, rules for three kinds of entities need to be specified: modules, interfaces and structures.

Annotations YAML

At the moment not all aspects of the interface description cannot be expressed using the IDL itself. For instance there is no language construct to define default value for the property or values the property can take on. Still this can be achieved via a mechanism called Annotations. Annotations allow great freedom and flexibility of expressing any concepts and constructs.

Below is an example of using annotations in the IDL. Here it's defined that interface is zoned and its identifier is specified.

@config: {zoned: true, id: "org.qt-project.qtivi.ClimateControl/1.2" }

Not all of the annotations make sense to be put in the main IDL file either. For instance, one may need to define some aspects of generation of the auto-testing code. Such annotations can be put in the YAML file accompanying the main IDL file and named after it. During the parse phase QFace picks this file up automatically and merges annotation specified in this YAML file with those defined in the IDL file.

As the accompanying YAML file is automatically picked up in all cases, this doesn't work for annoations which are only needed for some specific projects e.g. when generating a backend plugin. For this use case you can pass multiple additional annotation YAML files to the generator.

For QtIvi there are following annotations used for the IDL definition:

TagWhereObject typePurpose
@config(interfaceBuilder: "FunctionName")Main IDL fileModuleDeclares a function which will be called in the plugin to generate the instances for every interface. The function takes a pointer to the plugin instance and returns a QVector<QIviFeatureInterface *>. Interfaces should be generated in the same order as defined by Plugin::interfaces().

This can be used to instanciate classes derived from the generated plugin interfaces classes.

@config(zoned)Main IDL fileInterfacetells the generator whether the interface is zoned or not. This allows to define whether the backend feature interface is derived from QIviZonedFeatureInterface or from QIviFeatureInterface
@config(id=org.qt.project.qtivi.ClimateControl.1.0)Main IDL fileInterfacedefines the interface id. The id is a string used by the QtIvi service manager to glue frontend interface and backend implementation together. See Dynamic Backend System for more details.
@config(getter_name)Main IDL filePropertyOverrides the default getter method name. Useful for boolean properties (for example, getter for property 'enabled', should be 'isEnabled' rather than the default).
@config(setter_name)Main IDL filePropertyOverrides the default setter method name.
@config(qml_name)Main IDL fileModule, InterfaceDefines the name this interface/module should be using in QML. For interfaces, it is the name which is used to export the interface to QML. For modules it defines the uri of the complete module.

The annotations that are not logically part of the interface description but rather the ones used for specifying additional information are put in the accompanying YAML file. Here is the list of annotations used for defining various aspects of the generation of the backend-simulator:

TagWhereObject typePurpose
config_simulator:
     simulationFile: ":/qrc/simulation.qml"
Accompanying YAML fileModuleDefines which simulation QML file should be loaded by the simulation backend. The provided snippet loads the QML file from the resource system, which needs to be embedded by the developer.
config_simulator:
     zones: { FrontLeft, FrontRight, Rear }
Accompanying YAML fileInterfaceFor the backend simulator defines a list of zones supported by the simulation code.
config_simulator:
default: AirflowDirection.Floor | AirflowDirection.Dashboard
Accompanying YAML filePropertyDefines the initial values for the property returned by the simulator backend.

For zoned properties a mapping from a zone to a default value can be used. The default key of the map is "=".

config_simulator:
default: { FrontLeft: 21.0, FrontRight: 22.5, =: 0.0 }
config_simulator:
minimum: 10
Accompanying YAML filePropertyDefines the minimum value for integer and real properties, generated code in the simulator backend will check for validity.
config_simulator:
maximum: 10
Accompanying YAML filePropertyDefines the maximum value for integer and real properties, generated code in the simulator backend will check for validity.
config_simulator:
range: [10, 20]
Accompanying YAML filePropertyDefines the range value for integer and real properties, generated code in the simulator backend will check for validity.
config_simulator:
domain: {10, 20, 30}
Accompanying YAML filePropertyDefines the possible values for the property, generated code in the simulator backend will check for validity.

Generated projects structure

In the generator output directory first a new subfolder with the name of the module id will be created. All the generated files will be put in this folder. The following files will be generated:

Frontend

File namePurpose
"{{module.module_name|lower}}global.h"Standard file with global EXPORT defines
"{{module.module_name|lower}}module.h/cpp"Files defining a module class used for module global variables and types.
"{{module|lower|replace('.', '-')}}.pri"Standard Qt .pri file, containing all the generated files that can be used for including the autogenerated files into a qmake project.
"{{interface|lower}}backendinterface.h/cpp"Files defining the interface need to be implemented by the backend implementation of the feature
"{{interface|lower}}.h/cpp"Front end implementation of the feature, ready to be used from QML.
"{{interface|lower}}_p.h"Private part of the frontend implementation

Backend simulator

File namePurpose
"{{module.module_name|lower}}plugin.h/cpp"Files defining implementation of QtIvi backend plugin implementing QIviServiceInterface
"{{module.module_name|lower}}.json"File containing identifiers of the exposed feature interfaces needed by the Qt plugin system.
"{{module|lower|replace('.', '-')}}.pri"Standard Qt .pri file, containing all the generated files that can be used for including the autogenerated files into a qmake project.
"{{interface|lower}}backend.h/cpp"Files containing the implementation of the simulation backend.

Control Panel

The control_panel template is only available if the QtSimulator module was found. Please see the Configuration Page for more information.

Note: Currently the control_panel template doesn't support all qface features. At the moment models and structs are NOT supported.

File namePurpose
"main.cpp"Launcher code loading the QML code and exporting the C++ interface.
"main.qml"Main QML file containing the code to load the Control UIs for every interface.
"qml.qrc"QRC file for all QML code.
"FlagControl.qml"UI Element to control a flag inside a interface.
"EnumControl.qml"UI Element to control a enum inside a interface.
"{{module|lower|replace('.', '-')}}.pri"Standard Qt .pri file, containing all the generated files that can be used for including the autogenerated files into a qmake project.
"{{module.module_name|lower}}global.h"Standard file with global EXPORT defines
"{{module.module_name|lower}}module.h/cpp"Files defining a module class used for module global variables and types.
"{{interface|lower}}.h/cpp"C++ code retrieving and forwarding the state using QtSimulator.
"{{module.module_name|lower}}ControlUi.qml"Control UI for this interface. Contains a interface to control every property and method and log calls to signals.

QtRemoteObjects Backend

The backend_qtro template is only available if the QtRemoteObjects module was found. Despite the name, the remote object backend is not the location for the implementation of the actual backend logic, but just a client for connecting to the remote backend server.

File namePurpose
"{{module.module_name|lower}}plugin.h/cpp"Files defining implementation of QtIvi backend plugin implementing QIviServiceInterface
"{{module.module_name|lower}}.json"File containing identifiers of the exposed feature interfaces needed by the Qt plugin system.
"{{module|lower|replace('.', '-')}}.pri"Standard Qt .pri file, containing all the generated files that can be used for including the autogenerated files into a qmake project. Also adds the .rep file to the project and calls the remote object compiler.
"{{interface|lower}}backend.h/cpp"Files containing the implementation of the remote object backend. Establishes the connection and initializes the remote object replica.
"{{interface|lower}}.rep"The input file for Qt’s replica compiler for producing the replica class code.

QtRemoteObjects server

The server_qtro template is only available if the QtRemoteObjects module was found. The produced code contains merely the source classes to inherit and code for establishing the connection. It is up to the developer to implement the actual backend logic.

File namePurpose
"core.h/cpp"Code for establishing the connection and starting the remoting for the source objects.
"{{srcBase|lower}}.pri"Standard Qt .pri file, containing all the generated files that can be used for including the autogenerated files into a qmake project. Also includes the .rep file to the project and calls the remote object compiler.
"{{interface|lower}}.rep"The input file for the Qt’s replica compiler for producing the source class code.

© 2020 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.