Quantcast
Channel: Active questions tagged qtquick2 - Stack Overflow
Viewing all articles
Browse latest Browse all 107

QML ListView delegate that works for both QML and C++ models

$
0
0

I'm asking this question after getting some insights on my first question on displaying C++ backend model in QML.

I am new to Qt6 and QML, and I think I understood how to link models to delegates in QML, but maybe I missed something...

I would like to have a QML ListView delegate that works for both a QML list model and a C++ list model.
This requirement is needed to be able to have the designers to work in Qt Design Studio with a QML model mockup, to have a C++ mockup for unit tests, and to have the real C++ model loaded from the backend.

However, QML and C++ models seem to be accessed differently in the QML ListView delegate:

  • C++ model item properties are accessed through modelData.propertyName
  • QML model item properties are accessed through required propertyName (for an existing property in the delegate)

My question: is there an unified way to access properties for both C++ and QML models?

Here is a minimal working example to demonstrate my issue (see Main.qml for the difference between QML and C++ access):

backend.h

#ifndef BACKEND_H#define BACKEND_H#include <QObject>// Contains the data I want to display for each elementclass Item : public QObject{    Q_OBJECT    Q_PROPERTY(QString name MEMBER m_name NOTIFY onNameChanged)public:    Item(QString name, QObject *parent = nullptr)        : QObject{parent}, m_name(name)    {}signals:    void onNameChanged();private:    QString m_name {"NULL"};};// This class contains the model to display in the ListView.// The data will be loaded before loading the QML file.class Backend : public QObject{    Q_OBJECT    Q_PROPERTY(QList<Item*> model MEMBER m_model NOTIFY onModelChanged)public:    explicit Backend(QObject *parent = nullptr)        : QObject{parent}    {        m_model.append(new Item {"Cpp"});        m_model.append(new Item {"backend"});        m_model.append(new Item {"is"});        m_model.append(new Item {"great!"});    }    virtual ~Backend() override    {        for (Item* item : m_model)            delete item;    }signals:    void onModelChanged();private:    QList<Item*> m_model;};#endif // BACKEND_H

main.cpp

#include <QGuiApplication>#include <QQmlApplicationEngine>#include <QQMLContext>#include "backend.h"int main(int argc, char *argv[]){    QGuiApplication app(argc, argv);    QQmlApplicationEngine engine;    // Exposing the backend to QML with the name "cppBackend"    Backend backend;    engine.rootContext()->setContextProperty("cppBackend", &backend);    const QUrl url(u"qrc:/TestBackend/Main.qml"_qs);    QObject::connect(&engine,&QQmlApplicationEngine::objectCreationFailed,&app,        []() { QCoreApplication::exit(-1); },        Qt::QueuedConnection);    engine.load(url);    return app.exec();}

MyListItem.qml

import QtQuickItem {    id: myItem    property string name: "Default Name"    width: label.width    height: label.height    Text {        id: label        text: myItem.name        font.pointSize: 24    }}

Main.qml

import QtQuickWindow {    width: 640    height: 480    visible: true    title: qsTr("Hello World")    ListModel {        id: mockupList        ListElement { name: "Hello" }        ListElement { name: "World!" }        ListElement { name: "How" }        ListElement { name: "are" }        ListElement { name: "you?" }    }    ListView {        id: listView        anchors.fill: parent        anchors.margins: 20        spacing: 10        orientation: ListView.Vertical        model: mockupList // Works only with 'required name'        //model: cppBackend.model // Works only with 'name: modelData.name'        delegate: MyListItem {            required name // Works only with QML list model            //name: modelData.name // Works only with C++ list model        }    }}

Here are the results I get when commenting in/out the model and name lines in the Main.qml file:

  • mockupList with required name: QML model items are properly displayed
  • mockupList with name: modelData.name: all items show the default name in MyListItem.qml
  • cppBackend.model with required name: No item was created and throws the warning Required property name was not initialized
  • cppBackend.model with name: modelData.name: C++ model items are properly displayed

Viewing all articles
Browse latest Browse all 107

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>