diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-09-02 16:25:23 +0200 |
|---|---|---|
| committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2025-09-03 16:33:14 +0000 |
| commit | f417e4e2951aef9bb8e88b91ec3bb61f6c5e7328 (patch) | |
| tree | a30361fa0a5f7a290faa9d15c0866a39d8802d1c | |
| parent | 2f76b2f140b2cfe95b287a2742f44d24a46f75ad (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.cpp | 28 | ||||
| -rw-r--r-- | src/qmlmodels/qqmladaptormodel_p.h | 13 | ||||
| -rw-r--r-- | src/qmlmodels/qqmllistaccessor.cpp | 17 | ||||
| -rw-r--r-- | src/qmlmodels/qqmllistaccessor_p.h | 3 | ||||
| -rw-r--r-- | tests/auto/qml/qqmlrangemodel/tst_qqmlrangemodel.cpp | 10 |
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"); |
