Looking for a sample or doc of this pattern in C++ & QML



  • I have an object that is exposed to QML that is written in C++.
    I would like this C++ object to be able to provide a model to QML via a property or method.

    It's not clear to me how to do this because

    • my model is built at runtime so it's dissimilar from the examples where a model is created in main.cpp
    • my model derives from QAbstractTableModel (which disables copy constructors)

    In other words, in C++, it'd be like having a parent method that looks like this...

    @MyModel& buildMyModel();@

    I'm looking for a sample that goes beyond instantiating a fixed model in main.cpp.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    From the top of my head, It should rather be:

    @MyModel* buildMyModel();@



  • Thanks.

    OK, I will explore this.



  • [quote author="m2512" date="1409086186"]
    It's not clear to me how to do this because

    • my model is built at runtime so it's dissimilar from the examples where a model is created in main.cpp
      [/quote]

    You might have more luck interpreting the problem as a model that is created in the source, but is populated at runtime. When the program starts, the model will be empty. As data arrives, it is inserted and any attached views learn of new data via the appropriate signals.



  • That's one way to look at it. However, if you have many models or a deep hierarchy of data models it doesn't seem practical to bootstrap them all upfront.



  • I guess it's not clear to me what the problem is. Is the question how to define the model, how to assign the model to a view, or something else?



  • In simple terms it's how do you expose a model to QML that is the property of another object already exposed to QML considering that objects deriving from QObject typically disable copy constructors and assignment operators. Not to mention you don't want to be copying heavy models anyway. The suggestion is to expose a slot that returns a pointer to a model but I have yet to see any examples like this. I was looking for a sample or doc of a similar pattern.



  • main.cpp:
    @#include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QAbstractListModel>
    #include <QQmlContext>
    #include <QVariant>

    class Model : public QAbstractListModel
    {
    Q_OBJECT
    public:
    Model(QObject *parent = nullptr) : QAbstractListModel(parent) {}
    int rowCount(const QModelIndex &parent) const { return 10; }
    QVariant data(const QModelIndex &index, int role) const { return QString("string %1").arg(index.row()); }
    QHash<int, QByteArray> roleNames() const { return QHash<int, QByteArray> { {Qt::UserRole, "value" } }; }
    };

    class Container : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QVariant model READ getModel CONSTANT)
    public:
    Container(QObject *parent = nullptr) : QObject(parent) {m_model = new Model;}
    QVariant getModel() const { return QVariant::fromValue(m_model); }
    Model *m_model;
    };

    int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    Container container;
    engine.rootContext()->setContextProperty(QLatin1Literal("container"), &container);
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
    return app.exec&#40;&#41;;
    

    }

    #include "main.moc"@

    main.qml:
    @import QtQuick 2.2
    import QtQuick.Window 2.1

    Window {
    visible: true
    width: 360
    height: 360
    ListView {
    anchors.fill: parent
    model: container.model
    delegate: Text {
    text: value
    }
    }
    }@

    Given the stated goal of multiple models, registering a new QML type is probably more appropriate than setting a context property.



  • Excellent! Greatly appreciated - this is what I was looking for :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.