2017-08-03 2 views
0

Est-il possible de créer un ObjectModel à partir de C++ lors de l'exécution?Création d'ObjectModel à partir de C++ à l'exécution

J'ai une application à base de plug-in, où chaque plug-in créer un QQmlComponent et la configuration du signal et des fentes, puis donner le composant à l'application principale pour le rendu dans un ListView, pour cette fin, je veux avoir un ObjectModel dans le C++ côté et le manipuler là.

main.qml (interface principale de l'application):

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 
     } 
    } 

} 

élément 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 
     } 
    } 
} 

Au premier essai, je voulais accéder à l'élément MainArea de C++ côté et appeler la fonction addReport avec QQuickItem * retourné d'un plugin, sans chance.

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", &notificationModel); 

    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(); 
} 

interface plug-in 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) 

Main app screenshoot

+0

Alors comment est défini ObjectModel? D'où vient-il exactement? – dtech

+0

il vient de la [bibliothèque Qt] (http://doc.qt.io/qt-5/qml-qtqml-models-objectmodel.html) c'est un modèle standard qui rend ses objets. et dans mon cas je veux rendre quelques qquickitems qui sont émis à partir des plugins de l'application. –

+0

Je veux dire que c'est dans le plugin, n'est-ce pas? Pourquoi utilisez-vous une bibliothèque régulière? Il y a le 'QQmlExtensionPlugin 'dédié qui, comme son nom l'indique, est spécialement pour QML. – dtech

Répondre

1

It is possible to create any QML object from C++, bien que 99,99% des cas, il est une mauvaise pratique que vous ne devriez pas être faire, et une indication de mauvais design qui reviendra très probablement à vous mordre plus tard. Vous ne devez pas créer ou manipuler des objets QML à partir de C++, vous devez avoir une interface C++ bien définie qui est exposée à QML pour que les objets QML puissent interagir avec lui. Quoi que ce soit que vous ayez l'intention de faire, il y a très probablement une meilleure façon de le faire. Montrez-nous du code afin que nous puissions vous donner une réponse plus spécifique.

+0

J'ai édité le texte et ajouté du code, j'espère que cela aidera à voir clairement le problème. –