1
votes

I have a list of QObjects acting as a qml model for ListView. I can change their properties alright, but can't invoke any slots or Q_INVOKABLE methods. This is the minimal example for my issue (sad that it's still quite large).

Define a really simple class with a property and an invokable method


    // DummyObject.h

    class DummyElem : public QObject
    {
        Q_OBJECT

        Q_PROPERTY(QString dummy READ getDummy CONSTANT)
    public:
        explicit DummyElem(QObject *parent = nullptr);

        QString getDummy();
        Q_INVOKABLE void notifyStuff();
    };
Implement trivial methods of this simple class
    // DummyObject.cpp

    #include "DummyElem.h"
    #include <QDebug>

    DummyElem::DummyElem(QObject *parent) : QObject(parent) {}

    QString DummyElem::getDummy() {return "lorem";}
    void DummyElem::notifyStuff() {qDebug() << "ipsum";}
Start a qml app with the list as a root property. Exactly copy-pasted from a tutorial, the one they called q_incokable methods in.
    // main.cpp

    #include "DummyElem.h"

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

        QGuiApplication app(argc, argv);

        QList<QObject*> dataList;
        dataList.append(new DummyElem);
        dataList.append(new DummyElem);

        QQmlApplicationEngine engine;
        QQmlContext* context = engine.rootContext();
        context->setContextProperty("dataModel", QVariant::fromValue(dataList));

        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

        return app.exec();
    }

Describe a qml layout with a ListView and a delegate that will invoke a c++ method when clicked.
    // main.qml

    import QtQuick 2.7
    import QtQuick.Window 2.2

    Window {
        visible: true

        ListView {
            anchors.fill: parent
            model: dataModel
            delegate: Component {
                Text {
                    text: model.dummy

                    MouseArea {
                        anchors.fill: parent
                        onClicked: {model.notifyStuff()}
                    }
                }
            }
        }
    }

The issue is hard to debug as a c++ class model can't be json-strigified, nor can i get its javascript entries(). The error i get is "undefined is not a function" which is cool too. I tried registering the Qt type in QML, but that didn't do anything either.

I'm using Qt libraries version 5.9.4, but the "minimal qt version required" box in QtCreator is set to "Qt 5.6".

1
That should be onClicked: {model.dummy.notifyStuff()} ? Your list has no function "notifyStuff"... is this a copy and paste error?Mailerdaimon
@Mailerdaimon the dummy is a string property, I don't see how that would make sense?Amfasis
Ohh.. you are right. Sorry for that I need a Coffee.Mailerdaimon

1 Answers

2
votes

You need to use modelData. I'm not entirely sure why, most probably because of the QVariantList. You can read a bit more on this page.

Window {
    visible: true

    ListView {
        anchors.fill: parent
        model: dataModel
        delegate: Component {
            Text {
                text: modelData.dummy

                MouseArea {
                    anchors.fill: parent
                    onClicked: modelData.notifyStuff();
                }
            }
        }
    }
}

Fun fact: this is the error I get on Qt 5.11.3:

TypeError: Property 'notifyStuff' of object QQmlDMObjectData(0x5585fe567650) is not a function

At least a bit more telling than undefined, but still not fully descriptive I'd say.