summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorDominik Holland <dominik.holland@qt.io>2021-09-16 16:00:07 +0200
committerDominik Holland <dominik.holland@qt.io>2021-09-22 13:51:56 +0200
commitfe874d5625c324e76f2beccb16b8036498c26165 (patch)
tree6c832a2f4b42fd0b0bc4f94b53f3f3087f4c90fa /examples
parent69377143cc5fab6cf68c892305252ef00c0a6d05 (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')
-rw-r--r--examples/ifmedia/mediaplayer/doc/images/mediaplayer.pngbin0 -> 61704 bytes
-rw-r--r--examples/ifmedia/mediaplayer/doc/src/mediaplayer.qdoc60
-rw-r--r--examples/ifmedia/tuner/doc/images/tuner.pngbin0 -> 34382 bytes
-rw-r--r--examples/ifmedia/tuner/doc/src/tuner.qdoc124
-rw-r--r--examples/ifvehiclefunctions/CMakeLists.txt6
-rw-r--r--examples/ifvehiclefunctions/climate-qml/CMakeLists.txt (renamed from examples/ifvehiclefunctions/climate_qml/CMakeLists.txt)0
-rw-r--r--examples/ifvehiclefunctions/climate-qml/climate-qml.pro (renamed from examples/ifvehiclefunctions/climate_qml/climate_qml.pro)0
-rw-r--r--examples/ifvehiclefunctions/climate-qml/doc/images/climate-qml.pngbin0 -> 16135 bytes
-rw-r--r--examples/ifvehiclefunctions/climate-qml/doc/src/climate-qml.qdoc83
-rw-r--r--examples/ifvehiclefunctions/climate-qml/main.cpp (renamed from examples/ifvehiclefunctions/climate_qml/main.cpp)0
-rw-r--r--examples/ifvehiclefunctions/climate-qml/main.qml (renamed from examples/ifvehiclefunctions/climate_qml/main.qml)0
-rw-r--r--examples/ifvehiclefunctions/climate-qml/qml.qrc (renamed from examples/ifvehiclefunctions/climate_qml/qml.qrc)0
-rw-r--r--examples/ifvehiclefunctions/climate-widget/CMakeLists.txt (renamed from examples/ifvehiclefunctions/climate_widget/CMakeLists.txt)0
-rw-r--r--examples/ifvehiclefunctions/climate-widget/climate-widget.pro (renamed from examples/ifvehiclefunctions/climate_widget/climate_widget.pro)0
-rw-r--r--examples/ifvehiclefunctions/climate-widget/doc/images/climate-widget.pngbin0 -> 10433 bytes
-rw-r--r--examples/ifvehiclefunctions/climate-widget/doc/src/climate-widget.qdoc81
-rw-r--r--examples/ifvehiclefunctions/climate-widget/main.cpp (renamed from examples/ifvehiclefunctions/climate_widget/main.cpp)0
-rw-r--r--examples/ifvehiclefunctions/climate-widget/mainwindow.cpp (renamed from examples/ifvehiclefunctions/climate_widget/mainwindow.cpp)0
-rw-r--r--examples/ifvehiclefunctions/climate-widget/mainwindow.h (renamed from examples/ifvehiclefunctions/climate_widget/mainwindow.h)0
-rw-r--r--examples/ifvehiclefunctions/climate-widget/mainwindow.ui (renamed from examples/ifvehiclefunctions/climate_widget/mainwindow.ui)0
-rw-r--r--examples/ifvehiclefunctions/ifvehiclefunctions.pro6
-rw-r--r--examples/ifvehiclefunctions/window-qml/CMakeLists.txt (renamed from examples/ifvehiclefunctions/window_qml/CMakeLists.txt)0
-rw-r--r--examples/ifvehiclefunctions/window-qml/WindowItem.qml (renamed from examples/ifvehiclefunctions/window_qml/WindowItem.qml)0
-rw-r--r--examples/ifvehiclefunctions/window-qml/main.cpp (renamed from examples/ifvehiclefunctions/window_qml/main.cpp)0
-rw-r--r--examples/ifvehiclefunctions/window-qml/main.qml (renamed from examples/ifvehiclefunctions/window_qml/main.qml)0
-rw-r--r--examples/ifvehiclefunctions/window-qml/qml.qrc (renamed from examples/ifvehiclefunctions/window_qml/qml.qrc)0
-rw-r--r--examples/ifvehiclefunctions/window-qml/window-qml.pro (renamed from examples/ifvehiclefunctions/window_qml/window_qml.pro)0
-rw-r--r--examples/interfaceframework/CMakeLists.txt6
-rw-r--r--examples/interfaceframework/interfaceframework.pro6
-rw-r--r--examples/interfaceframework/qface-addressbook/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-addressbook/CMakeLists.txt)1
-rw-r--r--examples/interfaceframework/qface-addressbook/backend_simulator/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-addressbook/backend_simulator/CMakeLists.txt)4
-rw-r--r--examples/interfaceframework/qface-addressbook/backend_simulator/backend_simulator.pro (renamed from examples/interfaceframework/qface-if-addressbook/backend_simulator/backend_simulator.pro)4
-rw-r--r--examples/interfaceframework/qface-addressbook/backend_simulator/plugin_resource.qrc (renamed from examples/interfaceframework/qface-if-addressbook/backend_simulator/plugin_resource.qrc)0
-rw-r--r--examples/interfaceframework/qface-addressbook/backend_simulator/simulation.qml (renamed from examples/interfaceframework/qface-if-addressbook/backend_simulator/simulation.qml)0
-rw-r--r--examples/interfaceframework/qface-addressbook/demo/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-addressbook/demo/CMakeLists.txt)16
-rw-r--r--examples/interfaceframework/qface-addressbook/demo/demo.pro (renamed from examples/interfaceframework/qface-if-addressbook/demo/demo.pro)4
-rw-r--r--examples/interfaceframework/qface-addressbook/demo/main.cpp (renamed from examples/interfaceframework/qface-if-addressbook/demo/main.cpp)0
-rw-r--r--examples/interfaceframework/qface-addressbook/demo/main.qml (renamed from examples/interfaceframework/qface-if-addressbook/demo/main.qml)0
-rw-r--r--examples/interfaceframework/qface-addressbook/demo/qml.qrc (renamed from examples/interfaceframework/qface-if-addressbook/demo/qml.qrc)0
-rw-r--r--examples/interfaceframework/qface-addressbook/doc/images/qface-addressbook.pngbin0 -> 14331 bytes
-rw-r--r--examples/interfaceframework/qface-addressbook/doc/src/qface-addressbook.qdoc152
-rw-r--r--examples/interfaceframework/qface-addressbook/example-addressbook.qface (renamed from examples/interfaceframework/qface-if-addressbook/example-if-addressbook.qface)0
-rw-r--r--examples/interfaceframework/qface-addressbook/example-addressbook.yaml (renamed from examples/interfaceframework/qface-if-addressbook/example-if-addressbook.yaml)0
-rw-r--r--examples/interfaceframework/qface-addressbook/frontend/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-addressbook/frontend/CMakeLists.txt)4
-rw-r--r--examples/interfaceframework/qface-addressbook/frontend/frontend.pro (renamed from examples/interfaceframework/qface-if-addressbook/frontend/frontend.pro)4
-rw-r--r--examples/interfaceframework/qface-addressbook/qface-addressbook.pro (renamed from examples/interfaceframework/qface-if-addressbook/qface-if-addressbook.pro)4
-rw-r--r--examples/interfaceframework/qface-climate/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-climate/CMakeLists.txt)1
-rw-r--r--examples/interfaceframework/qface-climate/backend_simulator/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-climate/backend_simulator/CMakeLists.txt)4
-rw-r--r--examples/interfaceframework/qface-climate/backend_simulator/backend_simulator.pro (renamed from examples/interfaceframework/qface-if-climate/backend_simulator/backend_simulator.pro)4
-rw-r--r--examples/interfaceframework/qface-climate/demo/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-climate/demo/CMakeLists.txt)16
-rw-r--r--examples/interfaceframework/qface-climate/demo/demo.pro (renamed from examples/interfaceframework/qface-if-climate/demo/demo.pro)4
-rw-r--r--examples/interfaceframework/qface-climate/demo/main.cpp (renamed from examples/interfaceframework/qface-if-climate/demo/main.cpp)0
-rw-r--r--examples/interfaceframework/qface-climate/demo/main.qml (renamed from examples/interfaceframework/qface-if-climate/demo/main.qml)0
-rw-r--r--examples/interfaceframework/qface-climate/demo/qml.qrc (renamed from examples/interfaceframework/qface-if-climate/demo/qml.qrc)0
-rw-r--r--examples/interfaceframework/qface-climate/doc/images/qface-climate.pngbin0 -> 39319 bytes
-rw-r--r--examples/interfaceframework/qface-climate/doc/src/qface-climate.qdoc325
-rw-r--r--examples/interfaceframework/qface-climate/example-climate.qface (renamed from examples/interfaceframework/qface-if-climate/example-if-climate.qface)0
-rw-r--r--examples/interfaceframework/qface-climate/example-climate.yaml (renamed from examples/interfaceframework/qface-if-climate/example-if-climate.yaml)0
-rw-r--r--examples/interfaceframework/qface-climate/frontend/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-climate/frontend/CMakeLists.txt)4
-rw-r--r--examples/interfaceframework/qface-climate/frontend/frontend.pro (renamed from examples/interfaceframework/qface-if-climate/frontend/frontend.pro)4
-rw-r--r--examples/interfaceframework/qface-climate/qface-climate.pro (renamed from examples/interfaceframework/qface-if-climate/qface-if-climate.pro)4
-rw-r--r--examples/interfaceframework/qface-remote/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-remote/CMakeLists.txt)1
-rw-r--r--examples/interfaceframework/qface-remote/backend_qtro/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-remote/backend_qtro/CMakeLists.txt)4
-rw-r--r--examples/interfaceframework/qface-remote/backend_qtro/backend_qtro.pro (renamed from examples/interfaceframework/qface-if-remote/backend_qtro/backend_qtro.pro)4
-rw-r--r--examples/interfaceframework/qface-remote/demo/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-remote/demo/CMakeLists.txt)18
-rw-r--r--examples/interfaceframework/qface-remote/demo/demo.pro (renamed from examples/interfaceframework/qface-if-remote/demo/demo.pro)4
-rw-r--r--examples/interfaceframework/qface-remote/demo/main.cpp (renamed from examples/interfaceframework/qface-if-remote/demo/main.cpp)0
-rw-r--r--examples/interfaceframework/qface-remote/demo/main.qml (renamed from examples/interfaceframework/qface-if-remote/demo/main.qml)0
-rw-r--r--examples/interfaceframework/qface-remote/demo/qml.qrc (renamed from examples/interfaceframework/qface-if-remote/demo/qml.qrc)0
-rw-r--r--examples/interfaceframework/qface-remote/doc/images/qface-remote.pngbin0 -> 11337 bytes
-rw-r--r--examples/interfaceframework/qface-remote/doc/src/qface-remote.qdoc267
-rw-r--r--examples/interfaceframework/qface-remote/example-remote.qface (renamed from examples/interfaceframework/qface-if-remote/example-if-remote.qface)0
-rw-r--r--examples/interfaceframework/qface-remote/frontend/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-remote/frontend/CMakeLists.txt)4
-rw-r--r--examples/interfaceframework/qface-remote/frontend/frontend.pro (renamed from examples/interfaceframework/qface-if-remote/frontend/frontend.pro)4
-rw-r--r--examples/interfaceframework/qface-remote/qface-remote.pro (renamed from examples/interfaceframework/qface-if-remote/qface-if-remote.pro)2
-rw-r--r--examples/interfaceframework/qface-remote/server_qtro/CMakeLists.txt (renamed from examples/interfaceframework/qface-if-remote/server_qtro/CMakeLists.txt)20
-rw-r--r--examples/interfaceframework/qface-remote/server_qtro/main.cpp (renamed from examples/interfaceframework/qface-if-remote/server_qtro/main.cpp)0
-rw-r--r--examples/interfaceframework/qface-remote/server_qtro/processingservice.cpp (renamed from examples/interfaceframework/qface-if-remote/server_qtro/processingservice.cpp)0
-rw-r--r--examples/interfaceframework/qface-remote/server_qtro/processingservice.h (renamed from examples/interfaceframework/qface-if-remote/server_qtro/processingservice.h)0
-rw-r--r--examples/interfaceframework/qface-remote/server_qtro/server_qtro.pro (renamed from examples/interfaceframework/qface-if-remote/server_qtro/server_qtro.pro)6
-rw-r--r--examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-dbus.gifbin0 -> 343966 bytes
-rw-r--r--examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-final.gifbin0 -> 395076 bytes
-rw-r--r--examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-sync.gifbin0 -> 636529 bytes
-rw-r--r--examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-unsync.gifbin0 -> 625820 bytes
-rw-r--r--examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial.pngbin0 -> 163657 bytes
-rw-r--r--examples/interfaceframework/qface-tutorial/doc/src/qface-tutorial.qdoc893
86 files changed, 2070 insertions, 88 deletions
diff --git a/examples/ifmedia/mediaplayer/doc/images/mediaplayer.png b/examples/ifmedia/mediaplayer/doc/images/mediaplayer.png
new file mode 100644
index 00000000..94bb56a9
--- /dev/null
+++ b/examples/ifmedia/mediaplayer/doc/images/mediaplayer.png
Binary files differ
diff --git a/examples/ifmedia/mediaplayer/doc/src/mediaplayer.qdoc b/examples/ifmedia/mediaplayer/doc/src/mediaplayer.qdoc
new file mode 100644
index 00000000..81eefa29
--- /dev/null
+++ b/examples/ifmedia/mediaplayer/doc/src/mediaplayer.qdoc
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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 QtInterfaceFramework module 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$
+**
+****************************************************************************/
+
+/*!
+ \example ifmedia/mediaplayer
+ \title QML Media Player Example
+ \ingroup qtifmedia-examples
+
+ \brief The Example shows how to use the MediaPlayer API from QML.
+ \image mediaplayer.png
+*/
diff --git a/examples/ifmedia/tuner/doc/images/tuner.png b/examples/ifmedia/tuner/doc/images/tuner.png
new file mode 100644
index 00000000..3caf925e
--- /dev/null
+++ b/examples/ifmedia/tuner/doc/images/tuner.png
Binary files differ
diff --git a/examples/ifmedia/tuner/doc/src/tuner.qdoc b/examples/ifmedia/tuner/doc/src/tuner.qdoc
new file mode 100644
index 00000000..809e26a2
--- /dev/null
+++ b/examples/ifmedia/tuner/doc/src/tuner.qdoc
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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 QtInterfaceFramework module 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$
+**
+****************************************************************************/
+
+/*!
+ \example ifmedia/tuner
+ \title QML Tuner Example
+ \ingroup qtifmedia-examples
+
+ \brief This Example shows how to use the Tuner API from QML.
+ \image tuner.png
+
+ This Example shows how to use the Tuner API from QML.
+
+ First an AmFmTuner object is created. By default,
+ the auto discovery is used to search for a plugin that implements QIfAmFmTunerBackendInterface.
+ Depending on the selection of the band radio buttons the tuner band is selected.
+ \snippet ifmedia/tuner/main.qml 1
+
+ \section1 Station Information
+
+ In the left third of the UI we want to display information about the current radio station
+ as well as providing some buttons to change the stations or start a scan through all stations.
+ \snippet ifmedia/tuner/main.qml 2
+
+ The station property of AmFmTuner exposes the station you are currently listening to, which can
+ be empty as well, if the frequency property was manually changed to a frequency no station is
+ broadcasting on.
+
+ \section1 Station List
+
+ The middle part of the UI shows a list of all the available radio stations. Every item of the
+ list shows the name and the frequency of a station. By clicking on one of the list items,
+ the current station will be changed to this station. On the right side of every station is a
+ \c + button which can be used to save this station into the preset list.
+ \snippet ifmedia/tuner/main.qml 3
+
+ To fill the ListView with all available stations, the FilterAndBrowseModel model is used. As
+ the FilterAndBrowseModel is a generic model, it needs to know where the data should come from.
+ This is done by passing the service object of the AmFmTuner to the model. The model will then
+ use the QIfFilterAndBrowseModelInterface exposed by the same backend which is used by AmFmTuner.
+ Because the tuner backend could expose multiple different lists, the contentType needs to be
+ selected: in this case the contentType is set to \c station, which provides all available stations.
+ \snippet ifmedia/tuner/main.qml 4
+
+ To change the currently playing station the AmFmTuner::tune method is used by calling it
+ in an onClicked handler
+ \snippet ifmedia/tuner/main.qml 5
+
+ \section1 Preset List
+
+ The preset list occupies the right third of the UI and shows all favorite stations. This list
+ is sorted and maintained by the user. A press on the \c + button of the station list will
+ add a station to this list, the \c X button will remove the item and the arrow buttons can be
+ used to change the order of the stations.
+ \snippet ifmedia/tuner/main.qml 7
+
+ Similar to the station list, the FilterAndBrowseModel is used as a model, but the contentType
+ was changed to \c presets.
+ For maintaining the list, the move and remove functions of FilterAndBrowseModel are used.
+
+
+ \section1 Favorite Button
+
+ The \c + button of the station list should be enabled if the station is not already part of
+ the preset list. This is done by using the FilterAndBrowseModel::indexOf function which will
+ search for the passed item and call the callback function passed as second argument with the
+ result. Depending on whether the index is valid, the button will be enabled or disabled.
+ This asynchronous approach is needed, as the preset list might be pretty big and the data might
+ come from a different process which maintains the tuner state.
+ \snippet ifmedia/tuner/main.qml 6
+
+ If not already part of the preset list, the station is added to the list by using the
+ FilterAndBrowseModel::insert method, which is passed \c 0 as the first parameter to add it on
+ top of the list.
+*/
diff --git a/examples/ifvehiclefunctions/CMakeLists.txt b/examples/ifvehiclefunctions/CMakeLists.txt
index 617352cb..00a8e2e5 100644
--- a/examples/ifvehiclefunctions/CMakeLists.txt
+++ b/examples/ifvehiclefunctions/CMakeLists.txt
@@ -1,7 +1,7 @@
# Generated from ifvehiclefunctions.pro.
-add_subdirectory(climate_qml)
-add_subdirectory(window_qml)
+add_subdirectory(climate-qml)
+add_subdirectory(window-qml)
if(TARGET Qt::Widgets)
- add_subdirectory(climate_widget)
+ add_subdirectory(climate-widget)
endif()
diff --git a/examples/ifvehiclefunctions/climate_qml/CMakeLists.txt b/examples/ifvehiclefunctions/climate-qml/CMakeLists.txt
index 4bef4f24..4bef4f24 100644
--- a/examples/ifvehiclefunctions/climate_qml/CMakeLists.txt
+++ b/examples/ifvehiclefunctions/climate-qml/CMakeLists.txt
diff --git a/examples/ifvehiclefunctions/climate_qml/climate_qml.pro b/examples/ifvehiclefunctions/climate-qml/climate-qml.pro
index 8b11c109..8b11c109 100644
--- a/examples/ifvehiclefunctions/climate_qml/climate_qml.pro
+++ b/examples/ifvehiclefunctions/climate-qml/climate-qml.pro
diff --git a/examples/ifvehiclefunctions/climate-qml/doc/images/climate-qml.png b/examples/ifvehiclefunctions/climate-qml/doc/images/climate-qml.png
new file mode 100644
index 00000000..c123ff3c
--- /dev/null
+++ b/examples/ifvehiclefunctions/climate-qml/doc/images/climate-qml.png
Binary files differ
diff --git a/examples/ifvehiclefunctions/climate-qml/doc/src/climate-qml.qdoc b/examples/ifvehiclefunctions/climate-qml/doc/src/climate-qml.qdoc
new file mode 100644
index 00000000..3fbd2711
--- /dev/null
+++ b/examples/ifvehiclefunctions/climate-qml/doc/src/climate-qml.qdoc
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 QtInterfaceFramework module 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$
+**
+****************************************************************************/
+
+/*!
+ \example ifvehiclefunctions/climate-qml
+ \title Climate Control QML Example
+ \ingroup qtifvehiclefunctions-examples
+
+ \brief The Example shows how to access the climate control from QML.
+ \image climate-qml.png
+
+ The example shows how to access the climate control from QML.
+
+ In the example, ClimateControl is created and autoDiscovery enabled.
+ When autoDiscovery is enabled, the module starts searching for the presence
+ of a plugin that implements QIfClimateControlBackendInterface.
+ \snippet ifvehiclefunctions/climate-qml/main.qml 1
+
+ \note To simplify the deployment process, this example loads a simulation backend.
+
+ If discovery fails, a message dialog is shown:
+ \snippet ifvehiclefunctions/climate-qml/main.qml 4
+
+ As a Climate System can support multiple climate zones, we need to
+ differentiate between the zones. A \e {general zone} can be used for settings
+ that are applied to all zones.
+
+ General ClimateControl attribute values are handled in check boxes as follows:
+ \snippet ifvehiclefunctions/climate-qml/main.qml 2
+
+ For the zoned ClimateControl, the \l [QML] {AbstractZonedFeature::}{zoneAt}
+ property is used for controlling the values from the front left climate zone:
+ \snippet ifvehiclefunctions/climate-qml/main.qml 3
+*/
diff --git a/examples/ifvehiclefunctions/climate_qml/main.cpp b/examples/ifvehiclefunctions/climate-qml/main.cpp
index 0022cd0e..0022cd0e 100644
--- a/examples/ifvehiclefunctions/climate_qml/main.cpp
+++ b/examples/ifvehiclefunctions/climate-qml/main.cpp
diff --git a/examples/ifvehiclefunctions/climate_qml/main.qml b/examples/ifvehiclefunctions/climate-qml/main.qml
index 009794b9..009794b9 100644
--- a/examples/ifvehiclefunctions/climate_qml/main.qml
+++ b/examples/ifvehiclefunctions/climate-qml/main.qml
diff --git a/examples/ifvehiclefunctions/climate_qml/qml.qrc b/examples/ifvehiclefunctions/climate-qml/qml.qrc
index 5f6483ac..5f6483ac 100644
--- a/examples/ifvehiclefunctions/climate_qml/qml.qrc
+++ b/examples/ifvehiclefunctions/climate-qml/qml.qrc
diff --git a/examples/ifvehiclefunctions/climate_widget/CMakeLists.txt b/examples/ifvehiclefunctions/climate-widget/CMakeLists.txt
index fbbac0c6..fbbac0c6 100644
--- a/examples/ifvehiclefunctions/climate_widget/CMakeLists.txt
+++ b/examples/ifvehiclefunctions/climate-widget/CMakeLists.txt
diff --git a/examples/ifvehiclefunctions/climate_widget/climate_widget.pro b/examples/ifvehiclefunctions/climate-widget/climate-widget.pro
index d897dce0..d897dce0 100644
--- a/examples/ifvehiclefunctions/climate_widget/climate_widget.pro
+++ b/examples/ifvehiclefunctions/climate-widget/climate-widget.pro
diff --git a/examples/ifvehiclefunctions/climate-widget/doc/images/climate-widget.png b/examples/ifvehiclefunctions/climate-widget/doc/images/climate-widget.png
new file mode 100644
index 00000000..a0dec9a5
--- /dev/null
+++ b/examples/ifvehiclefunctions/climate-widget/doc/images/climate-widget.png
Binary files differ
diff --git a/examples/ifvehiclefunctions/climate-widget/doc/src/climate-widget.qdoc b/examples/ifvehiclefunctions/climate-widget/doc/src/climate-widget.qdoc
new file mode 100644
index 00000000..aa6329a1
--- /dev/null
+++ b/examples/ifvehiclefunctions/climate-widget/doc/src/climate-widget.qdoc
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QtInterfaceFramework module 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$
+**
+****************************************************************************/
+
+/*!
+ \example ifvehiclefunctions/climate-widget
+ \title Climate Control Widget Example
+ \ingroup qtifvehiclefunctions-examples
+
+ \brief This example shows how to access the climate control from C++.
+ \image climate-widget.png
+
+ This example shows how to access the climate control from the C++.
+
+ The first thing to do is to create a QIfClimateControl instance in our
+ MainWindow constructor. As we only have one Climate backend and don't want
+ to choose which one to use, we call \l {QIfAbstractFeature::}{startAutoDiscovery}
+ to start searching for a suitable backend right away and pick the first one
+ that matches.
+
+ \note To simplify the deployment process, this example loads a simulation backend.
+
+ \l {QIfClimateControl::}{isValid()} is used for verifying that the
+ autoDiscovery found a backend:
+ \snippet ifvehiclefunctions/climate-widget/mainwindow.cpp 1
+
+ The constructor then continues to connect the climate control
+ attribute change signals to the UI components:
+ \snippet ifvehiclefunctions/climate-widget/mainwindow.cpp 2
+
+ Airflow direction is controlled using these functions:
+ \snippet ifvehiclefunctions/climate-widget/mainwindow.cpp 3
+*/
diff --git a/examples/ifvehiclefunctions/climate_widget/main.cpp b/examples/ifvehiclefunctions/climate-widget/main.cpp
index 9757cc27..9757cc27 100644
--- a/examples/ifvehiclefunctions/climate_widget/main.cpp
+++ b/examples/ifvehiclefunctions/climate-widget/main.cpp
diff --git a/examples/ifvehiclefunctions/climate_widget/mainwindow.cpp b/examples/ifvehiclefunctions/climate-widget/mainwindow.cpp
index 8f06010a..8f06010a 100644
--- a/examples/ifvehiclefunctions/climate_widget/mainwindow.cpp
+++ b/examples/ifvehiclefunctions/climate-widget/mainwindow.cpp
diff --git a/examples/ifvehiclefunctions/climate_widget/mainwindow.h b/examples/ifvehiclefunctions/climate-widget/mainwindow.h
index 1a43adda..1a43adda 100644
--- a/examples/ifvehiclefunctions/climate_widget/mainwindow.h
+++ b/examples/ifvehiclefunctions/climate-widget/mainwindow.h
diff --git a/examples/ifvehiclefunctions/climate_widget/mainwindow.ui b/examples/ifvehiclefunctions/climate-widget/mainwindow.ui
index 7f53ae27..7f53ae27 100644
--- a/examples/ifvehiclefunctions/climate_widget/mainwindow.ui
+++ b/examples/ifvehiclefunctions/climate-widget/mainwindow.ui
diff --git a/examples/ifvehiclefunctions/ifvehiclefunctions.pro b/examples/ifvehiclefunctions/ifvehiclefunctions.pro
index 19ff424d..d290d4a7 100644
--- a/examples/ifvehiclefunctions/ifvehiclefunctions.pro
+++ b/examples/ifvehiclefunctions/ifvehiclefunctions.pro
@@ -1,7 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
- climate_qml \
- window_qml
+ climate-qml \
+ window-qml
-qtHaveModule(widgets): SUBDIRS += climate_widget
+qtHaveModule(widgets): SUBDIRS += climate-widget
diff --git a/examples/ifvehiclefunctions/window_qml/CMakeLists.txt b/examples/ifvehiclefunctions/window-qml/CMakeLists.txt
index 41f89141..41f89141 100644
--- a/examples/ifvehiclefunctions/window_qml/CMakeLists.txt
+++ b/examples/ifvehiclefunctions/window-qml/CMakeLists.txt
diff --git a/examples/ifvehiclefunctions/window_qml/WindowItem.qml b/examples/ifvehiclefunctions/window-qml/WindowItem.qml
index 55086efd..55086efd 100644
--- a/examples/ifvehiclefunctions/window_qml/WindowItem.qml
+++ b/examples/ifvehiclefunctions/window-qml/WindowItem.qml
diff --git a/examples/ifvehiclefunctions/window_qml/main.cpp b/examples/ifvehiclefunctions/window-qml/main.cpp
index 0022cd0e..0022cd0e 100644
--- a/examples/ifvehiclefunctions/window_qml/main.cpp
+++ b/examples/ifvehiclefunctions/window-qml/main.cpp
diff --git a/examples/ifvehiclefunctions/window_qml/main.qml b/examples/ifvehiclefunctions/window-qml/main.qml
index b0b234e0..b0b234e0 100644
--- a/examples/ifvehiclefunctions/window_qml/main.qml
+++ b/examples/ifvehiclefunctions/window-qml/main.qml
diff --git a/examples/ifvehiclefunctions/window_qml/qml.qrc b/examples/ifvehiclefunctions/window-qml/qml.qrc
index 4bb0efb9..4bb0efb9 100644
--- a/examples/ifvehiclefunctions/window_qml/qml.qrc
+++ b/examples/ifvehiclefunctions/window-qml/qml.qrc
diff --git a/examples/ifvehiclefunctions/window_qml/window_qml.pro b/examples/ifvehiclefunctions/window-qml/window-qml.pro
index b3f291c9..b3f291c9 100644
--- a/examples/ifvehiclefunctions/window_qml/window_qml.pro
+++ b/examples/ifvehiclefunctions/window-qml/window-qml.pro
diff --git a/examples/interfaceframework/CMakeLists.txt b/examples/interfaceframework/CMakeLists.txt
index 0a80629e..65744ca8 100644
--- a/examples/interfaceframework/CMakeLists.txt
+++ b/examples/interfaceframework/CMakeLists.txt
@@ -4,10 +4,10 @@ cmake_minimum_required(VERSION 3.14)
project(example LANGUAGES CXX)
if(QT_FEATURE_ifcodegen)
- add_subdirectory(qface-if-climate)
- add_subdirectory(qface-if-addressbook)
+ add_subdirectory(qface-climate)
+ add_subdirectory(qface-addressbook)
endif()
if(QT_FEATURE_ifcodegen AND QT_FEATURE_remoteobjects)
- add_subdirectory(qface-if-remote)
+ add_subdirectory(qface-remote)
add_subdirectory(qface-tutorial)
endif()
diff --git a/examples/interfaceframework/interfaceframework.pro b/examples/interfaceframework/interfaceframework.pro
index 9c1e40c8..06233a70 100644
--- a/examples/interfaceframework/interfaceframework.pro
+++ b/examples/interfaceframework/interfaceframework.pro
@@ -2,9 +2,9 @@ TEMPLATE = subdirs
QT_FOR_CONFIG += interfaceframework
qtConfig(ifcodegen) {
- SUBDIRS += qface-if-climate \
- qface-if-addressbook
+ SUBDIRS += qface-climate \
+ qface-addressbook
}
-qtConfig(ifcodegen): qtConfig(remoteobjects): SUBDIRS += qface-if-remote
+qtConfig(ifcodegen): qtConfig(remoteobjects): SUBDIRS += qface-remote
qtConfig(ifcodegen): qtConfig(remoteobjects): SUBDIRS += qface-tutorial
diff --git a/examples/interfaceframework/qface-if-addressbook/CMakeLists.txt b/examples/interfaceframework/qface-addressbook/CMakeLists.txt
index b3394426..4f9f70ef 100644
--- a/examples/interfaceframework/qface-if-addressbook/CMakeLists.txt
+++ b/examples/interfaceframework/qface-addressbook/CMakeLists.txt
@@ -1,4 +1,3 @@
-# Generated from qface-if-addressbook.pro.
cmake_minimum_required(VERSION 3.14)
project(example_if_addressbook LANGUAGES CXX)
diff --git a/examples/interfaceframework/qface-if-addressbook/backend_simulator/CMakeLists.txt b/examples/interfaceframework/qface-addressbook/backend_simulator/CMakeLists.txt
index 27737ebc..a9089b5c 100644
--- a/examples/interfaceframework/qface-if-addressbook/backend_simulator/CMakeLists.txt
+++ b/examples/interfaceframework/qface-addressbook/backend_simulator/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-addressbook/interfaceframework/")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-addressbook/interfaceframework/")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -20,7 +20,7 @@ set_target_properties(addressbook_backend_simulator PROPERTIES LIBRARY_OUTPUT_DI
# Interface Framework Generator:
qt6_ifcodegen_extend_target(addressbook_backend_simulator
- IDL_FILES ../example-if-addressbook.qface
+ IDL_FILES ../example-addressbook.qface
TEMPLATE backend_simulator
)
diff --git a/examples/interfaceframework/qface-if-addressbook/backend_simulator/backend_simulator.pro b/examples/interfaceframework/qface-addressbook/backend_simulator/backend_simulator.pro
index 4dc8239b..72871754 100644
--- a/examples/interfaceframework/qface-if-addressbook/backend_simulator/backend_simulator.pro
+++ b/examples/interfaceframework/qface-addressbook/backend_simulator/backend_simulator.pro
@@ -12,12 +12,12 @@ QT += core interfaceframework
CONFIG += ifcodegen plugin
IFCODEGEN_TEMPLATE = backend_simulator
-IFCODEGEN_SOURCES = ../example-if-addressbook.qface
+IFCODEGEN_SOURCES = ../example-addressbook.qface
PLUGIN_TYPE = interfaceframework
PLUGIN_CLASS_NAME = AddressBookSimulatorPlugin
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-addressbook/interfaceframework/
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-addressbook/interfaceframework/
INSTALLS += target
#! [0]
diff --git a/examples/interfaceframework/qface-if-addressbook/backend_simulator/plugin_resource.qrc b/examples/interfaceframework/qface-addressbook/backend_simulator/plugin_resource.qrc
index 7b89debe..7b89debe 100644
--- a/examples/interfaceframework/qface-if-addressbook/backend_simulator/plugin_resource.qrc
+++ b/examples/interfaceframework/qface-addressbook/backend_simulator/plugin_resource.qrc
diff --git a/examples/interfaceframework/qface-if-addressbook/backend_simulator/simulation.qml b/examples/interfaceframework/qface-addressbook/backend_simulator/simulation.qml
index 4f564843..4f564843 100644
--- a/examples/interfaceframework/qface-if-addressbook/backend_simulator/simulation.qml
+++ b/examples/interfaceframework/qface-addressbook/backend_simulator/simulation.qml
diff --git a/examples/interfaceframework/qface-if-addressbook/demo/CMakeLists.txt b/examples/interfaceframework/qface-addressbook/demo/CMakeLists.txt
index 7871e4a6..477c867a 100644
--- a/examples/interfaceframework/qface-if-addressbook/demo/CMakeLists.txt
+++ b/examples/interfaceframework/qface-addressbook/demo/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-addressbook")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-addressbook")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -17,20 +17,20 @@ find_package(Qt6 COMPONENTS Qml)
find_package(Qt6 COMPONENTS Quick)
find_package(Qt6 COMPONENTS InterfaceFramework)
-qt_add_executable(qface-if-addressbook
+qt_add_executable(qface-addressbook
main.cpp
)
-set_target_properties(qface-if-addressbook PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../)
-set_target_properties(qface-if-addressbook PROPERTIES
+set_target_properties(qface-addressbook PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../)
+set_target_properties(qface-addressbook PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE FALSE
)
-target_compile_definitions(qface-if-addressbook PUBLIC
+target_compile_definitions(qface-addressbook PUBLIC
QT_DEPRECATED_WARNINGS
)
-target_link_libraries(qface-if-addressbook PUBLIC
+target_link_libraries(qface-addressbook PUBLIC
QtIfAdressBookExample
Qt::Core
Qt::Gui
@@ -44,14 +44,14 @@ set(qml_resource_files
"main.qml"
)
-qt6_add_resources(qface-if-addressbook "qml"
+qt6_add_resources(qface-addressbook "qml"
PREFIX
"/"
FILES
${qml_resource_files}
)
-install(TARGETS qface-if-addressbook
+install(TARGETS qface-addressbook
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/interfaceframework/qface-if-addressbook/demo/demo.pro b/examples/interfaceframework/qface-addressbook/demo/demo.pro
index 9ec597fe..2bba3196 100644
--- a/examples/interfaceframework/qface-if-addressbook/demo/demo.pro
+++ b/examples/interfaceframework/qface-addressbook/demo/demo.pro
@@ -1,4 +1,4 @@
-TARGET = qface-if-addressbook
+TARGET = qface-addressbook
QMAKE_PROJECT_NAME = $$TARGET
TEMPLATE = app
@@ -34,5 +34,5 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-addressbook
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-addressbook
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-addressbook/demo/main.cpp b/examples/interfaceframework/qface-addressbook/demo/main.cpp
index c0bc5fe3..c0bc5fe3 100644
--- a/examples/interfaceframework/qface-if-addressbook/demo/main.cpp
+++ b/examples/interfaceframework/qface-addressbook/demo/main.cpp
diff --git a/examples/interfaceframework/qface-if-addressbook/demo/main.qml b/examples/interfaceframework/qface-addressbook/demo/main.qml
index f1c6e068..f1c6e068 100644
--- a/examples/interfaceframework/qface-if-addressbook/demo/main.qml
+++ b/examples/interfaceframework/qface-addressbook/demo/main.qml
diff --git a/examples/interfaceframework/qface-if-addressbook/demo/qml.qrc b/examples/interfaceframework/qface-addressbook/demo/qml.qrc
index 5f6483ac..5f6483ac 100644
--- a/examples/interfaceframework/qface-if-addressbook/demo/qml.qrc
+++ b/examples/interfaceframework/qface-addressbook/demo/qml.qrc
diff --git a/examples/interfaceframework/qface-addressbook/doc/images/qface-addressbook.png b/examples/interfaceframework/qface-addressbook/doc/images/qface-addressbook.png
new file mode 100644
index 00000000..7e170f88
--- /dev/null
+++ b/examples/interfaceframework/qface-addressbook/doc/images/qface-addressbook.png
Binary files differ
diff --git a/examples/interfaceframework/qface-addressbook/doc/src/qface-addressbook.qdoc b/examples/interfaceframework/qface-addressbook/doc/src/qface-addressbook.qdoc
new file mode 100644
index 00000000..b6958c35
--- /dev/null
+++ b/examples/interfaceframework/qface-addressbook/doc/src/qface-addressbook.qdoc
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** 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-addressbook
+\brief This example shows how to generate models using the Qt Interface Framework Generator.
+\ingroup qtinterfaceframework-examples
+\title Qt Interface Framework Generator Addressbook Example
+\image qface-addressbook.png
+
+\section1 Introduction
+
+This example shows how to generate a model using the \e model type in a qface file with the Qt Interface Framework
+Generator.
+
+It will only explain the details on how to use the \e model type and how it works internally. For a
+general introduction to the Qt Interface Framework Generator, please have a look at the
+\l {interfaceframework/qface-climate} {Qt Interface Framework Generator Climate Example}.
+
+\section2 Walkthrough
+
+The IDL file used in the example represents an addressbook API. It contains a single interface
+providing the contacts as a model and a struct definition for the actual contact.
+
+\snippet interfaceframework/qface-addressbook/example-addressbook.qface 0
+
+The \e contact property is defined to be of type \e model<Contact>. The \l frontend template will
+create a C++ property of type \l {QIfPagingModel}{QIfPagingModel*}. The getter function of this
+property returns a valid instance once a backend is connected and the properties are initialized.
+This QIfPagingModel instance can be used from C++, as well as from QML and already provides the
+basic functionality for retrieving its data in an optimized fashion using the so called \e
+Pagination concept.
+
+For the backend interface the property type is different and will be a \l QIfPagingModelInterface
+pointer. This is needed as the QIfPagingModel is also a QtInterfaceFramework feature and, like all features, it
+uses a backend interface for the frontend-backend separation. For more information, see
+\l{Concepts and Architecture}.
+
+The backend plugin needs to implement the \l QIfPagingModelInterface class for every exposed
+property.
+The \l backend_simulator template already takes care of this and generates all the needed code.
+
+\section1 Configuring the Simulation Backend Plugin
+
+By default the generated simulation backend does not populate any data for the model, as the
+template doesn't know what content it should provide.
+
+For this use-case the \l {config_simulator_default}{default} annotation can be used to configure
+the simulator to provide static simulation data.
+
+This is done in the example-addressbook.yaml file:
+
+\quotefile interfaceframework/qface-addressbook/example-addressbook.yaml
+
+The JSON fragment assigned to the \l {config_simulator_default}{default} variable is parsed by the
+Qt Interface Framework Generator and will be used to generate a simulation backend which creates two Contact
+instances and returns them as content for the contacts model.
+
+\section1 Demo Application
+
+The demo application is not autogenerated, but a standard QQmlEngine setup for an application
+similar to other examples.
+
+\snippet interfaceframework/qface-addressbook/demo/main.qml 0
+
+The model is retrieved from the \e addressbook object using the \e contacts property and passed to
+the ListView. The delegate can access the actual contact using the \l {QIfPagingModel::}{ItemRole}
+of the QIfPagingModel, which is exposed to QML through \e model.item.
+
+\section1 Extended Simulation Behavior
+
+Because the \l backend_simulator template can only generated a stub, it doesn't know what behavior
+it should implement for the insertContact function of the qface file. The ifcodegen will simply
+generate a stub implementation printing a message that this function is not implemented.
+
+This limitation is fixed by using the \l {config_simulator_simulationFile}{simulationFile}
+annotation to tell the autogenerator we want to provide our own simulation QML file.
+
+In the example the \e simulationFile annotation points to a QML file in a resource file. The
+resource file is added to the build system like this.
+
+\e CMake:
+
+\snippet interfaceframework/qface-addressbook/backend_simulator/CMakeLists.txt 0
+
+\e qmake:
+
+\snippet interfaceframework/qface-addressbook/backend_simulator/backend_simulator.pro 0
+
+\section2 Providing the simulation behavior in QML
+
+The autogenerated simulation backend code loads the simulation behavior from a QML file using a
+QIfSimulationEngine. This special engine makes sure the autogenerated backend interfaces are
+provided to the QML file and they can be extended from there. It also makes sure that the
+interfaces are available only to this engine instance and to no other engine running in the same
+process (e.g. in the frontend). See the QIfSimulationEngine documentation for more information
+about how the engine works.
+
+Using the ifcodegen for the simulation backend, the simulation interfaces are provided in the \e
+example.if.addressbook.simulation uri. The provided types are named after the backend interfaces
+implemented by the simulation backend. For our example two types are registered:
+
+\list
+ \li AddressBookBackend
+ \li ContactsModelBackend
+\endlist
+
+Our simulation QML file looks like this:
+
+\snippet interfaceframework/qface-addressbook/backend_simulator/simulation.qml 0
+
+It creates an AddressBookBackend instance and prints a message once the QML code is loaded by using
+the Component.onCompleted handler.
+
+To implement the behavior for the insertContact function, a JS function is added to the
+AddressBookBackend object in QML. This function takes three arguments, the first one is an
+PendingReply object used to notify the frontend once the request was successful or failed. The
+other arguments are as defined in the IDL file.
+
+To insert the provided contact to our list we use the \e contacts property which hold the
+implementation of the QIfPagingModelInterface for the contacts property. This implementation
+provides some extra convenience functions which can be used by the simulation to modify the model
+in an easy way. In our case we just call the \c insert() function and let the autogenerated
+implementation do the rest.
+
+*/
diff --git a/examples/interfaceframework/qface-if-addressbook/example-if-addressbook.qface b/examples/interfaceframework/qface-addressbook/example-addressbook.qface
index 12eca1ab..12eca1ab 100644
--- a/examples/interfaceframework/qface-if-addressbook/example-if-addressbook.qface
+++ b/examples/interfaceframework/qface-addressbook/example-addressbook.qface
diff --git a/examples/interfaceframework/qface-if-addressbook/example-if-addressbook.yaml b/examples/interfaceframework/qface-addressbook/example-addressbook.yaml
index 2e7a3c1c..2e7a3c1c 100644
--- a/examples/interfaceframework/qface-if-addressbook/example-if-addressbook.yaml
+++ b/examples/interfaceframework/qface-addressbook/example-addressbook.yaml
diff --git a/examples/interfaceframework/qface-if-addressbook/frontend/CMakeLists.txt b/examples/interfaceframework/qface-addressbook/frontend/CMakeLists.txt
index 5f293acc..59c5bb18 100644
--- a/examples/interfaceframework/qface-if-addressbook/frontend/CMakeLists.txt
+++ b/examples/interfaceframework/qface-addressbook/frontend/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-ifaddressbook")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-addressbook")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS InterfaceFramework)
@@ -20,7 +20,7 @@ qt6_add_library(QtIfAdressBookExample)
# Interface Framework Generator:
qt6_ifcodegen_extend_target(QtIfAdressBookExample
- IDL_FILES ../example-if-addressbook.qface
+ IDL_FILES ../example-addressbook.qface
TEMPLATE frontend
)
diff --git a/examples/interfaceframework/qface-if-addressbook/frontend/frontend.pro b/examples/interfaceframework/qface-addressbook/frontend/frontend.pro
index 93fc30ae..7bfe6a7c 100644
--- a/examples/interfaceframework/qface-if-addressbook/frontend/frontend.pro
+++ b/examples/interfaceframework/qface-addressbook/frontend/frontend.pro
@@ -7,7 +7,7 @@ QT_FOR_CONFIG += interfaceframework
QT += interfaceframework qml quick
CONFIG += ifcodegen
-IFCODEGEN_SOURCES = ../example-if-addressbook.qface
+IFCODEGEN_SOURCES = ../example-addressbook.qface
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-ifaddressbook
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-addressbook
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-addressbook/qface-if-addressbook.pro b/examples/interfaceframework/qface-addressbook/qface-addressbook.pro
index 48c88ba8..48028cc6 100644
--- a/examples/interfaceframework/qface-if-addressbook/qface-if-addressbook.pro
+++ b/examples/interfaceframework/qface-addressbook/qface-addressbook.pro
@@ -9,5 +9,5 @@ CONFIG += ordered
OTHER_FILES +=
DISTFILES += \
- example-if-addressbook.qface \
- example-if-addressbook.yaml
+ example-addressbook.qface \
+ example-addressbook.yaml
diff --git a/examples/interfaceframework/qface-if-climate/CMakeLists.txt b/examples/interfaceframework/qface-climate/CMakeLists.txt
index 72827137..45fa4804 100644
--- a/examples/interfaceframework/qface-if-climate/CMakeLists.txt
+++ b/examples/interfaceframework/qface-climate/CMakeLists.txt
@@ -1,4 +1,3 @@
-# Generated from qface-if-climate.pro.
cmake_minimum_required(VERSION 3.14)
project(example_if_climate LANGUAGES CXX)
diff --git a/examples/interfaceframework/qface-if-climate/backend_simulator/CMakeLists.txt b/examples/interfaceframework/qface-climate/backend_simulator/CMakeLists.txt
index eacf45a3..5f61f67b 100644
--- a/examples/interfaceframework/qface-if-climate/backend_simulator/CMakeLists.txt
+++ b/examples/interfaceframework/qface-climate/backend_simulator/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-climate/interfaceframework/")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-climate/interfaceframework/")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -25,7 +25,7 @@ set_target_properties(climate_backend_simulator PROPERTIES LIBRARY_OUTPUT_DIRECT
#! [2]
# Interface Framework Generator:
qt6_ifcodegen_extend_target(climate_backend_simulator
- IDL_FILES ../example-if-climate.qface
+ IDL_FILES ../example-climate.qface
TEMPLATE backend_simulator
)
#! [2]
diff --git a/examples/interfaceframework/qface-if-climate/backend_simulator/backend_simulator.pro b/examples/interfaceframework/qface-climate/backend_simulator/backend_simulator.pro
index 8f92435e..84413d82 100644
--- a/examples/interfaceframework/qface-if-climate/backend_simulator/backend_simulator.pro
+++ b/examples/interfaceframework/qface-climate/backend_simulator/backend_simulator.pro
@@ -16,10 +16,10 @@ QT += core interfaceframework
#! [2]
CONFIG += ifcodegen plugin
IFCODEGEN_TEMPLATE = backend_simulator
-IFCODEGEN_SOURCES = ../example-if-climate.qface
+IFCODEGEN_SOURCES = ../example-climate.qface
PLUGIN_TYPE = interfaceframework
PLUGIN_CLASS_NAME = ClimateSimulatorPlugin
#! [2]
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-climate/interfaceframework/
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-climate/interfaceframework/
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-climate/demo/CMakeLists.txt b/examples/interfaceframework/qface-climate/demo/CMakeLists.txt
index 1b0ceb50..9806b26a 100644
--- a/examples/interfaceframework/qface-if-climate/demo/CMakeLists.txt
+++ b/examples/interfaceframework/qface-climate/demo/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-climate")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-climate")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -17,20 +17,20 @@ find_package(Qt6 COMPONENTS Qml)
find_package(Qt6 COMPONENTS Quick)
find_package(Qt6 COMPONENTS InterfaceFramework)
-qt_add_executable(qface-if-climate
+qt_add_executable(qface-climate
main.cpp
)
-set_target_properties(qface-if-climate PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
-set_target_properties(qface-if-climate PROPERTIES
+set_target_properties(qface-climate PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
+set_target_properties(qface-climate PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE FALSE
)
-target_compile_definitions(qface-if-climate PUBLIC
+target_compile_definitions(qface-climate PUBLIC
QT_DEPRECATED_WARNINGS
)
-target_link_libraries(qface-if-climate PUBLIC
+target_link_libraries(qface-climate PUBLIC
QtIfClimateExample
Qt::Core
Qt::Gui
@@ -44,14 +44,14 @@ set(qml_resource_files
"main.qml"
)
-qt6_add_resources(qface-if-climate "qml"
+qt6_add_resources(qface-climate "qml"
PREFIX
"/"
FILES
${qml_resource_files}
)
-install(TARGETS qface-if-climate
+install(TARGETS qface-climate
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/interfaceframework/qface-if-climate/demo/demo.pro b/examples/interfaceframework/qface-climate/demo/demo.pro
index 52790c3e..7a26ef25 100644
--- a/examples/interfaceframework/qface-if-climate/demo/demo.pro
+++ b/examples/interfaceframework/qface-climate/demo/demo.pro
@@ -1,4 +1,4 @@
-TARGET = qface-if-climate
+TARGET = qface-climate
QMAKE_PROJECT_NAME = $$TARGET
TEMPLATE = app
@@ -34,5 +34,5 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-climate
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-climate
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-climate/demo/main.cpp b/examples/interfaceframework/qface-climate/demo/main.cpp
index 3fc0f846..3fc0f846 100644
--- a/examples/interfaceframework/qface-if-climate/demo/main.cpp
+++ b/examples/interfaceframework/qface-climate/demo/main.cpp
diff --git a/examples/interfaceframework/qface-if-climate/demo/main.qml b/examples/interfaceframework/qface-climate/demo/main.qml
index f6723db6..f6723db6 100644
--- a/examples/interfaceframework/qface-if-climate/demo/main.qml
+++ b/examples/interfaceframework/qface-climate/demo/main.qml
diff --git a/examples/interfaceframework/qface-if-climate/demo/qml.qrc b/examples/interfaceframework/qface-climate/demo/qml.qrc
index 5f6483ac..5f6483ac 100644
--- a/examples/interfaceframework/qface-if-climate/demo/qml.qrc
+++ b/examples/interfaceframework/qface-climate/demo/qml.qrc
diff --git a/examples/interfaceframework/qface-climate/doc/images/qface-climate.png b/examples/interfaceframework/qface-climate/doc/images/qface-climate.png
new file mode 100644
index 00000000..7c4f943c
--- /dev/null
+++ b/examples/interfaceframework/qface-climate/doc/images/qface-climate.png
Binary files differ
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
+
+*/
diff --git a/examples/interfaceframework/qface-if-climate/example-if-climate.qface b/examples/interfaceframework/qface-climate/example-climate.qface
index 49187e3b..49187e3b 100644
--- a/examples/interfaceframework/qface-if-climate/example-if-climate.qface
+++ b/examples/interfaceframework/qface-climate/example-climate.qface
diff --git a/examples/interfaceframework/qface-if-climate/example-if-climate.yaml b/examples/interfaceframework/qface-climate/example-climate.yaml
index f774fe35..f774fe35 100644
--- a/examples/interfaceframework/qface-if-climate/example-if-climate.yaml
+++ b/examples/interfaceframework/qface-climate/example-climate.yaml
diff --git a/examples/interfaceframework/qface-if-climate/frontend/CMakeLists.txt b/examples/interfaceframework/qface-climate/frontend/CMakeLists.txt
index f2d6cb43..5f4e0df9 100644
--- a/examples/interfaceframework/qface-if-climate/frontend/CMakeLists.txt
+++ b/examples/interfaceframework/qface-climate/frontend/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-climate")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-climate")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -24,7 +24,7 @@ qt6_add_library(QtIfClimateExample)
# Interface Framework Generator:
qt6_ifcodegen_extend_target(QtIfClimateExample
- IDL_FILES ../example-if-climate.qface
+ IDL_FILES ../example-climate.qface
TEMPLATE frontend
)
#! [1]
diff --git a/examples/interfaceframework/qface-if-climate/frontend/frontend.pro b/examples/interfaceframework/qface-climate/frontend/frontend.pro
index 2a1f9015..45bd140c 100644
--- a/examples/interfaceframework/qface-if-climate/frontend/frontend.pro
+++ b/examples/interfaceframework/qface-climate/frontend/frontend.pro
@@ -10,8 +10,8 @@ QT += interfaceframework qml quick
#! [1]
CONFIG += ifcodegen
-IFCODEGEN_SOURCES = ../example-if-climate.qface
+IFCODEGEN_SOURCES = ../example-climate.qface
#! [1]
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-climate
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-climate
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-climate/qface-if-climate.pro b/examples/interfaceframework/qface-climate/qface-climate.pro
index 6879e643..769d621d 100644
--- a/examples/interfaceframework/qface-if-climate/qface-if-climate.pro
+++ b/examples/interfaceframework/qface-climate/qface-climate.pro
@@ -7,5 +7,5 @@ SUBDIRS = frontend \
CONFIG += ordered
OTHER_FILES += \
- example-if-climate.qface \
- example-if-climate.yaml
+ example-climate.qface \
+ example-climate.yaml
diff --git a/examples/interfaceframework/qface-if-remote/CMakeLists.txt b/examples/interfaceframework/qface-remote/CMakeLists.txt
index 9b6d2fc7..60d58632 100644
--- a/examples/interfaceframework/qface-if-remote/CMakeLists.txt
+++ b/examples/interfaceframework/qface-remote/CMakeLists.txt
@@ -1,4 +1,3 @@
-# Generated from qface-if-remote.pro.
cmake_minimum_required(VERSION 3.14)
project(example_if_remote LANGUAGES CXX)
diff --git a/examples/interfaceframework/qface-if-remote/backend_qtro/CMakeLists.txt b/examples/interfaceframework/qface-remote/backend_qtro/CMakeLists.txt
index 5628738f..4ebb32a2 100644
--- a/examples/interfaceframework/qface-if-remote/backend_qtro/CMakeLists.txt
+++ b/examples/interfaceframework/qface-remote/backend_qtro/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-remote/interfaceframework/")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-remote/interfaceframework/")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -25,7 +25,7 @@ set_target_properties(remote_backend_qtro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ..
#! [2]
# Interface Framework Generator:
qt6_ifcodegen_extend_target(remote_backend_qtro
- IDL_FILES ../example-if-remote.qface
+ IDL_FILES ../example-remote.qface
TEMPLATE backend_qtro
)
#! [2]
diff --git a/examples/interfaceframework/qface-if-remote/backend_qtro/backend_qtro.pro b/examples/interfaceframework/qface-remote/backend_qtro/backend_qtro.pro
index be83f15e..4921ee5f 100644
--- a/examples/interfaceframework/qface-if-remote/backend_qtro/backend_qtro.pro
+++ b/examples/interfaceframework/qface-remote/backend_qtro/backend_qtro.pro
@@ -16,10 +16,10 @@ QT += core interfaceframework
#! [2]
CONFIG += ifcodegen plugin
IFCODEGEN_TEMPLATE = backend_qtro
-IFCODEGEN_SOURCES = ../example-if-remote.qface
+IFCODEGEN_SOURCES = ../example-remote.qface
PLUGIN_TYPE = interfaceframework
PLUGIN_CLASS_NAME = RemoteClientQtROPlugin
#! [2]
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-remote/interfaceframework/
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-remote/interfaceframework/
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-remote/demo/CMakeLists.txt b/examples/interfaceframework/qface-remote/demo/CMakeLists.txt
index 01322e8b..8a1b626f 100644
--- a/examples/interfaceframework/qface-if-remote/demo/CMakeLists.txt
+++ b/examples/interfaceframework/qface-remote/demo/CMakeLists.txt
@@ -1,7 +1,7 @@
# Generated from demo.pro.
cmake_minimum_required(VERSION 3.14)
-project(qface-if-remote LANGUAGES CXX)
+project(qface-remote LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -13,7 +13,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-remote")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-remote")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
@@ -21,20 +21,20 @@ find_package(Qt6 COMPONENTS Qml)
find_package(Qt6 COMPONENTS Quick)
find_package(Qt6 COMPONENTS InterfaceFramework)
-qt_add_executable(qface-if-remote
+qt_add_executable(qface-remote
main.cpp
)
-set_target_properties(qface-if-remote PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
-set_target_properties(qface-if-remote PROPERTIES
+set_target_properties(qface-remote PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
+set_target_properties(qface-remote PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE FALSE
)
-target_compile_definitions(qface-if-remote PUBLIC
+target_compile_definitions(qface-remote PUBLIC
QT_DEPRECATED_WARNINGS
)
-target_link_libraries(qface-if-remote PUBLIC
+target_link_libraries(qface-remote PUBLIC
QtIfRemoteExample
Qt::Core
Qt::Gui
@@ -48,14 +48,14 @@ set(qml_resource_files
"main.qml"
)
-qt6_add_resources(qface-if-remote "qml"
+qt6_add_resources(qface-remote "qml"
PREFIX
"/"
FILES
${qml_resource_files}
)
-install(TARGETS qface-if-remote
+install(TARGETS qface-remote
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/interfaceframework/qface-if-remote/demo/demo.pro b/examples/interfaceframework/qface-remote/demo/demo.pro
index ed97d881..ca6ee5f0 100644
--- a/examples/interfaceframework/qface-if-remote/demo/demo.pro
+++ b/examples/interfaceframework/qface-remote/demo/demo.pro
@@ -1,4 +1,4 @@
-TARGET = qface-if-remote
+TARGET = qface-remote
QMAKE_PROJECT_NAME = $$TARGET
TEMPLATE = app
@@ -34,5 +34,5 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-remote
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-remote
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-remote/demo/main.cpp b/examples/interfaceframework/qface-remote/demo/main.cpp
index faecda76..faecda76 100644
--- a/examples/interfaceframework/qface-if-remote/demo/main.cpp
+++ b/examples/interfaceframework/qface-remote/demo/main.cpp
diff --git a/examples/interfaceframework/qface-if-remote/demo/main.qml b/examples/interfaceframework/qface-remote/demo/main.qml
index 61e0d1a9..61e0d1a9 100644
--- a/examples/interfaceframework/qface-if-remote/demo/main.qml
+++ b/examples/interfaceframework/qface-remote/demo/main.qml
diff --git a/examples/interfaceframework/qface-if-remote/demo/qml.qrc b/examples/interfaceframework/qface-remote/demo/qml.qrc
index 5f6483ac..5f6483ac 100644
--- a/examples/interfaceframework/qface-if-remote/demo/qml.qrc
+++ b/examples/interfaceframework/qface-remote/demo/qml.qrc
diff --git a/examples/interfaceframework/qface-remote/doc/images/qface-remote.png b/examples/interfaceframework/qface-remote/doc/images/qface-remote.png
new file mode 100644
index 00000000..fc671c7d
--- /dev/null
+++ b/examples/interfaceframework/qface-remote/doc/images/qface-remote.png
Binary files differ
diff --git a/examples/interfaceframework/qface-remote/doc/src/qface-remote.qdoc b/examples/interfaceframework/qface-remote/doc/src/qface-remote.qdoc
new file mode 100644
index 00000000..20d801af
--- /dev/null
+++ b/examples/interfaceframework/qface-remote/doc/src/qface-remote.qdoc
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** 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-remote
+\brief Learn how to use the Qt Interface Framework Generator to create QtRemoteObjects based
+backends.
+\ingroup qtinterfaceframework-examples
+\title Generate QtRemoteObjects based backends with the Qt Interface Framework Generator
+\image qface-remote.png
+
+\section1 Introduction
+
+This example shows how to generate a Middleware API, a Middleware Backend, and the
+corresponding Middleware Service using the Qt Interface Framework Generator. The communication
+between the backend and the service is done with QtRemoteObjects as the IPC.
+
+We use a single QFace IDL file to generate:
+
+\list
+\li a shared library with the front-end code
+\li a backend plugin that implements a client to connect to the server
+\li a server that runs the actual backend logic in a separate server process
+\li a demo application that connects to the server and provides a UI to use the service
+\endlist
+
+In addition to the generated C++ code, the backend plugin and the server also contain an
+intermediate \c{.rep} file that is further processed by the
+\l [QtRemoteObjects] {Qt Remote Objects Compiler} {replica compiler} to produce the source and
+replica classes.
+
+\section2 Walkthrough
+
+The IDL file used in the example represents an imaginary remote service for processing data. It
+contains a single interface with one property and one method.
+
+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.
+
+\snippet interfaceframework/qface-remote/example-remote.qface 0
+
+The most important part is the definition of the \e interface.
+
+\snippet interfaceframework/qface-remote/example-remote.qface 1
+
+In this case, we define an \e interface named \b ProcessingService with one property and one
+method. Every property and method definition needs to 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}.
+
+
+\section1 Frontend library
+
+Next, we use the Interface Framework Generator to generate a shared library containing a C++
+implementation of our module and its interface; particularly the \e frontend template. This template
+generates a class derived from \l{QIfAbstractFeature}, that includes all of the specified
+properties. The generated library uses the \l{Dynamic Backend System} from QtInterfaceFramework,
+consequently providing an easy way to change how the behavior is implemented.
+
+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-remote/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-remote/frontend/CMakeLists.txt 1
+
+\e qmake:
+
+\snippet interfaceframework/qface-remote/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, similar to the \c SOURCES variable in regular qmake
+projects. However, activating the qmake feature via the \c CONFIG variable has one disadvantage: if
+the feature is not available, no errors are reported. We recommend using the following additional
+code to report errors:
+
+\snippet interfaceframework/qface-remote/frontend/frontend.pro 0
+
+The remaining part of the project file is a normal library setup that works on Linux, macOS, and
+Windows.
+
+
+\section1 QtRemoteObjects Backend Plugin
+
+As mentioned above, the \e frontend library uses the \l{Dynamic Backend System}. This means
+that for the library to provide some functionality, we also need a \e backend plugin. The generated
+plugin here works as a client that connects to the server using Qt Remote Objects. 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-remote/backend_qtro/CMakeLists.txt 2
+
+\e qmake:
+
+\snippet interfaceframework/qface-remote/backend_qtro/backend_qtro.pro 2
+
+The generated backend plugin code is usable as is, and doesn't require any further change. 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.
+
+For the plugin to compile correctly it needs to get the
+backend interface header from the previously created library. But this header is also generated, so
+it's not part of our source tree, but part of the build tree. To provide the backend interface
+header, we add it to the include path using the following code:
+
+\e CMake:
+
+\snippet interfaceframework/qface-remote/backend_qtro/CMakeLists.txt 1
+
+\e qmake:
+
+\snippet interfaceframework/qface-remote/backend_qtro/backend_qtro.pro 1
+
+Most of the code in the backend plugin is generated by the Interface Framework Generator, but some
+of it is generated by the Qt's Remote Object Compiler, \c repc. To achieve this, the Interface
+Framework Generator produces an intermediate \c{.repc} file that's further processed by the \c repc
+compiler. This compiler is called via the generated build system file, found in the build directory.
+
+
+Our application doesn't know about the existence of our backend plugin, so we need to put this
+plugin in a folder where the application typically looks for plugins. By default, Qt either
+searches 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 provided within a
+\b interfaceframework sub-folder. Add the following line to the backend build system file, as
+follows:
+
+\e CMake:
+
+\snippet interfaceframework/qface-remote/backend_qtro/CMakeLists.txt 0
+
+\e qmake:
+
+\snippet interfaceframework/qface-remote/backend_qtro/backend_qtro.pro 0
+
+
+\section1 RemoteObjects Server
+
+The server is an independent, GUI-less application that contains the backend's business logic, and
+we need to write most of its implementation. Nevertheless, the generator produces some code to
+simplify the development. We can generate server side code by using the Interface Framework
+Generator with the \e server_qtro template:
+
+\e CMake:
+
+\snippet interfaceframework/qface-remote/server_qtro/CMakeLists.txt 0
+
+\e qmake:
+
+\snippet interfaceframework/qface-remote/server_qtro/server_qtro.pro 0
+\dots 0
+\snippet interfaceframework/qface-remote/server_qtro/server_qtro.pro 1
+
+To use the generated remote source, we need to inherit from one of the classes defined in the
+generated \c rep_processingservice_source.h file. In this example, we implement our server's
+logic in the \c ProcessingService class and use the \c ProcessingServiceSimpleSource as the base
+class:
+
+\code
+// server_qtro/processingservice.h
+\endcode
+\snippet interfaceframework/qface-remote/server_qtro/processingservice.h 0
+
+Note that the base class already has the definitions for property accessors, but any custom
+method or slot needs to be overridden and defined. Our implementation of the process function
+merely counts and returns the length of the data passed and updates the \c lastMessage property:
+
+\code
+// server_qtro/processingservice.cpp
+\endcode
+\snippet interfaceframework/qface-remote/server_qtro/processingservice.cpp 0
+
+To make the \c ProcessingService class accessible remotely, we need to share it via the
+QRemoteObjectNode::enableRemoting() function. The \c Core class generated provides a preconfigured
+instance of a \c remotenode that is used for the remoting. For the plugin to connect to the right
+object, use an identifier in the format "ModuleName.InterfaceName", which in our case is
+"Example.If.Remote.ProcessingService". All this is done in the \c main() function, along with
+the start of the main event loop:
+
+\code
+// server_qtro/main.cpp
+\endcode
+\snippet interfaceframework/qface-remote/server_qtro/main.cpp 0
+
+This is all you need to do to implement a service that is accessible remotely; use the properties
+as usual and provide the method implementations. The QtRemoteObjects library takes care of the
+communication.
+
+
+\section1 Demo Client Application
+
+The demo application presents a simple QML GUI to use the remote service over the generated
+interface.
+
+As we do not provide a QML plugin, the application needs to link to the generated frontend library
+and call the \c{RemoteModule::registerTypes} and \c{RemoteModule::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 which is used
+in the QFace file. Afterwards the interface can be instantiated like any other QML item.
+
+\code
+// demo/main.qml
+\endcode
+\snippet interfaceframework/qface-remote/demo/main.qml 0
+\dots 0
+
+Every method call that is made through a generated API, is asynchronous. This means that instead
+of directly returning a return value, a QIfPendingReply object is returned. Using the
+\l QIfPendingReply::then() method on the returned object, we may assign callbacks to it that are
+called when the method call has been successfully finished; or if it has failed.
+
+\code
+// demo/main.qml
+\endcode
+\snippet interfaceframework/qface-remote/demo/main.qml 1
+
+In case of properties, we use bindings as usual:
+
+\code
+// demo/main.qml
+\endcode
+\snippet interfaceframework/qface-remote/demo/main.qml 2
+
+\section1 Running the Example
+
+To see the demo's entire functionality, run both the server and the demo application
+simultaneously. You may leave the server running and restart the application, or vice versa,
+to see that the reconnection works. Run the demo application alone without the server running,
+to test how the remote method call fails when there is no connection.
+
+*/
diff --git a/examples/interfaceframework/qface-if-remote/example-if-remote.qface b/examples/interfaceframework/qface-remote/example-remote.qface
index 4354e9e7..4354e9e7 100644
--- a/examples/interfaceframework/qface-if-remote/example-if-remote.qface
+++ b/examples/interfaceframework/qface-remote/example-remote.qface
diff --git a/examples/interfaceframework/qface-if-remote/frontend/CMakeLists.txt b/examples/interfaceframework/qface-remote/frontend/CMakeLists.txt
index 0e756e4f..0b2342f8 100644
--- a/examples/interfaceframework/qface-if-remote/frontend/CMakeLists.txt
+++ b/examples/interfaceframework/qface-remote/frontend/CMakeLists.txt
@@ -13,7 +13,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-remote")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-remote")
find_package(Qt6 COMPONENTS Core)
#! [0]
@@ -27,7 +27,7 @@ qt6_add_library(QtIfRemoteExample)
# Interface Framework Generator:
qt6_ifcodegen_extend_target(QtIfRemoteExample
- IDL_FILES ../example-if-remote.qface
+ IDL_FILES ../example-remote.qface
TEMPLATE frontend
)
#! [1]
diff --git a/examples/interfaceframework/qface-if-remote/frontend/frontend.pro b/examples/interfaceframework/qface-remote/frontend/frontend.pro
index 1765afb3..bebdf360 100644
--- a/examples/interfaceframework/qface-if-remote/frontend/frontend.pro
+++ b/examples/interfaceframework/qface-remote/frontend/frontend.pro
@@ -10,8 +10,8 @@ QT += interfaceframework qml quick
#! [1]
CONFIG += ifcodegen
-IFCODEGEN_SOURCES = ../example-if-remote.qface
+IFCODEGEN_SOURCES = ../example-remote.qface
#! [1]
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-remote
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-remote
INSTALLS += target
diff --git a/examples/interfaceframework/qface-if-remote/qface-if-remote.pro b/examples/interfaceframework/qface-remote/qface-remote.pro
index 085236b2..0dbdb0b6 100644
--- a/examples/interfaceframework/qface-if-remote/qface-if-remote.pro
+++ b/examples/interfaceframework/qface-remote/qface-remote.pro
@@ -8,4 +8,4 @@ SUBDIRS = frontend \
CONFIG += ordered
OTHER_FILES += \
- example-if-remote.qface
+ example-remote.qface
diff --git a/examples/interfaceframework/qface-if-remote/server_qtro/CMakeLists.txt b/examples/interfaceframework/qface-remote/server_qtro/CMakeLists.txt
index 17975374..185caee9 100644
--- a/examples/interfaceframework/qface-if-remote/server_qtro/CMakeLists.txt
+++ b/examples/interfaceframework/qface-remote/server_qtro/CMakeLists.txt
@@ -1,7 +1,7 @@
# Generated from server_qtro.pro.
cmake_minimum_required(VERSION 3.14)
-project(qface-if-remote-server LANGUAGES CXX)
+project(qface-remote-server LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -13,43 +13,43 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-if-remote-server")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/interfaceframework/qface-remote-server")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Qml)
find_package(Qt6 COMPONENTS Quick)
find_package(Qt6 COMPONENTS InterfaceFramework)
-qt_add_executable(qface-if-remote-server
+qt_add_executable(qface-remote-server
main.cpp
processingservice.cpp processingservice.h
)
#! [0]
# Interface Framework Generator:
-qt6_ifcodegen_extend_target(qface-if-remote-server
- IDL_FILES ../example-if-remote.qface
+qt6_ifcodegen_extend_target(qface-remote-server
+ IDL_FILES ../example-remote.qface
TEMPLATE server_qtro
)
#! [0]
-set_target_properties(qface-if-remote-server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
+set_target_properties(qface-remote-server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
-set_target_properties(qface-if-remote-server PROPERTIES
+set_target_properties(qface-remote-server PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE FALSE
)
-target_compile_definitions(qface-if-remote-server PUBLIC
+target_compile_definitions(qface-remote-server PUBLIC
QT_DEPRECATED_WARNINGS
)
-target_link_libraries(qface-if-remote-server PUBLIC
+target_link_libraries(qface-remote-server PUBLIC
QtIfRemoteExample
Qt::Core
)
-install(TARGETS qface-if-remote-server
+install(TARGETS qface-remote-server
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/interfaceframework/qface-if-remote/server_qtro/main.cpp b/examples/interfaceframework/qface-remote/server_qtro/main.cpp
index 765ba103..765ba103 100644
--- a/examples/interfaceframework/qface-if-remote/server_qtro/main.cpp
+++ b/examples/interfaceframework/qface-remote/server_qtro/main.cpp
diff --git a/examples/interfaceframework/qface-if-remote/server_qtro/processingservice.cpp b/examples/interfaceframework/qface-remote/server_qtro/processingservice.cpp
index f3cd443f..f3cd443f 100644
--- a/examples/interfaceframework/qface-if-remote/server_qtro/processingservice.cpp
+++ b/examples/interfaceframework/qface-remote/server_qtro/processingservice.cpp
diff --git a/examples/interfaceframework/qface-if-remote/server_qtro/processingservice.h b/examples/interfaceframework/qface-remote/server_qtro/processingservice.h
index 9f68b2eb..9f68b2eb 100644
--- a/examples/interfaceframework/qface-if-remote/server_qtro/processingservice.h
+++ b/examples/interfaceframework/qface-remote/server_qtro/processingservice.h
diff --git a/examples/interfaceframework/qface-if-remote/server_qtro/server_qtro.pro b/examples/interfaceframework/qface-remote/server_qtro/server_qtro.pro
index c89a77ce..a4618e8d 100644
--- a/examples/interfaceframework/qface-if-remote/server_qtro/server_qtro.pro
+++ b/examples/interfaceframework/qface-remote/server_qtro/server_qtro.pro
@@ -1,4 +1,4 @@
-TARGET = qface-if-remote-server
+TARGET = qface-remote-server
#! [0]
TEMPLATE = app
QT -= gui
@@ -16,7 +16,7 @@ SOURCES += main.cpp \
QMAKE_RPATHDIR += $ORIGIN
#! [1]
IFCODEGEN_TEMPLATE = server_qtro
-IFCODEGEN_SOURCES = ../example-if-remote.qface
+IFCODEGEN_SOURCES = ../example-remote.qface
#! [1]
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
@@ -36,7 +36,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += install_ok # Do not cargo-cult this!
-target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-if-remote-server
+target.path = $$[QT_INSTALL_EXAMPLES]/interfaceframework/qface-remote-server
INSTALLS += target
HEADERS += \
diff --git a/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-dbus.gif b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-dbus.gif
new file mode 100644
index 00000000..6b3da504
--- /dev/null
+++ b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-dbus.gif
Binary files differ
diff --git a/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-final.gif b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-final.gif
new file mode 100644
index 00000000..e8a833bd
--- /dev/null
+++ b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-final.gif
Binary files differ
diff --git a/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-sync.gif b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-sync.gif
new file mode 100644
index 00000000..b1dece69
--- /dev/null
+++ b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-sync.gif
Binary files differ
diff --git a/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-unsync.gif b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-unsync.gif
new file mode 100644
index 00000000..7157d9e6
--- /dev/null
+++ b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial-unsync.gif
Binary files differ
diff --git a/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial.png b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial.png
new file mode 100644
index 00000000..318cceae
--- /dev/null
+++ b/examples/interfaceframework/qface-tutorial/doc/images/qface-tutorial.png
Binary files differ
diff --git a/examples/interfaceframework/qface-tutorial/doc/src/qface-tutorial.qdoc b/examples/interfaceframework/qface-tutorial/doc/src/qface-tutorial.qdoc
new file mode 100644
index 00000000..f5e8fe21
--- /dev/null
+++ b/examples/interfaceframework/qface-tutorial/doc/src/qface-tutorial.qdoc
@@ -0,0 +1,893 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2019 Luxoft Sweden AB
+** 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-tutorial
+ \brief Demonstrates step-by-step how to generate a Middleware API based on a QML application.
+ \ingroup qtinterfaceframework-examples
+ \title Qt Interface Framework Generator Tutorial
+ \image qface-tutorial.png
+
+ This tutorial demonstrates how you can extend a QML application with your own autogenerated
+ Middleware API. We use an existing QML Instrument Cluster application and proceed through the
+ following steps:
+
+ \list 1
+ \li \l{chapter1}{Integrate a basic interface without a backend}
+ \li \l{chapter2}{Extend the interface and add annotations}
+ \li \l{chapter3}{Add a simulation backend and corresponding simulation annotations; with a QML plugin}
+ \li \l{chapter4}{Add a custom simulation behavior}
+ \li \l{chapter5}{Add a simulation server and use it from a Qt Remote Objects Backend}
+ \li \l{chapter6}{Develop a production backend that connects to a DBus interface}
+ \endlist
+
+ Before we start the actual Middleware integration, let's take a look at the existing Instrument
+ Cluster QML code and all the features it supports:
+ \list
+ \li \c images -- This folder contains all images used in the QML code.
+ \li \c Cluster.qml -- The main QML file that assembles all other QML components together.
+ \li \c Dial.qml -- The base component to show values like speed or Revolutions per Minute
+ (RPM), using a needle.
+ \li \c Fuel.qml -- The component to show the actual fuel level.
+ \li \c Label.qml -- A small helper component which sets all common settings used to display
+ text.
+ \li \c LeftDial.qml -- Shows the current speed using the Dial component and as text, as
+ well as the current metric in miles per hour (mph) or kilometers per hour (km/h).
+ \li \c RightDial.qml -- Shows the current RPM and offers a way to show warning indicators.
+ \li \c Top.qml -- The top bar that shows the current date and the current temperature.
+ \endlist
+
+ Next, we use our Middleware API to add support for the following features:
+ \list
+ \li Show the current speed in the left dial.
+ \li Show the current RPM in the right dial.
+ \li Change between different metrics.
+ \li Show the current temperature in the top bar.
+ \li Show different warnings on the right dial.
+ \li Indicate whether the instrument cluster is connected and show real data.
+ \endlist
+
+ The ultimate goal is to connect all of these features together to simulate a real-time driving
+ experience like this:
+
+ \image qface-tutorial-final.gif
+
+ \target chapter1
+ \section1 Chapter 1: Basic Middlware API with the Interface Framework Generator
+
+ In this chapter we integrate a Middleware API into the existing Instrument Cluster QML code.
+ Instead of manually writing all of these parts ourselves, which is done in most basic
+ \l{https://doc.qt.io/qt-5/qtquick-codesamples.html}{QML examples}, we'll use the Interface Framework Generator
+ to autogenerate the required parts.
+
+ \target define-speed-property
+ \section2 Interface Definition Language
+
+ To be able to autogenerate the Middleware API, the Interface Framework Generator needs some input on what to
+ generate. This input is given in form of an Interface Definition Language (IDL), QFace, which
+ describes the API in a very simple way.
+
+ Let's start to define a very simple interface which provides us with a speed property:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/instrument-cluster.qface
+ \printuntil }
+
+ First, we need to define which module we want to describe. The module acts as a namespace,
+ because the IDL file can contain multiple interfaces.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/instrument-cluster.qface
+ \printuntil module
+
+ The most important part of the module is its interface definition.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/instrument-cluster.qface
+ \skipto interface
+ \printuntil }
+
+ In this case, we define an interface named \c InstrumentCluster that consists of one property.
+ 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}.
+
+ \section2 Autogeneration
+
+ Now that our first version of the IDL file is ready, it's time to autogenerate API from it,
+ using the \l{Qt Interface Framework Generator}{Interface Framework Generator tool}. Similar to
+ \l{https://doc.qt.io/qt-5/moc.html}{moc}, this autogeneration process is integrated into the
+ Build System and is done on compile time.
+
+ In the following snippets we build a C++ library based on our IDL file:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/frontend/CMakeLists.txt
+ \skipto find_package
+ \printto install
+
+ First \e find_package needs to be used to get all needed libraries into the CMake build system.
+ A new library is defined with \l {qt6_add_library} and, using CMake target_properties, the
+ output name, as well as the output directory are set. As we need to link to this library in the
+ future, it is easier to put the file into the upper directory.
+
+ By calling the \l {qt6_ifcodegen_extend_target} function, the autogenerator is called and the
+ previously defined library is extended with the generated files. The input file is specified
+ using the \e IDL_FILES argument. See \l{Build System Integration} for more information.
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/frontend/frontend.pro
+ \printto CONFIG += install_ok
+
+ Most of the \c{.pro} file is a standard setup to define a C++ library, using "lib" \c TEMPLATE
+ and defining the required file name in the \c TARGET variable. The \c qtLibraryTarget function
+ that we use helps to append the "d" postfix on the filename correctly, for a library that
+ provides debugging information. In the future, we need to link this file, so we set the
+ \c DESTDIR to the upper directory to simplify this.
+
+ \note Windows searches for libraries in the same directory automatically.
+
+ Activating the Interface Framework Generator integration requires the \c CONFIG variable to specify the
+ \c ifcodegen option. This makes sure the Interface Framework Generator is called during the build process,
+ using the QFace file that we specify in \c IFCODEGEN_SOURCES. For more information, see
+ \l{Build System Integration}.
+
+ \section2 Which Files are Autogenerated
+
+ The Interface Framework Generator works based on generation templates. These templates define what content
+ should be generated from a QFace file. Using qmake the template needs to be defined by the
+ \c IFCODEGEN_TEMPLATE variable. If it is not defined, it defaults to the "frontend" template.
+ In CMake the template neeeds to be specified using the \c TEMPLATE argument of
+ \l {qt6_ifcodegen_extend_target} and friends.
+ For more details on these templates, see \l{Use the Generator}.
+
+ In short, the "frontend" template generates:
+ \list
+ \li a C++ class derived from QIfAbstractFeature for every interface in the QFace file
+ \li one module class that helps to register all interfaces to QML and stores global types
+ and functions.
+ \endlist
+
+ To inspect the C++ code yourself, you can view these files in the your library's build folder.
+
+ Right now, the most important autogenerated file for us, is the resulting C++ class for our
+ defined interface. It looks like this:
+
+ \quotefile interfaceframework/qface-tutorial/chapter1-basics/frontend/instrumentcluster.h
+
+ As you can see, the autogenerated C++ class implements a \c speed property, that we previously
+ defined in the QFace file. By using the \c Q_OBJECT and \c Q_PROPERTY macros, the class is now
+ ready for use directly in your QML code.
+
+ \section2 Integrate the Frontend Library with the QML Code
+
+ For this integration, we use the autogenerated frontend library from the QML code. For the sake
+ of simplicity, we follow the standard Qt example pattern and use a small C++ main function
+ which registers our autogenerated types to QML and loads the Instrument Cluster QML code into
+ the QQmlApplicationEngine:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/instrument-cluster/main.cpp
+ \skipto #include "instrumentclustermodule.h"
+ \printuntil }
+
+ All we need now is the actual integration of the InstrumentCluster QML element and connecting
+ the \c speed property to the \c leftDial. This is done by instantiating the element first with
+ the \c instrumentCluster ID.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/instrument-cluster/Cluster.qml
+ \skipto import
+ \printuntil InstrumentCluster
+ \printuntil }
+ \codeline
+
+ Lastly, we can create a Binding for the \c LeftDial Item's \c value property to our
+ InstrumentCluster API's \c speed property.
+
+ \printuntil }
+
+ \target chapter2
+ \section1 Chapter 2: Extend the Interface and add Annotations
+
+ In this chapter we extend our Middleware API with more properties via enums and by defining our
+ own structure.
+
+ \section2 Define Speed as a Read-only Property
+
+ \l{define-speed-property}{Previously}, we defined the speed property in our QFace file in the
+ following way:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter1-basics/instrument-cluster.qface
+ \printuntil }
+
+ This property is defined as readable and writable, as we didn't use any extra specifiers.
+ However, it's not necessary for our Instrument Cluster example to have a writable \c speed
+ property because it's not used to accelerate the car, but just to visualize the current state.
+
+ To define the property as read-only, use the \c readonly keyword.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter2-enums-structs/instrument-cluster.qface
+ \printuntil readonly
+ \skipto }
+ \printuntil }
+
+ When we build our app again, the build system recognizes this change and runs the Interface Framework
+ Generator to generate an updated version of the C++ code. After the Interface Framework Generator is done,
+ open the \c instrumentcluster.h from the build folder and notice that the generated
+ \c speed property changed -- it no longer has a setter anymore and is now read-only.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter2-enums-structs/frontend/instrumentcluster.h
+ \skipto class Q_EXAMPLE
+ \printuntil Q_PROPERTY
+ \dots
+ \skipto };
+ \printuntil };
+
+ \section2 Extend the Interface
+
+ To reach our goal to provide a full simulation for the Instrument Cluster, we need to add more
+ properties to our QFace file: \c rpm, \c fuel and \c temperature:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter2-enums-structs/instrument-cluster.qface
+ \printuntil readonly real temperature
+ \skipto }
+ \printuntil }
+
+ You might have noticed that we use a different type for the \c fuel and \c temperature
+ properties. We use \c real here, as we would like to show the temperature as a floating point
+ number, and the current fuel level as a value between 0 and 1.
+
+ \section2 Define a New Enum Type
+
+ One useful feature is to be able to switch between the metric and the imperial system, so we
+ need to define a property for the system we currently use. Using a boolean property would work,
+ but doesn't offer a nice API, so we define a new enum type in the QFace file and use it as the
+ type for our new \c system property:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter2-enums-structs/instrument-cluster.qface
+ \printuntil readonly SystemType
+ \skipto }
+ \printuntil enum
+ \printuntil }
+
+ In the autogenerated code, this results in an enum which is part of the module class, making it
+ possible for the same enum to be used by multiple classes which are part of the same module:
+
+ \quotefile interfaceframework/qface-tutorial/chapter2-enums-structs/frontend/instrumentclustermodule.h
+
+ \section2 Add a New Structure
+
+ To display warnings on the Instrument Cluster's right dial, we'd like to use a structure that
+ stores color, icon, and text for the warning; instead of using 3 independent properties.
+ Similar to defining an interface, we can use the \c struct keyword in our QFace file:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter2-enums-structs/instrument-cluster.qface
+ \skipto struct
+ \printuntil }
+
+ Using this new structure as a type for a property, works in the same way as when using an enum.
+ The QFace file should now look like this:
+
+ \quotefile interfaceframework/qface-tutorial/chapter2-enums-structs/instrument-cluster.qface
+
+ \section2 Integrate the New Properties
+
+ Like in the previous chapter, actually integrating the newly introduced properties involves
+ creating Bindings. The \c rpm property can be directly connected to the \c rightDial Item's
+ \c value property; the same is done for the top Item's \c temperature property. To control
+ which unit is displayed in the left Dial, the \c leftDial Item provides \c metricSystem, a bool
+ property. As we used an enum in our QFace file, we need to convert the value first by testing
+ the \c sytemType property for the "Metric" value.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter2-enums-structs/instrument-cluster/Cluster.qml
+ \skipto LeftDial
+ \printuntil }
+ \codeline
+
+ These enums are part of the module class, which is also exported to QML as
+ \c InstrumentClusterModule. To trigger a warning in the \c rightDial Item, we use 3 bindings to
+ connect to the 3 member variables in the structure:
+
+ \printuntil }
+
+ \target chapter3
+ \section1 Chapter 3: Add a Simulation Backend and Annotations with a QML plugin
+
+ In the previous two chapters, we wrote a Middleware API using a QFace file and used the Interface Framework
+ Generator to autogenerate a C++ API in the form of a library. Now, in this chapter, we extend
+ this further by introducing a simulation backend and using annotations to define default values
+ for our simulation.
+
+ \section2 Separation between the Frontend and Backend
+
+ Both QtInterfaceFramework and the Interface Framework Generator enable you to write code that separates the frontend from the
+ backend -- to split an API from its actual implementation. Already, Qt uses this concept in a
+ lot of areas, most prominently in the underlying window system technology on various Qt
+ platforms like XCB on Linux and Cocoa on macOS.
+
+ The same separation is done for our Middleware API, where the frontend provides the API as
+ a library; the backend provides an implementation of this API. This implementation is based on
+ QtInterfaceFramework's \l{Dynamic Backend System} which enables us to switch between such backends at runtime.
+
+ \image feature-backend.png
+
+ \section2 Add a Simulation Backend
+
+ For our Instrument Cluster, we'd like to add such a backend to provide actual values. For now,
+ we'd like to just have some simulation behavior as we can't connect it easily to a real car.
+ This is why such backends are called "simulation backend". To add this type of backend, once
+ again, we use the Interface Framework Generator to do the heavy lifting for us and generate one. This work
+ is done in a similar way to when we generated a library with the "frontend" template. But now,
+ we are using the "backend_simulator" template:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/CMakeLists.txt
+ \skipto find_package
+ \printto target_link_libraries
+
+ Similar to the frontend library, first the used components are imported using \e find_package.
+ As we want to build a plugin (dynamic library) which is loaded at runtime instead of linking
+ against it, we use the \l {qt_add_plugin} function instead. One important aspect
+ here is that the library name ends with "_simulation", which is a way to tell QtInterfaceFramework that this
+ is a simulation backend. When a "production" backend is available, it is preferred over the
+ "simulation" one. For more information, see \l{Dynamic Backend System}.
+
+ As before, the Interface Framework Generator is called by using the \l{qt6_ifcodegen_extend_target}
+ function, this time setting "backend_simulator" as the \c TEMPLATE.
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/backend_simulator.pro
+ \printto DESTDIR
+ \skipto QT
+ \printuntil CONFIG
+ \skipto IFCODEGEN_TEMPLATE
+ \printto CONFIG += install_ok
+
+ Just like for the frontend library, the project file builds a \c lib and defines the library
+ name using \c qtLibraryTarget to also support the Windows debug postfix. One important aspect
+ here is that the library name ends with "_simulation", which is a way to tell QtInterfaceFramework that this
+ is a simulation backend. When a "production" backend is available, it is preferred over the
+ "simulation" one. For more information, see \l{Dynamic Backend System}.
+
+ Enabling the Interface Framework Generator is also done in the same way as we did earlier: by using the same
+ \c IFCODEGEN_SOURCE variable, but defining \c IFCODEGEN_TEMPLATE to "backend_simulator", to use the
+ correct generation template. In addition, we need to add 'plugin' to the \c CONFIG variable,
+ to make this library a Qt plugin which can be easily loaded at runtime.
+
+ \section2 Link Settings and Locating Plugins
+
+ Trying to build the project file just as it is, right now, would result in compilation and
+ linking errors. This is because: to do the frontend and backend separation, we need to have the
+ backend implement a defined interface class, that is known to the frontend. This interface is
+ aptly called "backend interface" and is automatically generated as part of the frontend
+ library. Because this class provides signals and slots and uses QObject for its base class, you
+ need to link to the frontend library when you inherit from it. As this is needed for the
+ backend plugin, we need to add the following lines in addition:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/CMakeLists.txt
+ \skipto target_link_libraries
+ \printto install
+
+ By defining the frontent library named \e libIc_chapter3 as a target link library the include
+ path gets updated accordingly.
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/backend_simulator.pro
+ \skipuntil CONFIG
+ \printuntil INCLUDEPATH
+
+ Now the project should build fine and create the plugin in your build folder; or the plugin
+ folder if you don't use a shadow build. When you start the Instrument Cluster again, you should
+ see the following message:
+
+ \badcode
+ There is no production backend implementing "Example.If.InstrumentCluster.InstrumentCluster" .
+ There is no simulation backend implementing "Example.If.InstrumentCluster.InstrumentCluster" .
+ No suitable ServiceObject found.
+ \endcode
+
+ This message indicates that QtInterfaceFramework is still unable to find the simulation plugin we just created.
+ Here, you need to know a little bit more about Qt's Plugin System, especially how it it finds
+ plugins.
+
+ Qt searches for it's plugins in multiple directories, the first one is the plugin folder,
+ \c plugins, which comes with your Qt installation. Within the plugins folder, every plugin type
+ has it's own sub-folder, such as \c platforms, for the platform plugins used to talk to the
+ underlying platform API and the windowing system.
+
+ Similarly, QtInterfaceFramework searches for its backend plugins in the \c interfaceframework folder.
+
+ To make sure our simulation backend ends up in such a folder, we add the following changes in
+ our build system file:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/CMakeLists.txt
+ \skipuntil qt_add_plugin
+ \printuntil set_target_properties
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/backend_simulator.pro
+ \skipto DESTDIR
+ \printuntil DESTDIR
+
+ You might wonder how creating a \c interfaceframework folder in the upper directory solves this problem of
+ finding the plugin as it's not part of the system plugins folder. But Qt supports searching in
+ multiple folders for such plugins and one of those folders is the path to where the executable
+ itself is located.
+
+ Alternatively, we could add an additional plugin path using the QCoreApplication::addLibraryPath()
+ function or using the \c QT_PLUGIN_PATH environment variable. For more information, see
+ \l{https://doc.qt.io/qt-5/plugins-howto.html}{How to create Qt Plugins}.
+
+ Now everything is in place, but because our plugin links against the frontend library, we need
+ to make sure the library can be found by the dynamic linker. This can be achieved by
+ setting the \c LD_LIBRARY_PATH environment variable to our library folder. But this results
+ in the problem, that every user would need to set this variable to be able to use our
+ application.
+
+ \e CMake:
+
+ Using CMake, the location of our frontend library is automatically added as a \e RUNPATH to the
+ the binary and no further steps are needed.
+
+ \e qmake:
+
+ In qmake we can ease the setup by using a relative \e RPATH instead of the \c LD_LIBRARY_PATH
+ and annotate our plugin with the information for the linker, where it might find the needed
+ libraries, relative to the plugin's location:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/backend_simulator/backend_simulator.pro
+ \skipto INCLUDEPATH
+ \printuntil QMAKE_RPATHDIR
+
+ \section2 Export the QML Types in a QML Plugin
+
+ In the first chapter, we extended our \c main.cpp to register all types of our autogenerated
+ Middleware APIs. Although this works fine, in bigger projects it's common to use a QML Plugin
+ instead and be able to use qmlscene for development. Although the code for doing this is
+ not complex, the Interface Framework Generator supports this as well and makes it even easier.
+
+ From the first chapter, we know that the module name is used for the QML import URI. This is
+ important for a QML plugin as the QmlEngine expects the plugin in a specific folder to
+ follow the module name, where every section of the module name is a sub-folder. Our build system
+ file to generate a QML plugin looks like this:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/imports/CMakeLists.txt
+ \skipto qt6_ifcodegen_import_variables
+ \printto install
+
+ Unlike all our previous generator calls we don't extend a previously defined target, but
+ import the generated code into CMake and pass it to the \l {qt_add_qml_module} function.
+ The \l {qt6_ifcoegen_import_variables} function will call the generator and export variables
+ starting with \e CLUSTER as prefix to the current CMake scope.
+ Those variables reference autogenerated code, but also expose other information like the QML
+ import URI.
+ In the next call, the variables are used to define a QML Module with the correct URI and version
+ (as specified in our IDL file). By using the \e OUTPUT_DIRECTORY variable we can make sure that
+ the correct folder structure is generated and we can import the QML plugin directly from within
+ the build folder.
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/imports/imports.pro
+ \printto target.path
+
+ All lines until \c IFCODEGEN_SOURCES should be familiar. We use \c CONFIG to build a plugin, then
+ define the settings for the linker to link against our frontend library. Then, we use
+ \c IFCODEGEN_TEMPLATE to define "qmlplugin" as the generation template. Instead of adding
+ \c ifcodegen to \c CONFIG, this time we use
+ \l{https://doc.qt.io/qt-5/qmake-test-function-reference.html#load-feature}
+ {qmake's load() function} to explicitly load the feature. This enables us to use the \c URI
+ variable which is part of the "qmlplugin" generation template. This URI can be used to define
+ a \c DESTDIR by replacing all dots with slashes.
+
+ In addition to the folder structure, the QmlEngine also needs a \c qmldir file which indicates
+ what files are part of the plugin, and under which URI. For more information, see
+ \l{https://doc.qt.io/qt-5/qtqml-modules-qmldir.html}{Module Definition qmldir Files}. Both this
+ \c qmldir file and a \c plugins.qmltypes file which provides information about code-completion,
+ are autogenerated by the Interface Framework Generator; but they need to be placed next to the library. To do
+ so, we add the files to a scope similar to an \c INSTALL target, but add it to the \c COPIES
+ variable instead. This makes sure that the files are copied when the plugin is built.
+
+ Now the plugin is ready for use, but our Instrument Cluster application doesn't know where to
+ search for it and is still using the old hardcoded registration. So, we can now remove the
+ linking step in the \c instrument-cluster build system file and change our main file
+ accordingly:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter3-simulation-backend/instrument-cluster/main.cpp
+ \skipto #include
+ \printuntil }
+
+ What has changed is that we've now added an additional import path with the \c addImportPath
+ function, which points to the "imports" folder next to the binary's location.
+
+ \target chapter4
+ \section1 Chapter 4: Add a Custom Simulation
+
+ So far, we've created a Middleware API and integrated it into our Instrument Cluster QML code,
+ extended it with a QML plugin, and generated a simulation backend. In the background, quite a
+ lot has happened to support us; but on the UI side not much has changed till now. This chapter
+ is about bringing our simulation backend to life by defining sane default values and starting
+ to simulate a real car ride.
+
+ \section2 Define Default Values
+
+ We start by defining default values for our properties, using annotations in our QFace file.
+ An annotation is a special kind of comment which adds extra data to an interface, method,
+ property, and so on. For this use case we use the \c config_simulator annotation. For more
+ information, see \l{annotations-yaml}{Annotations}.
+
+ Currently, in our Instrument Cluster, the temperatur defaults to 0. Let's change this to a
+ temperature in spring, 15 degrees Celsius, with the following YAML fragment:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter4-simulation-behavior/instrument-cluster.qface
+ \printuntil }
+
+ Compile the plugin again for this temperature change to be reflected in our Instrument Cluster.
+ Let's see how this actually works: when starting the Interface Framework Generator, the config_simulator
+ annotation was transformed into a JSON file that's now part of the "simulation backend" build
+ folder. This JSON file looks like this:
+
+ \quotefile interfaceframework/qface-tutorial/chapter4-simulation-behavior/backend_simulator/instrumentclustermodule.json
+
+ But how is this JSON file related to the actual simulation backend code? The autogenerated
+ simulation backend code uses QIfSimulationEngine, that reads the JSON file and provides its
+ data to a QML simulation file. A default QML file is also autogenerated and loaded from the
+ QIfSimulationEngine. This default QML file provides the behavior of what should happen in the
+ the simulation backend.
+
+ Later, in the next section, we take a look at the QML file and how we can change it. But first,
+ let's see how we can change the default values in a more dynamic way.
+
+ The QIfSimulationEngine allows us to override which JSON file should be loaded into the
+ engine, when we set the \c QTIF_SIMULATION_DATA_OVERRIDE environment variable. Since there can
+ be multiple engines run by different backends, we need to define which engine we're referring
+ to. In the autogenerated code, the module name is always used as the engine specifier. For this
+ chapter, we already prepared a second JSON file which is part of our source directory. Setting
+ the environment variable as follows, changes the \c systemType to mph instead of km/h:
+
+ \badcode
+ QTIF_SIMULATION_DATA_OVERRIDE=instrumentcluster=<path-to-file>/miles.json
+ \endcode
+
+ \section2 Define a QML Behavior
+
+ Before we define our custom behavior, let's see what's been autogenerated for us. There are two
+ QML files: The first is \c instrumentcluster_simulation.qml and rather simple. It defines an
+ entry point that istantiates the second file, an \c InstrumentClusterSimulation.qml file. This
+ split is done as there can be multiple interfaces defined as part of the same module.
+
+ \note A QML Engine can only have one entry point. While QIfSimulationEngine has this same
+ limitation, if you have a module with multiple interfaces, you want to have multiple simulation
+ files -- one per interface. This is why the first QML file merely instantiates the QML files for
+ all interfaces that it supports. In the case of our example, it's only one interface.
+
+ The InstrumentClusterSimulation.qml file is very interesting:
+
+ \quotefile interfaceframework/qface-tutorial/chapter4-simulation-behavior/backend_simulator/InstrumentClusterSimulation.qml
+
+ First, there's a \c settings property, that's initialized with the return value from the
+ \l{IfSimulator::findData}{IfSimulator.findData} method, which takes the
+ \l{IfSimulator::simulationData}{IfSimulator.simulationData} and a string as input. The
+ \c simulationData is the JSON file represented as a JavaScript object.
+
+ The \c findData method helps us to extract only the data that is of interest for this
+ interface, \c InstrumentCluster. The properties that follow help the interface to know whether
+ the default values are set. The \c LoggingCategory is used to identify the log output from this
+ simulation file.
+
+ Afterwards, the actual behavior is defined by instantiating an \c InstrumentClusterBackend Item
+ and extending it with more functions. The \c InstrumentClusterBackend is the interface towards
+ our \c InstrumentCluster QML frontend class. But, apart from the frontend, these properties are
+ also writable to make it possible to change them to provide a useful simulation.
+
+ Each time a frontend instance connects to a backend, the \c initialize() function is called.
+ The same applies to the QML simulation: as the \c initialize() C++ function forwards this to
+ the QML instance. This also applies to all other functions, like setter and getters, for
+ properties or methods. For more details, see \l{QIfSimulationEngine}.
+
+ Inside the QML \c initialize() function, we call \c{IfSimulator.initializeDefault()}, to read
+ the default values from the \c simulationData object and initialize all properties. This is
+ done only \b once, as we don't want the properties be reset to default when the next frontend
+ instance connects to the backend. Lastly, the base implementation is called to make sure that
+ the \c initializationDone signal is sent to the frontend.
+
+ Similarly, a setter function is defined for each property; they use the
+ \c{IfSimulator.checkSettings()} to read specific constraint settings for the property from
+ the \c simulationData and check whether these constraints are valid for the new value. If
+ these constraints aren't valid, then \c{IfSimulator.constraint()} is used to provide a
+ meaningful error message to the user.
+
+ \section2 Define Our Own QML Simulation
+
+ As mentioned above, the \c InstrumentClusterBackend Item does provide all the properties of our
+ QFace file. This can be used to simulate a behavior by changing the properties to the values
+ we want. The simplest form for this would be value assignment, but this would be rather static
+ not exactly what we'd like to achieve. Instead, we use QML Animation objects to change the
+ values over time:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter4-simulation-behavior/backend_simulator/simulation.qml
+ \skipto NumberAnimation
+ \printuntil }
+
+ The code snippet above changes the speed property to 80 over 4000 seconds and simulates an
+ accelerating car. Extending this to the other properties, and combining both sequential and
+ parallel animations, we can create a full simulation:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter4-simulation-behavior/backend_simulator/simulation.qml
+ \skipto property var animation
+ \printuntil property: "fuel"
+ \printuntil property: "fuel"
+ \printuntil }
+ \printuntil }
+
+ Then, to provide a nice simulation for the \c rpm property, we use a binding which does some
+ calculations based on the current speed. The complete simulation file looks like this:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter4-simulation-behavior/backend_simulator/simulation.qml
+ \skipto import
+
+ The next step is to tell the Interface Framework Generator and the QIfSimulationEngine about our new
+ simulation file. Similar to QML files, the best aproach here is to put the simulation file into
+ a resource file. In our example, we add a new file called \c simulation.qrc which contains our
+ \c simulation.qml using the \c{/} prefix.
+
+ In our QFace file, this location now needs to be added in the form of an annotation:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter4-simulation-behavior/instrument-cluster.qface
+ \printuntil module
+ \dots
+
+ Now, rebuilding the simulation backend embeds the simulation file into the plugin and hands the
+ file over to the QIfSimulationEngine, which starts the simulation when loaded.
+
+ \target chapter5
+ \section1 Chapter 5: Add a Simulation Server Combined with QtRemoteObjects
+
+ In this chapter we extend our Instrument Cluster to use an Inter-Process Communication (IPC)
+ mechanism and use two processes. At the moment, the simulation is loaded as a plugin that
+ causes it to be part of the same service. Although this is good enough for a small example
+ application, it's not how it's done in modern multi-process architectures, where multiple
+ processes need to be able to access the same value and react to changes. We could write a
+ second Application that uses the same Middleware API. However, we can achieve the same thing
+ just by starting the Instrument Cluster twice and checking whether the animations are in sync.
+ Currently, they're not.
+
+ \image qface-tutorial-unsync.gif
+
+ \section2 Add a QtRemoteObjects Integration
+
+ The IPC for this example is QtRemoteObjects, because the Interface Framework Generator already supports it
+ out of the box. To use QtRemoteObjects we generate a second plugin, a "production" backend,
+ this time. Production backends are automatically preferred over the simulation backend we
+ introduced before.
+
+ This is done with the following build system files:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter5-ipc/backend_qtro/CMakeLists.txt
+ \skipto qt_add_plugin
+ \printto install
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter5-ipc/backend_qtro/backend_qtro.pro
+ \printto CONFIG += install_ok
+
+ These files are almost identical to the ones we used earlier for our simulation backend.
+ For now we highlight what's changed.
+
+ The name of the plugin doesn't end with "_simulation" to indicate that this is a "production"
+ backend. The template is now changed to "backend_qtro" to generate a backend that uses
+ QtRemoteObjects Replicas to connect to a QtRemoteObjects Source that provides the values. In
+ addition to a QtRemoteObject-based backend, we also need a QtRemoteObject-based server. This
+ part can also be autogenerated using the Interface Framework Generator in a similar fashion:
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter5-ipc/simulation_server/CMakeLists.txt
+ \skipto qt_add_executable
+ \printto # Resources:
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro
+ \printto RESOURCES
+
+ Because we'd like to generate a server binary, the qmake \c TEMPLATE needs to be set to "app"
+ instead of "lib", in CMake we use \l {qt_add_exectuable} instead. Similar to the plugin, the
+ server also needs to link against our library to give it access to the defined enums,
+ structures, and other types. The template we use to generate a simulation server is called
+ "server_qtro_simulator".
+
+ \section2 Reuse the Existing Simulation Behavior
+
+ Now, if you start the server and then the Instrument Cluster, you don't see the simulation
+ from our previous chapter anymore. The reason for this, is that the simulation code is part of
+ our simulation backend, but this backend is no longer used as we added the
+ QtRemoteObjects-based "production" backend.
+
+ Because we used the "server_qtro_simulator" generation template, this can easily be fixed, as
+ the generated server code is also using the QIfSimulationEngine and supports to use the same
+ simulation file than our simulation backend. We just need to extend the project file in the
+ same way as we did before and are also able to use the same resource file for this.
+
+ \e CMake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter5-ipc/simulation_server/CMakeLists.txt
+ \skipto # Resources:
+ \printto install
+
+ \e qmake:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro
+ \skipto RESOURCES
+ \printuntil RESOURCES
+
+ In the same way, we can also use the other simulation data JSON file that we defined in the
+ previous chapter, by using the same environment variable. We just need to pass it to the
+ server instead of our Instrument Cluster application.
+
+ Let's do the final test: starting two Instrument Cluster instances should now show the
+ animations in sync:
+
+ \image qface-tutorial-sync.gif
+
+ \target chapter6
+ \section1 Chapter 6: Develop a Production Backend with D-Bus
+
+ Previously, we extended our Instrument Cluster code by using QtRemoteObjects as IPC and
+ autogenerated a backend for it, as well as a server that provides the simulation. In this
+ chapter, we'd like to write our own backend \b manually using D-Bus as IPC.
+
+ We've already prepared a working D-Bus server which provides limited simulation.
+
+ First, let's look at the server code and see what's done there; then write the backend that
+ connects to it.
+
+ \section2 D-Bus Server
+
+ As mentioned above, we use D-Bus for this chapter and we already have an XML file that
+ describes the D-Bus interface, similar to our QFace file:
+
+ \quotefile interfaceframework/qface-tutorial/chapter6-own-backend/demo_server/instrumentcluster.xml
+
+ This XML file is used to let qmake generate a base class which is extended by the server with
+ actual functionality. For more information, see \l{QtDBus}.
+
+ Our D-Bus server starts on the session bus, on the \c{/} path, and provides an interface named
+ "Example.If.InstrumentCluster". To simulate some values, we keep it simple and use a timer
+ event to change the speed value every 100 milliseconds. Then, we start from 0, once the
+ maximum of 250 is reached. Similarly, the \c rpm value is increased to 5000. For all other
+ properties, we provide hardcoded values.
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter6-own-backend/demo_server/instrumentcluster.cpp
+ \skipto timerEvent
+ \printuntil }
+
+ \section2 Write Our own D-Bus Backend
+
+ Let's start with a build system file for our backend. This is very similar to previous
+ files, but it doesn't use the Interface Framework Generator. Instead, it uses \c DBUS_INTERFACES
+ for qmake to autogenerate some client code which sends and receives messages over D-Bus.
+ In the CMake case the \l {qt6_add_dbus_interface} function is used to do the same.
+
+ Now, we need to define an entry point for our plugin. This plugin class needs to derive from
+ QIfServiceInterface and implement two functions:
+
+ \list
+ \li \c {QStringList interfaces()} -- that returns a list of all interfaces this plugin
+ supports.
+ \li \c {QIfFeatureInterface *interfaceInstance(const QString &interface)} -- that returns
+ an instance of the requested interface.
+ \endlist
+
+ Additionally, we also need to provide a list of interfaces we support as plugin metadata, in
+ the form of a JSON file which looks like this:
+
+ \quotefile interfaceframework/qface-tutorial/chapter6-own-backend/backend_dbus/instrumentcluster_dbus.json
+
+ We need this list, as it gives QtInterfaceFramework the chance to know which interfaces a backend supports,
+ before instantiating it and loading only the plugins which the application code needs.
+
+ Our plugin code looks like this:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter6-own-backend/backend_dbus/instrumentclusterplugin.cpp
+ \skipto #include
+ \printto
+
+ In \c interfaces() we use the IID which is defined in \c{instrumentclusterbackendinterface.h}
+ from our autogenerated library. In \c insterfaceInstance() we check for the correct string and
+ return an instance of the instrument cluster backend we implemented.
+
+ This backend is defined in \c instrumentclusterbackend.h and derives from
+ \c InstrumentClusterBackendInterface. In our \c InstrumentClusterBackend class, we need to
+ implement all pure virtual functions from InstrumentClusterBackendInterface and derived classes.
+
+ For our example, this isn't complex, as we just need to implement the initialize() function.
+ If our XML file would use writable properties or methods, then we'd need to implement those as
+ well. We don't need to implement getters for our properties, because QtInterfaceFramework uses the changed
+ signals during the initialization phase to get information about the current state. Although
+ the generated D-Bus interface class would provide getters to retrieve the properties from our
+ server, it's not recommended to use these when you develop a backend. These getters are
+ implemented by using synchronous calls, which means they will block the event loop until an
+ answer is received by the client. Since this can lead to performance issues, we recommend to
+ use \b asynchronous calls instead.
+
+ In our backend, we define a fetch function for each property that's implemented like this:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter6-own-backend/backend_dbus/instrumentclusterbackend.cpp
+ \skipto ::fetchSpeed
+ \printto ::fetchRpm
+
+ First, we add the property to a list, to know which properties have been fetched successfully.
+ Next, we use the \c asyncCall() function to call the getter for the \c speed property and use a
+ \c QDBusPendingCallWatcher to wait for the result. Once the result is ready, the lambda removes
+ the property again from our \c fetchList, uses the \c onSpeedChanged() function to store the
+ value and notifies the frontend about it. Since we don't need the watcher anymore, we delete it
+ in the next event loop run using \c deleteLater(), and call the \c checkInitDone() function.
+
+ The \c checkInitDone() function is defined as follows:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter6-own-backend/backend_dbus/instrumentclusterbackend.cpp
+ \skipto ::checkInitDone
+ \printto onSpeedChanged
+
+ It ensures that the \c initializationDone() signal is sent to the frontend once all our
+ properties are fetched from the server, and the initialization is complete.
+
+ In addition to retrieving the current state from the server, we also need to inform our frontend
+ every time a property changes. This is done by emitting the corresponding change signal when the
+ server changes one of its properties. To handle this, we define a slot for each property. This
+ slot saves the property in our class an emits the change signal:
+
+ \quotefromfile interfaceframework/qface-tutorial/chapter6-own-backend/backend_dbus/instrumentclusterbackend.cpp
+ \skipto void InstrumentClusterBackend::onSpeedChanged(int speed)
+ \printto onRpmChanged
+
+ The same slot is also used during the initialization phase to save and emit the value.
+
+ You might wonder why saving the value is needed at all, if we can just emit the signal. This is
+ because the backend plugin is used directly by every instance of the \c InstrumentCluster class
+ and every instance calls the \c initialize() function to retrieve the current state. Instead of
+ fetching all properties again, the second \c initialize() call just emits values that were
+ already saved; and the slots keep them up to date.
+
+ Now, when we start the Instrument Cluster, our backend should connect to our D-Bus server and
+ look like this:
+
+ \image qface-tutorial-dbus.gif
+
+*/