Hello, I'm using QML for some years now but recently I have found a behaviour which may be a bug or at least makes list property initialisation inconsistent with the way other types are handled. The behaviour can be traced back to (at least) Qt 5.2 and is still present in Qt 5.13. If I create a class with a QQmlListProperty and then initialise it with an array in some QML file, then subclass the QML type in a second QML file and try to override the array there, when creating an instance of the child class, the list contains the arrays concatenated instead of the overriding array. In the following example, I would expect the list to contain 2 elements instead of 5. What are your thoughts? Should I fill a bug report and try to provide a fix?
Best regards, Unai Irigoyen Example: // containedtype.h // #ifndef CONTAINEDTYPE_H #define CONTAINEDTYPE_H #include <QObject> class ContainedType : public QObject { Q_OBJECT }; #endif // CONTAINEDTYPE_H // mytype.h // #ifndef MYTYPE_H #define MYTYPE_H #include <QObject> #include <QQmlListProperty> #include "containedtype.h" class MyType : public QObject { Q_OBJECT Q_PROPERTY(QQmlListProperty<ContainedType> myList READ myList) QQmlListProperty<ContainedType> myList(){ return QQmlListProperty<ContainedType>(this, 0, &my_list_append, &my_list_count, &my_list_at, &my_list_clear); } private: QList<ContainedType*> m_myList; static inline void my_list_append(QQmlListProperty<ContainedType> * property,ContainedType * value) { MyType * instance = qobject_cast<MyType*>(property->object); if(instance) { instance->m_myList.append(value); } } static inline int my_list_count(QQmlListProperty<ContainedType> * property) { MyType * instance = qobject_cast<MyType*>(property->object); if(instance) { return instance->m_myList.count(); } else { return 0; } } static inline ContainedType * my_list_at(QQmlListProperty<ContainedType> * property, int index) { MyType * instance = qobject_cast<MyType*>(property->object); if(instance) { return instance->m_myList.at(index); } else { return nullptr; } } static inline void my_list_clear(QQmlListProperty<ContainedType> * property) { MyType * instance = qobject_cast<MyType*>(property->object); if(instance) { instance->m_myList.clear(); } } }; #endif // MYTYPE_H // main.cpp // #include <QGuiApplication> #include <QQmlApplicationEngine> #include "mytype.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<ContainedType>("array.override.test", 1, 0, "ContainedType"); qmlRegisterType<MyType>("array.override.test", 1, 0, "MyType"); 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); engine.load(url); return app.exec(); } // BaseType.qml // import array.override.test 1.0 MyType { myList: [ ContainedType{}, ContainedType{}, ContainedType{} ] } // OverridenType.qml // import array.override.test 1.0 BaseType { myList: [ ContainedType{}, ContainedType{} ] } // main.qml // import array.override.test 1.0 OverridenType { }
_______________________________________________ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest