Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QQmlListProperty is deprecated, but how to migrate?



  • I have a project that extending QML using C++ which is using QQmlListProperty for default property. But from Qt 5.15 it complains deprecated warning.
    This is a minimal reproducing refer to this example. My project is very similar.

    // person.h
    #ifndef PERSON_H
    #define PERSON_H
    
    #include <QObject>
    
    class Person : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    public:
        explicit Person(QObject *parent = nullptr);
    
        QString name() const;
        void setName(const QString& name);
    
    signals:
        void nameChanged(QString name);
    
    private:
        QString m_name;
    };
    
    #endif // PERSON_H
    
    // person.cpp
    #include "person.h"
    
    Person::Person(QObject *parent) : QObject(parent)
    {
    
    }
    
    QString Person::name() const
    {
        return this->m_name;
    }
    
    void Person::setName(const QString &name)
    {
        if (this->m_name != name) {
            this->m_name = name;
    
            emit this->nameChanged(name);
        }
    }
    
    // birthdayparty.h
    #ifndef BIRTHDAYPARTY_H
    #define BIRTHDAYPARTY_H
    
    #include <QObject>
    
    #include <QQmlListProperty>
    
    #include "person.h"
    
    class BirthdayParty : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(Person* host READ host WRITE setHost)
        Q_PROPERTY(QQmlListProperty<Person> guests READ guests)
        Q_CLASSINFO("DefaultProperty", "guests")
    //    QML_ELEMENT
    public:
        BirthdayParty(QObject *parent = nullptr);
    
        Person* host() const;
        void setHost(Person *host);
    
        QQmlListProperty<Person> guests();
        int guestCount() const;
        Person* guest(int) const;
    
    private:
        Person *m_host;
        QList<Person*> m_guests;
    };
    
    #endif // BIRTHDAYPARTY_H
    
    // birthdayparty.cpp
    #include "birthdayparty.h"
    
    BirthdayParty::BirthdayParty(QObject *parent) : QObject(parent)
    {
    
    }
    
    Person* BirthdayParty::host() const
    {
        return this->m_host;
    }
    
    void BirthdayParty::setHost(Person *host)
    {
        this->m_host = host;
    }
    
    QQmlListProperty<Person> BirthdayParty::guests()
    {
        return QQmlListProperty<Person>(this, this->m_guests);
    }
    
    int BirthdayParty::guestCount() const
    {
        return this->m_guests.length();
    }
    
    Person* BirthdayParty::guest(int i) const
    {
        return this->m_guests[i];
    }
    
    // main.cpp
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include "person.h"
    #include "birthdayparty.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
    
        qmlRegisterType<Person>("ExtendingExample", 1, 0, "Person");
        qmlRegisterType<BirthdayParty>("ExtendingExample", 1, 0, "BirthdayParty");
    
        engine.load(url);
    
        return app.exec();
    }
    

    and using in QML

    // main.qml
    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    import ExtendingExample 1.0
    
    Window {
      visible: true
      width: 640
      height: 480
      title: qsTr("Hello World")
    
      BirthdayParty {
        host: Person {
          name: "John Doe"
        }
    
        Person {
          name: "Jane Doe"
        }
        Person {
          name: "Mary Smith"
        }
        Person {
          name: "Robert Brown"
        }
      }
    }
    

    This works except the warning in compile time.

    warning: ‘QQmlListProperty<T>::QQmlListProperty(QObject*, QList<T*>&) [with T = Person]’ is deprecated: Use constructor taking QList pointer, and gain improved performance [-Wdeprecated-declarations]
    

    so I replaced QQmlListProperty<Person> to QList<Person*>.

    Q_PROPERTY(QList<Person*> guests READ guests)
    ...
    QList<Person*> guests();
    ...
    QList<Person*> BirthdayParty::guests()
    {
        return this->m_guests;
    }
    

    This time, an error occured in QML.

    Invalid property assignment: "guests" is a read-only property
    

    again, I added WRITE method to the property.

    Q_PROPERTY(QList<Person*> guests WRITE setGuests READ guests)
                                     ^
    ...
    void BirthdayParty::setGuests(QList<Person*> guests)
    {
        this->m_guests = guests;
    }
    

    But QML error message is,

    Cannot assign to property of unknown type "QList<Person*>".
    

    How can I solve this? I don't want to see deprecated warnings because Qt 5.15 is the last Qt5 version so my project may won't work next Qt6 and very difficult to migrate to.


  • Moderators

    @Yujeonja replace QList<Person*> with QList<QObject*> thats supported and on the qml side happens an "implicit cast" when you try to access Person functions


  • Qt Champions 2018

    The warning tells you exactly what to do.

    replace return QQmlListProperty<Person>(this, this->m_guests); with return QQmlListProperty<Person>(this, &this->m_guests);



  • I misread the documents and warning. The deprecated is constructor not class. That constructor is removed from the QQmlListProperty documentation and replaced with new one and are very similar..


Log in to reply