是否可以在运行时从 c++ 创建 ObjectModel?
我有一个基于插件的应用程序,每个插件创建一个QQmlComponent
并设置信号和插槽,然后将组件提供给主应用程序以在 a 中呈现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
}
}
}
主要区域项目:
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
}
}
}
第一次尝试时,我想从 c++ 端访问 MainArea 项,并使用从插件返回的 QQuickItem* 调用 addReport 函数,但没有运气。
主.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)