Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to edit QQmlListProperty in QML

Tags:

c++

qt

qobject

qml

If we want to use a list of custom C++ objects in QML we can use QQmlListProperty

While registering it in QML we need to specify a function that QML will read the list with.

The documentation states that for fully functional list we need to use this function:

QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append,
                                   CountFunction count, AtFunction at, ClearFunction clear)

Here is example of how do I write it in C++:

classwithlist.h

#ifndef CLASSWITHLIST_H
#define CLASSWITHLIST_H

#include <QObject>
#include <QQmlListProperty>
#include "element.h"

class Element;

class ClassWithList : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Element> elements  READ getElements  NOTIFY elementsChanged)


public:
    explicit ClassWithList(QObject *parent = 0);

    QQmlListProperty<Element> getElements();
    void appendElements(QQmlListProperty<Element> *list, Element *e);
    static int elementsCount(QQmlListProperty<Element> *list);
    static Element* elementsAt(QQmlListProperty<Element> *list, int i);
    static void elementsClear(QQmlListProperty<Element> *list);

signals:
    void elementsChanged(QQmlListProperty<Element>);

private:
    QList<Element *> m_elements;

};

#endif // CLASSWITHLIST_H

classwithlist.cpp

#include "classwithlist.h"

ClassWithList::ClassWithList(QObject *parent) : QObject(parent)
{

}

QQmlListProperty<Element> ClassWithList::getElements()
{
    return QQmlListProperty<Element>(this, m_elements, &appendElements,&elementsCount,&elementsAt,&elementsClear);
}
void ClassWithList::appendElements(QQmlListProperty<Element> *list, Element *e)
{
    ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
    if (cwl && e) {
        cwl->m_elements.append(e);
    }
}
int ClassWithList::elementsCount(QQmlListProperty<Element> *list)
{
    ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
    if (cwl)
        return cwl->m_elements.count();
    return 0;
}
Element *ClassWithList::elementsAt(QQmlListProperty<Element> *list, int i)
{
    ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
    if (cwl)
        return cwl->m_elements.at(i);
    return 0;
}
void ClassWithList::elementsClear(QQmlListProperty<Element> *list)
{
    ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
    if (cwl) {
        cwl->m_elements.clear();
    }
}

And after exposing the class to QML I have following code in QML

ClassWithList {
    Component.onCompleted: {
        console.log(elements.length) // works
        console.log(elements[0])     // works

//        elements.push()      // does not work
//        elements.append()    // does not work
//        elements.clear()     // does not work
//        elements.at()        // does not work
    }
}

Can I use functions that will add items to the list or clear it? As seen above I can use functions CountFunction and AtFunction by using .length and brackets. Can I somehow use ClearFunction and AppendFunction too?

Maybe I cannot do this with QQmlListProperty and I should use QAbstractListModel?

like image 440
Filip Hazubski Avatar asked Mar 12 '23 06:03

Filip Hazubski


1 Answers

EDIT: Due to changes in the list property interface, the answer below is no longer completly true. It is now possible to append objects by using push (from the documentation linked below):

Values can be dynamically added to the list by using the push method, as if it were a JavaScript Array

Original answer below


You cannot append elements to or clear a QQmlListProperty directly in QML. To edit QQmlListProperty in QML, assign a new list to it.

According to QML list documentation:

Any QQmlListProperty value passed into QML from C++ is automatically converted into a list value, and vice-versa.

Note that objects cannot be individually added to or removed from the list once created; to modify the contents of a list, it must be reassigned to a new list.

like image 81
mcchu Avatar answered Mar 27 '23 13:03

mcchu