aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2025-09-02 16:25:23 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2025-09-03 16:33:14 +0000
commitf417e4e2951aef9bb8e88b91ec3bb61f6c5e7328 (patch)
treea30361fa0a5f7a290faa9d15c0866a39d8802d1c
parent2f76b2f140b2cfe95b287a2742f44d24a46f75ad (diff)
QmlModels: Use QObject accessor for any sequence of QObject-derived
Before we used it only for QObjectList. All other sequences were considered to contain value types which can't have signals. Therefore we were missing all property updates on the objects in such lists. Change-Id: I80e9c6430de2c7e3674b941eaeb0fb104df509e2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> (cherry picked from commit 5130c179b30635e9f692d66d96225dfdd82d56c0) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qmlmodels/qqmladaptormodel.cpp28
-rw-r--r--src/qmlmodels/qqmladaptormodel_p.h13
-rw-r--r--src/qmlmodels/qqmllistaccessor.cpp17
-rw-r--r--src/qmlmodels/qqmllistaccessor_p.h3
-rw-r--r--tests/auto/qml/qqmlrangemodel/tst_qqmlrangemodel.cpp10
5 files changed, 49 insertions, 22 deletions
diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp
index 8c047aff9c..b36b524981 100644
--- a/src/qmlmodels/qqmladaptormodel.cpp
+++ b/src/qmlmodels/qqmladaptormodel.cpp
@@ -41,22 +41,34 @@ void QQmlAdaptorModel::setModel(const QVariant &variant)
accessors = new VDMAbstractItemModelDataType(this);
else
accessors = new VDMObjectDelegateDataType(this);
- } else if (list.type() == QQmlListAccessor::ListProperty) {
- auto object = static_cast<const QQmlListReference *>(list.list().constData())->object();
- if (QQmlData *ddata = QQmlData::get(object))
+ return;
+ }
+
+ switch (list.type()) {
+ case QQmlListAccessor::ListProperty:
+ setObject(static_cast<const QQmlListReference *>(list.list().constData())->object());
+ if (QQmlData *ddata = QQmlData::get(object()))
modelStrongReference = ddata->jsWrapper;
- setObject(object);
accessors = new VDMObjectDelegateDataType(this);
- } else if (list.type() == QQmlListAccessor::ObjectList) {
+ break;
+ case QQmlListAccessor::ObjectList:
+ case QQmlListAccessor::ObjectSequence:
setObject(nullptr);
accessors = new VDMObjectDelegateDataType(this);
- } else if (list.type() != QQmlListAccessor::Invalid
- && list.type() != QQmlListAccessor::Instance) { // Null QObject
+ break;
+ case QQmlListAccessor::StringList:
+ case QQmlListAccessor::UrlList:
+ case QQmlListAccessor::VariantList:
+ case QQmlListAccessor::Integer:
+ case QQmlListAccessor::ValueSequence:
setObject(nullptr);
accessors = new VDMListDelegateDataType(this);
- } else {
+ break;
+ case QQmlListAccessor::Instance:
+ case QQmlListAccessor::Invalid:
setObject(nullptr);
accessors = &m_nullAccessors;
+ break;
}
}
diff --git a/src/qmlmodels/qqmladaptormodel_p.h b/src/qmlmodels/qqmladaptormodel_p.h
index 11cb2039b5..bc46a4a8d4 100644
--- a/src/qmlmodels/qqmladaptormodel_p.h
+++ b/src/qmlmodels/qqmladaptormodel_p.h
@@ -115,9 +115,16 @@ public:
return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index));
}
inline bool hasProxyObject() const {
- return list.type() == QQmlListAccessor::Instance
- || list.type() == QQmlListAccessor::ListProperty
- || list.type() == QQmlListAccessor::ObjectList;
+ switch (list.type()) {
+ case QQmlListAccessor::Instance:
+ case QQmlListAccessor::ListProperty:
+ case QQmlListAccessor::ObjectList:
+ case QQmlListAccessor::ObjectSequence:
+ return true;
+ default:
+ break;
+ }
+ return false;
}
inline bool notify(
diff --git a/src/qmlmodels/qqmllistaccessor.cpp b/src/qmlmodels/qqmllistaccessor.cpp
index acf6a14e02..7483c07056 100644
--- a/src/qmlmodels/qqmllistaccessor.cpp
+++ b/src/qmlmodels/qqmllistaccessor.cpp
@@ -110,7 +110,9 @@ void QQmlListAccessor::setList(const QVariant &v)
const QQmlType type = QQmlMetaType::qmlListType(variantsType);
if (type.isSequentialContainer()) {
m_metaSequence = type.listMetaSequence();
- m_type = Sequence;
+ m_type = m_metaSequence.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)
+ ? ObjectSequence
+ : ValueSequence;
return;
}
@@ -123,7 +125,9 @@ void QQmlListAccessor::setList(const QVariant &v)
if (sequence.hasSize() && sequence.canGetValueAtIndex()) {
// If the resulting iterable is useful for anything, use it.
m_metaSequence = sequence;
- m_type = Sequence;
+ m_type = sequence.valueMetaType().flags().testFlag(QMetaType::PointerToQObject)
+ ? ObjectSequence
+ : ValueSequence;
return;
}
@@ -161,7 +165,8 @@ qsizetype QQmlListAccessor::count() const
case ListProperty:
Q_ASSERT(d.metaType() == QMetaType::fromType<QQmlListReference>());
return reinterpret_cast<const QQmlListReference *>(d.constData())->count();
- case Sequence:
+ case ValueSequence:
+ case ObjectSequence:
Q_ASSERT(m_metaSequence != QMetaSequence());
return m_metaSequence.size(d.constData());
case Instance:
@@ -193,7 +198,8 @@ QVariant QQmlListAccessor::at(qsizetype idx) const
case ListProperty:
Q_ASSERT(d.metaType() == QMetaType::fromType<QQmlListReference>());
return QVariant::fromValue(reinterpret_cast<const QQmlListReference *>(d.constData())->at(idx));
- case Sequence: {
+ case ValueSequence:
+ case ObjectSequence: {
Q_ASSERT(m_metaSequence != QMetaSequence());
QVariant result;
const QMetaType valueMetaType = m_metaSequence.valueMetaType();
@@ -239,7 +245,8 @@ void QQmlListAccessor::set(qsizetype idx, const QVariant &value)
Q_ASSERT(d.metaType() == QMetaType::fromType<QQmlListReference>());
static_cast<QQmlListReference *>(d.data())->replace(idx, value.value<QObject *>());
break;
- case Sequence: {
+ case ValueSequence:
+ case ObjectSequence: {
Q_ASSERT(m_metaSequence != QMetaSequence());
const QMetaType valueMetaType = m_metaSequence.valueMetaType();
if (valueMetaType == QMetaType::fromType<QVariant>()) {
diff --git a/src/qmlmodels/qqmllistaccessor_p.h b/src/qmlmodels/qqmllistaccessor_p.h
index d713ad7f85..4d61e537e8 100644
--- a/src/qmlmodels/qqmllistaccessor_p.h
+++ b/src/qmlmodels/qqmllistaccessor_p.h
@@ -45,7 +45,8 @@ public:
ListProperty,
Instance,
Integer,
- Sequence,
+ ObjectSequence,
+ ValueSequence,
};
Type type() const { return m_type; }
diff --git a/tests/auto/qml/qqmlrangemodel/tst_qqmlrangemodel.cpp b/tests/auto/qml/qqmlrangemodel/tst_qqmlrangemodel.cpp
index 106fc97a7e..2038a0ed7f 100644
--- a/tests/auto/qml/qqmlrangemodel/tst_qqmlrangemodel.cpp
+++ b/tests/auto/qml/qqmlrangemodel/tst_qqmlrangemodel.cpp
@@ -252,12 +252,12 @@ void tst_QQmlRangeModel::objectList()
QCOMPARE(currentItem->property("currentData"), writeBack ? "42: one" : "1: one");
QCOMPARE(entry->number(), writeBack ? 42 : 1);
- // changing C++ doesn't update required property values in either case
+ // changing C++ does update required property values in either case
entry->setText("fortytwo");
- QCOMPARE(currentValueSpy.count(), 1);
- QCOMPARE(currentItem->property("currentValue"), "42: one");
+ QCOMPARE(currentValueSpy.count(), 2);
+ QCOMPARE(currentItem->property("currentValue"), "42: fortytwo");
- // but does update modelData
+ // and updates modelData
QCOMPARE(currentDataSpy.count(), writeBack ? 2 : 1);
QCOMPARE(currentItem->property("currentData"), entry->toString());
@@ -269,7 +269,7 @@ void tst_QQmlRangeModel::objectList()
#endif
QMetaObject::invokeMethod(currentItem, "setModelData", QVariant::fromValue(newEntry.get()));
QVERIFY(entry); // old object still alive
- QCOMPARE(currentItem->property("currentValue"), writeBack ? "42: fortytwo" : "42: one");
+ QCOMPARE(currentItem->property("currentValue"), "42: fortytwo");
QCOMPARE(entry->toString(), writeBack ? "42: fortytwo" : "1: fortytwo");
QCOMPARE(currentItem->property("currentData"), "2: two");
QCOMPARE(newEntry->toString(), "2: two");