[Interest] Overriding list properties in QML at initialisation
Unai IRIGOYEN
u.irigoyen at gmail.com
Wed Aug 14 07:39:42 CEST 2019
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 {
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20190814/609c7cef/attachment.html>
More information about the Interest
mailing list