Qt Interface Framework Generator Addressbook Example
This example shows how to generate models using the Qt Interface Framework Generator.
Introduction
This example shows how to generate a model using the model type in a qface file with the Qt Interface Framework Generator.
It will only explain the details on how to use the model type and how it works internally. For a general introduction to the Qt Interface Framework Generator, please have a look at the Qt Interface Framework Generator Climate Example.
Walkthrough
The Interface Definition Language (IDL) file used in the example represents an address book API. It contains a single interface providing the contacts as a model and a struct
definition for the actual contact.
interface AddressBook { model<Contact> contacts; void insertContact(int index, Contact contact); } struct Contact { string forename; string name; int phone; }
The contact property is defined to be of type model<Contact>. The frontend template will create a C++ property of type QIfPagingModel*. The getter function of this property returns a valid instance once a back end 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 Pagination concept.
For the back end interface the property type is different and will be a QIfPagingModelInterface pointer. This is needed as the QIfPagingModel is also a QtInterfaceFramework feature and, like all features, it uses a back end interface for the front end-back end separation. For more information, see Concepts and Architecture.
The back end plugin needs to implement the QIfPagingModelInterface class for every exposed property. The backend_simulator template already takes care of this and generates all the needed code.
Configuring the Simulation Back End Plugin
By default the generated simulation back end does not populate any data for the model, as the template doesn't know what content it should provide.
For this use-case the default annotation can be used to configure the simulator to provide static simulation data.
This is done in the example-addressbook.yaml file:
Example.If.AddressBookModule: config_simulator: simulationFile: "qrc:/plugin_resource/simulation.qml" Example.If.AddressBookModule.AddressBook#contacts: config_simulator: default: [[ "John", "Doe", "12345" ], [ "Jane", "Doe", "67890" ]]
The JSON fragment assigned to the default variable is parsed by the Qt Interface Framework Generator and will be used to generate a simulation back end which creates two Contact instances and returns them as content for the contacts model.
Demo Application
The demo application is not autogenerated, but a standard QQmlEngine setup for an application similar to other examples.
ListView { Layout.fillWidth: true Layout.fillHeight: true model: addressBook.contacts clip: true delegate: ItemDelegate { width: parent.width height: 100 text: model.item.forename + " " + model.item.name } }
The model is retrieved from the addressbook object using the contacts property and passed to the ListView. The delegate can access the actual contact using the ItemRole of the QIfPagingModel, which is exposed to QML through model.item.
Extended Simulation Behavior
Because the 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 simulationFile annotation to tell the autogenerator we want to provide our own simulation QML file.
In the example the simulationFile annotation points to a QML file in a resource file. The resource file is added to the build system like this.
CMake:
set(plugin_resource_resource_files "simulation.qml" ) qt_add_resources(addressbook_backend_simulator "plugin_resource" PREFIX "/plugin_resource" FILES ${plugin_resource_resource_files} )
qmake:
RESOURCES += plugin_resource.qrc
Providing the simulation behavior in QML
The auto-generated simulation back end code loads the simulation behavior from a QML file using a QIfSimulationEngine. This special engine makes sure the auto-generated back end 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 back end, the simulation interfaces are provided in the example.if.addressbook.simulation uri. The provided types are named after the back end interfaces implemented by the simulation back end. For our example two types are registered:
- AddressBookBackend
- ContactsModelBackend
Our simulation QML file looks like this:
import QtQuick import Example.If.AddressBookModule.simulation Item { AddressBookBackend { id: backend property var settings : IfSimulator.findData(IfSimulator.simulationData, "AddressBook") function initialize() { print("AddressBookSimulation INITIALIZE") IfSimulator.initializeDefault(settings, backend) Base.initialize() } function insertContact(reply, index, contact) { print("BACKEND SIMULATION INSERT CONTACT") contacts.insert(index, contact); reply.setSuccess(true); } Component.onCompleted: { console.log("BACKEND SIMULATION CREATED") } } }
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 front end 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 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 insert()
function and let the auto-generated implementation do the rest.
© 2021 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.