In the last part we’ve created a connection to D-Bus from within Qt-C++ to execute methods to e.g. activate the modem or to register, receive and parse a D-Bus-Signal when an Ofono VoiceCallManager’s property was changed. The aim of this part is to use that C++ implementations from within QML.
How to connect C++ and QML
First of all, there are two ways to achieve a connection between those two parts. You can compile your C++ code as a library and import it into your QML file which is run in the Qmlviewer application. But here we want to go another way and load our QML files into our existing C++ application and show it there as our main UI.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDeclarativeView view;
view.setSource(QUrl::fromLocalFile(":qml/mobos-gui.qml"));
view.setSceneRect(0, 0, 240, 320);
view.show();
return a.exec();
}
The listing shows how few lines of code are enough to load and show a QML file in a Qt C++ application. In the beginning of QML it was much more complicated with a lot of QtDeclarative classes and casts and so on, but that’s gone. Just create a QDeclarativeView, set the source and show it.
The loaded QML file might look like this. It’s just an example. Most of those buttons are without functionality. Now we want to connect the “ON”-Button with the setPowerOn() method from part 2.
Use C++ Methods in QML
The setPowerOn() method in the class Ofono must be either a public slot, or marked as “invokable”. Let’s use the latter way:
public:
/**
* Set the oFono "powered" property to "true"
*/
Q_INVOKABLE void setPowerOn();
Now we need to push this to our QML part. For that we add the following line to our simple example from above (main()), e.g. immediately after the View is created:
...
view.rootContext()->setContextProperty("OfonoContext", new Ofono());
...
We create a new instance of our Ofono-Class and push it to the QML part where it shall have the name “OfonoContext“.
Last but not least, we have to use the method in QML. Use any of your defined buttons’ click event to execute the method:
...
onClicked: { OfonoContext.setPowerOn() }
...
That’s it. Implement the same for an “OFF”-Button and you can activate and deactivate the Phonesim modem (or any other Ofono modem) with QML.
How to connect Signals
The next step is to receive a signal e.g. from the PropertyChanged-Slot we’ve implemented in part 2.
... emit callChanged(opath.path()); ...
The signal callChanged is emitted with the object path of the phone call. To receive this signal in QML we can also use the already pushed Context-Object OfonoContext.
Item {
...
Connections {
target: OfonoContext
onCallChanged: {
console.log("QML: Changed call: " + id);
}
}
...
}
With the Connections-Element Signals from the C++ part can be used. The target is the name of the Context-Object we’ve assigned above with setContextProperty(). The signal’s name is automatically changed to the typical QML style with “on” and then a capitalized letter. In this example the given String is just printed to the console. The name – which is id here – is the same you use in the C++ part.
Conclusion
In three parts everything from installing Ofono and the GSM-Modem simulator Phonesim, over the C++ Qt part to connect to Ofono through D-Bus, to the UI in QML and how to use the Ofono-Services from there, has been described.
I hope I didn’t forget any important part. It’s as short and simple – but hopefully complete – as possible. Have fun implementing applications using Ofono and QML.
