Troubles passing a list<> from Qml to C++



  • I've got a Qml item I've defined (call it MyItem) and in Qml I'm constructing lists of these guys:
    @property list<MyItem> items: [
    MyItem { id: fred },
    MyItem { id: george }
    ]@

    Then I've got a C++ class that looks something like this:
    @class MyInfo : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QVariant stuff READ getStuff WRITE setStuff NOTIFY stuffChanged)
    ...
    void setStuff(QVariant stuff)
    {
    m_var = stuff;
    m_list = m_var.value<QQmlListReference>();
    }

    QVariant m_var;
    QQmlListReference m_list;
    }@

    When I say (in Qml)
    @theInfo.stuff = items@

    everything works fine - my C++ code gets the list of MyItem objects and can process them as I need.

    The problem comes when I change to a new set of items:
    @theInfo.stuff = differentItems@

    When the C++ code sets m_list to the new QQmlList, it destructs all of the objects in the old list. My Qml code clearly shows that "items" is now empty.

    How can I, in my C++ code, view the list of MyItem objects created in Qml, without destroying them when I'm done with them?

    Thanks,
    Chris



  • Hi,

    I cannot reproduce your issue, using Qt 5.3
    Here is my code:

    listprop.pro:
    @
    QT += qml quick
    SOURCES += main.cpp
    HEADERS += ListPropTest.h
    FILES += test.qml
    TARGET=listprop
    @

    ListPropTest.h:
    @
    #ifndef LISTPROPTEST_H
    #define LISTPROPTEST_H
    #include <QObject>
    #include <QVariant>
    #include <QQmlListReference>
    #include <QtDebug>

    class ListPropTest : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QVariant listRef READ listRef WRITE setListRef NOTIFY listRefChanged)

    public:
    ListPropTest(QObject *parent = 0) : QObject(parent) {}

    Q_INVOKABLE void doTest(const QVariant &listprop) {
        m_listref = listprop.value<QQmlListReference>();
        for (int i = m_listref.count() - 1; i >= 0; --i) {
            qDebug() << "CPP: new list: " << m_listref.at(i);
        }
        emit listRefChanged();
    }
    
    QVariant listRef() const {
        return QVariant::fromValue<QQmlListReference>(m_listref);
    }
    void setListRef(const QVariant &listprop) {
        doTest(listprop);
    }
    

    Q_SIGNALS:
    void listRefChanged();

    private:
    QQmlListReference m_listref;
    };
    #endif
    @

    main.cpp:
    @
    #include <QtGui/QGuiApplication>
    #include <QQmlContext>
    #include <QQmlEngine>
    #include <QQuickView>
    #include <qqml.h>
    #include <QtDebug>

    #include "ListPropTest.h"

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

    QQuickView viewer;
    ListPropTest test;
    viewer.engine()->rootContext()->setContextProperty("listPropTest", &test);
    viewer.setSource(QStringLiteral("test.qml"));
    viewer.show();
    return app.exec();
    

    }
    @

    test.qml
    @
    import QtQuick 2.0

    Item {
    id: root

    property list<QtObject> objectsA: [
        QtObject { id: aOne; objectName: "aOne" },
        QtObject { id: aTwo; objectName: "aTwo" }
    ]
    
    property list<QtObject> objectsB: [
        QtObject { id: bOne; objectName: "bOne" },
        QtObject { id: bTwo; objectName: "bTwo" }
    ]
    
    onObjectsAChanged: {
        console.log("ObjectsA Changed!")
        for (var a in objectsA) {
            console.log(objectsA[a])
        }
    }
    
    onObjectsBChanged: {
        console.log("ObjectsB Changed!")
        for (var b in objectsB) {
            console.log(objectsB[b])
        }
    }
    
    Timer {
        running: true
        interval: 2000
        repeat: true
        property int triggerCount: 0
        onTriggered: {
            triggerCount++
            if (triggerCount == 1) {
                listPropTest.listRef = objectsA //or: listPropTest.doTest(objectsA)
            } else if (triggerCount == 2) {
                listPropTest.listRef = objectsB //or: listPropTest.doTest(objectsB)
    
                // check that objectsA is still valid, not cleared
                for (var a in objectsA) console.log("QML: old list: " + objectsA[a])
            } else {
                // ensure that there was no delete-later style delayed deletion
                for (var a in objectsA) console.log("QML: old list: " + objectsA[a])
                repeat = false; running = false;
            }
        }
    }
    

    }
    @

    After running for 6 seconds, the objects in the objectsA list remain valid and not deleted. Perhaps the object which you reference the list property from somehow goes out of scope or otherwise gets deleted, rendering the list property invalid?

    Cheers,
    Chris.


Log in to reply
 

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