Extending Qt Interface Framework

Introduction

Qt Interface Framework provides a pattern for extending Qt with more features in a way that suites the automotive use-case.

A key aspect is the separation between the front end that defines the API, from the back end that implements the functionality. This separation makes it possible to have multiple implementations of the same API which can be used to interface various hardware configurations, but also to provide stubbed or simulated implementations for early development and testing purposes.

The Big Picture

Qt Interface Framework consists of three types of building blocks. The core module provides base classes and common code for all the more specific modules and API definitions like a climate API or a media player API. Each of these APIs is the second building block called Feature, which defines the API used by the application developers. The last block consists of a back-end interface and one or more back ends implementing it to either connect to the underlying service or to a simulation of it.

Features

A feature is a set of classes for working with a specific function. It defines the interface towards application developers, but it does not implement the complete functionality. Instead, it defines a back-end interface to be implemented by a back end providing the actual functionality.

For easy deployment, Qt Interface Framework extensions should be built as Qt modules. This makes it easy to install and find headers, shared libraries, and plugin modules from app projects.

By using the module system the developer can easily enable the inclusion of his module in the following way:

QT += <module>

In addition, your module is properly set up to work with qdoc and auto test.

make tests

When creating a new Qt Interface Framework module, it is recommended that you pick a name such as PlatformFeatureName, where Platform is the name of the platform or product, and FeatureName is the name of the feature(s) of the module. In addition to the name, a reverse domain name prefix is needed for prefixing back-end interface names, for example com.example

Features are based on the QIfAbstractFeature base class, or QIfAbstractZonedFeature for zoned features. These classes provide the basic functions expected by users, e.g. back end loading.

Features define the back-end interface to be implemented by the back ends providing the functionality. The back-end interface is commonly based on the QObject class. It is important to keep this API as unbiased as possible, as there might be multiple back-end implementations relying on different technological solutions.

Some key rules to keep in mind are:

  • Keep everything asynchronous to avoid blocking the main loop.
  • Avoid call-to-signal sequences and try to keep signals independent from calls, For example, when a value change is signaled, it must not be due to a call to change the value from the feature (and visa versa). In other words a call to change a value is not required to always result in a value changed signal.
  • Implement stateless APIs whenever possible as the back end may be replaced at any time.

It is common to provide a stubbed back-end implementation and a testing back end with each feature.

Back ends

A back-end class is derived from the (commonly QObject-derived) back-end interface class specified by a feature. Instances of the back-end class are called service objects.

Back ends are implemented as an ordinary Qt C++ plugin project that depends on Qt Interface Framework Core and the corresponding feature module.

The back ends are loaded by Qt Interface Framework Core when the features request them. Each back end has to provide a Qt Interface Framework plugin that exposes a factory to the Core. This is what is used to load and create back ends. The plugin interface is called QIfServiceInterface.

Service Manager

In most cases, the back-end loading is handed over to the Qt Interface Framework Core. In some cases QIfServiceManager can manually search for plugins with a specific BackendInterface. The discovery and loading of the back ends takes place in this class.

The QIfServiceManager class can also be used to register back ends which are part of the same application and shouldn’t go into a plugin. This is especially useful for automated testing as you need to control the back end and the feature at the same time.

Common Practices

The reference APIs provided as a part of Qt Interface Framework introduce some common concepts. If implementing the same functionality, it is recommended to use these already defined patterns and it is encouraged to add API additions back to the Qt Interface Framework repository to create more common ground for future APIs.

© 2023 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.