Solved 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.
-
@Yujeonja replace
QList<Person*>
withQList<QObject*>
thats supported and on the qml side happens an "implicit cast" when you try to access Person functions -
The warning tells you exactly what to do.
replace
return QQmlListProperty<Person>(this, this->m_guests);
withreturn 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..