QML: C++ classes with “bring your own component”

I’m trying to develop a Qt C++ application, with a QML frontend, but I hit a roadblock.

This is what I have so far:

  • A Factory class that outputs a choice of objects. These objects, that I’m going to call “controllers”, control different pieces of hardware.
    • The Factory would be exposed to the QML layer with setContextProperty.
    • The controller would be chosen basically with a combo box controlling the factory.

Now, for the tricky bit. I want that the “controllers” behave in a “bring your own component” way. This means that they would have a method returning the respective QML file for their controller. That shouldn’t be to hard to do, it’s basically biding a Loader to a method of the Factory/Manager saying the file with the component to load into a placeholder.

But the problem is: how can this newly created component and this newly created controller know and talk to each other? This is something I did before with QWidgets, just having pointers between the classes. Quite trivial.

I tried an architecture like this before for QWidgets, but seems to not be ideal for QML.

I made this drawing of what I would ultimately like to happen: ArchIdea

This architecture allows for a very trivial plugin system (at least in the QWidgets world) and I would very much like to keep that. Not a massive singleton and account for every possible action…

I’d appreciate ideas!

Answer

The Loader setSource method have additional parameter you could pass to provide initial value for some property. Something like this:

ComboBox {
   model: controlerFactory.specificHWListModel
   onCurrentTextChanged: {
       var specificHWControler = controlerFactory.getObjectFor( currentText );
       loader1.setSource( 
           specificHWControler.qml_file,
           { "controler": specificHWControler }
       );
   }
}
Loader { 
    id: loader1
}

The specificHWListModel cold be QStringList or some custom QAbstractListModel. And getObjectForcould be just a invokable function.

Q_INVOKABLE QObject* getObjectFor(QString hwName);

The object returned from Q_INVOKABLE function will be managed by QQmlEngine by default if you don’t set by the QQmlEngine::setObjectOwnership. Remember to register your SpecificHWControler class to QQmlEngine.

The qml_file SpecificView.ui.qml, should have property controler, and could be edited with Designer:

import SpecificHWControlerModule 1.0
Item {
    property SpecificHWControler controler

}

https://doc.qt.io/qtcreator/quick-connections-backend.html

Leave a Reply

Your email address will not be published. Required fields are marked *