Создать ObjectModel из C++ во время выполнения
Можно ли создать ObjectModel из C++ во время выполнения?
У меня есть приложение на основе плагинов, где каждый плагин создает QQmlComponent
и настроить сигнал и слоты, а затем дать компонент для основного приложения для рендеринга в ListView
для этого я хочу иметь ObjectModel
в сторону C++ и манипулировать им там.
main.qml (основной интерфейс приложения):
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:
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
}
}
}
С первой попытки я хотел получить доступ к элементу MainArea со стороны C++ и вызвать функцию addReport с помощью QQuickItem*, возвращаемого из плагина, но не повезло.
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:
#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)
1 ответ
Можно создать любой объект QML из C++, хотя в 99,99% случаев это плохая практика, которую вам не следует делать, и указание на неправильный дизайн, который, скорее всего, вернется к вам позже.
Вы не должны создавать или манипулировать объектами QML из C++, у вас должен быть четко определенный интерфейс C++, который доступен для QML, чтобы объекты QML могли взаимодействовать с ним.
Что бы вы ни собирались делать, скорее всего, есть лучший способ сделать это. Покажите нам код, чтобы мы могли дать вам более конкретный ответ.