1
votes

I made this class to use it as data container. I read from a json some data (in c++) and fill a list of GUIArea that I store in the m_guiAreas list in the dataHandler. At a certain point from QML I request a series of selectedAreas to the dataHandler. DataHandler fill the QList m_selectedGuiAreas and emit the selectedAreasChanged() signal. Now I expect to se a grid of rectangle filled with the selected Datas but I don't see anything. At C++ level, when selectedAreasChanged() is emitted, the m_selectedGuiAreas result filled with right data but at QML level it seems empty or maybe that datas aren't read right way.

Here is thw class I use as wrapper to bring datas to QML level:

class GUIArea : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString id READ id )
        Q_PROPERTY(QString configurations READ configurations )

        ...

    public:
        explicit GUIArea(QObject *parent = nullptr): QObject (parent) {}

        QString id() {return m_id;}
        void id(QString newId) {m_id = newId;}

        QString configurations() {return m_configuration; }
        void configurations(QString newConfiguration) {m_configuration = newConfiguration;}

        ...

    private:
        QString m_id;
        QString m_configuration;
    };

here below is the dataHandler class where I declare the lists of data read from Json and that I convert from Qlist to QQmlPropertyList (I see this in some QML guide for exposing c++ properties to QML). The method initializeDatas read the datas storing them in the m_GUIAreas and then select ones to send to QML in m_selectedGUIAreas, emitting in the end the signal selectedGUIAsChanged().

class dataHandler : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QQmlListProperty<GUIArea> selectedGuiAreas READ selectedGuiAreas NOTIFY selectedAreasChanged)

public:
    explicit dataHandler(QObject *parent = nullptr);
    static dataHandler* instance();

    QQmlListProperty<GUIArea> selectedGuiAreas();
    ...

public slots:
        void initializeDatas(const json& blocksList);
    ... 

signals:
    ...
    void selectedAreasChanged();
    ...
private:   
    ... 
    QList<GUIArea *> m_guiAreas;
    QList<GUIArea *> m_selectedGuiAreas;
};

in the main file then the dataHandler is declared as a property: here is the code:

  QQuickView view;
  ...
  view.engine()->rootContext()->setContextProperty("dataHandler", dataHandler::instance());
  ...
  view.show();

a part of the page I want to visualize in QML is here below. AreaButton is a Rectangle within a Text and a alias of the property text.

Grid {
    id: areasButtonsGrid
    columns: 4
    anchors.fill: parent

    Repeater {
        model: dataHandler.selectedGuiAreas
        delegate:
            AreaButton {
                text: qsTr(model.modelData.programName)
            }
    }
}
1
Did you set the dataHandler as context property? See doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.htmlAmfasis
Show the code where you register dataHandler type.folibis
yes, I registered dataHandler as context property! here is the code: QQuickView view; view.engine()->rootContext()-> setContextProperty("dataHandler",dataHandler::instance());Denis
yes, I did @Amfasis... I also added the code to the question . And also I read the docs at the link you posted without finding a solution to my problem.Denis

1 Answers

0
votes

The code can not be analyzed since it is incomplete so I will just provide a working code so you can analyze where the problem is:

main.cpp

#include <QGuiApplication>
#include <QQmlContext>
#include <QQuickView>
#include <QTimer>

class GUIArea : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString id READ id  CONSTANT)
    Q_PROPERTY(QString configurations READ configurations CONSTANT)
public:
    GUIArea(const QString & id="", const QString & configurations="", QObject *parent=nullptr):
        QObject(parent), m_id(id), m_configurations(configurations)
    {}
    QString id() const{return m_id;}
    QString configurations() const{return m_configurations;}
    void setId(const QString &id){
        m_id = id;
    }
    void setConfigurations(const QString &configurations){
        m_configurations = configurations;
    }
private:
    QString m_id;
    QString m_configurations;
};

class DataHandler: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<GUIArea> selectedGuiAreas READ selectedGuiAreas NOTIFY selectedAreasChanged)
    using QObject::QObject;
public:
    static DataHandler& instance(){
        static DataHandler handler;
        return handler;
    }
    QQmlListProperty<GUIArea> selectedGuiAreas(){
        return QQmlListProperty<GUIArea>(this, m_selectedGuiAreas);
    }
    void append(GUIArea *area){
        if(area){
            m_selectedGuiAreas << area;
            emit selectedAreasChanged();
        }
    }
signals:
    void selectedAreasChanged();
private:
    QList<GUIArea *> m_selectedGuiAreas;
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    qmlRegisterType<GUIArea>();
    QQuickView view;
    view.rootContext()->setContextProperty("dataHandler", &DataHandler::instance());
    view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
    view.show();
    QTimer timer;
    static int counter =0;
    QObject::connect(&timer, &QTimer::timeout, [](){
        GUIArea *area = new GUIArea(QString::number(counter),
                                    QString("configuratio-%1").arg(counter),
                                    &DataHandler::instance());
        DataHandler::instance().append(area);
        counter++;
    });
    timer.start(1000);
    return app.exec();
}
#include "main.moc"

main.qml

import QtQuick 2.12

Grid {
    id: areasButtonsGrid
    columns: 5
    width: 640
    height: 480
    spacing: 20
    Repeater {
        model: dataHandler.selectedGuiAreas
        delegate:
            Rectangle{
            width: 100
            height: 100
            color: "blue"
            Text {
                anchors.fill: parent
                text: qsTr(model.modelData.configurations)
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }
    }
}