Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QQmlListProperty is deprecated, but how to migrate?
Forum Updated to NodeBB v4.3 + New Features

QQmlListProperty is deprecated, but how to migrate?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 3 Posters 2.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    Yujeonja
    wrote on last edited by
    #1

    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.

    J.HilkJ 1 Reply Last reply
    0
    • Y Yujeonja

      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.

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #2

      @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


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      1 Reply Last reply
      0
      • GrecKoG Offline
        GrecKoG Offline
        GrecKo
        Qt Champions 2018
        wrote on last edited by
        #3

        The warning tells you exactly what to do.

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

        1 Reply Last reply
        4
        • Y Offline
          Y Offline
          Yujeonja
          wrote on last edited by
          #4

          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..

          1 Reply Last reply
          2

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved