Reputation: 749
Is it possible to create an ObjectModel from c++ at runtime?
I have a plugin based application, where every plugin create a QQmlComponent
and setup the signal and slots then give the component to the main app for rendering in a ListView
, for this end I want to have a ObjectModel
in the c++ side and manipulate it there.
main.qml (main app interface):
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
ApplicationWindow {
id: qmlMainWindow
width: 1240
height: 720
minimumWidth: 270+600
minimumHeight: 120+400
visibility: "Maximized"
visible: true
title: "CTC - Tableau de bord"
GridLayout {
anchors.fill: parent
columnSpacing: 0
rowSpacing: 0
columns: 2
rows: 2
HeaderArea {
id: headerArea
Layout.row: 0
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: 120
Layout.maximumHeight: 120
}
NotificationArea {
id: notificationArea
Layout.row: 1
Layout.column: 1
Layout.fillHeight: true
Layout.maximumWidth: 350
Layout.preferredWidth: 300
Layout.minimumWidth: 270
model: notificationModel
}
MainArea {
id: mainArea
bgColor: "lightgray"
Layout.row: 1
Layout.column: 0
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
MainArea item:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQml.Models 2.1
Item {
objectName: "mainArea"
function addReport(obj) {
omodel.append(obj);
}
property alias bgColor: mainAreaBackground.color
property ObjectModel omodel
Rectangle {
id: mainAreaBackground
anchors.fill: parent
color: "white"
ListView {
anchors.fill: parent
model: omodel
}
}
}
At first attempt I wanted to access the MainArea item from c++ side and call the addReport function with QQuickItem* returned from a plugin, without luck.
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
#include <QtPlugin>
#include <QPluginLoader>
#include <QDebug>
#include <QtQmlModel>
#include "notificationmodel.h" // model used in the notification area
#include "interfaces/inotification.h" // interface for a plugin
#include "interfaces/ireport.h" // interface for a plugin (of interest for this post)
int main(int argc, char *argv[])
{
QGuiApplication::setApplicationName("ctc_dashboard");
QGuiApplication::setOrganizationName("CTC");
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication a(argc, argv);
NotificationModel notificationModel(&a);
QQmlApplicationEngine engine;
QPluginLoader ploader; // I load the plugin which his task is to connect
// to a QtRemoteObject on some server and create a QQuickItem
// which will present some statistics.
ploader.setFileName("plugins/affair_states/AffairStates.dll");
engine.rootContext()->setContextProperty("notificationModel", ¬ificationModel);
engine.load(QString("%1/%2")
.arg(QGuiApplication::applicationDirPath())
.arg("qml/main.qml"));
if (engine.rootObjects().isEmpty())
return -1;
if(ploader.load()){
IReports* plugin = qobject_cast<IReports*>(ploader.instance());
if(plugin) {
qDebug() << "Good plugin : " << plugin->name();
QObject::connect(plugin, &IReports::notify, [&](NotificationModel::Notification n){
notificationModel.addNotification(n);
});
QObject::connect(plugin, &IReports::newReport, [&](QQuickItem* i){
qInfo() << "Signal recived";
qDebug() << "New report " << i;
qInfo() << engine.rootContext()->contextObject()->findChild<QObject*>("mainArea");
qInfo() << "Omodel " << engine.rootContext()->contextProperty("omodel");
});
}
}
return a.exec();
}
IReport plugin interface :
#include <QtPlugin>
#include "inotification.h"
#include <QQuickItem>
class IReports: public INotification
{
Q_OBJECT
public:
IReports();
virtual ~IReports();
virtual QList<QQuickItem*> reports() = 0;
virtual QString name() const = 0;
virtual QString sectionName() const = 0;
signals:
void newReport(QQuickItem* report);
};
#define IReports_iid "dz.ctc.dashboard.interfaces.IReports"
Q_DECLARE_INTERFACE(IReports, IReports_iid)
Upvotes: 0
Views: 557
Reputation: 49329
It is possible to create any QML object from C++, although it 99.99% of the cases it is bad practice that you shouldn't be doing, and an indication of wrong design that will most likely come back to bite you later on.
You should not create or manipulate QML objects from C++, what you should have is a well defined C++ interface that is exposed to QML so that QML objects can interact with it.
Whatever it is that you intend on doing, there is most likely a better way to do it. Show us some code so we can give you a more specific answer.
Upvotes: 1