diff options
author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2022-05-19 07:20:18 +0300 |
---|---|---|
committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2022-05-19 07:20:18 +0300 |
commit | 89407ff20e4f76314887e2f3625f5126910031ac (patch) | |
tree | 0730cdcea1c3d729f0a20e5dad8bd84f490039c3 | |
parent | 809412e1cc2151c21f843796ef67705600f6aafb (diff) | |
parent | 48f561783d549d7505b2041cbbfce5810d6217a3 (diff) |
Merge remote-tracking branch 'origin/tqtc/lts-5.15.5' into tqtc/lts-5.15-opensourcev5.15.5-lts-lgpl
Change-Id: I0846b203f280e4f3ea09f53eb2b771bedf1ffe2b
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp | 9 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h | 14 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp | 37 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h | 4 | ||||
-rw-r--r-- | tests/auto/modelreplica/tst_modelreplicatest.cpp | 89 |
6 files changed, 147 insertions, 8 deletions
diff --git a/.qmake.conf b/.qmake.conf index 3c27360..1c1f34c 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,6 +4,6 @@ CONFIG += qt_example_installs DEFINES += QT_NO_JAVA_STYLE_ITERATORS DEFINES += QT_NO_FOREACH -MODULE_VERSION = 5.15.4 +MODULE_VERSION = 5.15.5 QTRO_SOURCE_TREE = $$PWD diff --git a/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp b/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp index 4e6995f..a401bd5 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp +++ b/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp @@ -79,6 +79,7 @@ QAbstractItemModelSourceAdapter::QAbstractItemModelSourceAdapter(QAbstractItemMo connect(m_model, &QAbstractItemModel::columnsInserted, this, &QAbstractItemModelSourceAdapter::sourceColumnsInserted); connect(m_model, &QAbstractItemModel::rowsRemoved, this, &QAbstractItemModelSourceAdapter::sourceRowsRemoved); connect(m_model, &QAbstractItemModel::rowsMoved, this, &QAbstractItemModelSourceAdapter::sourceRowsMoved); + connect(m_model, &QAbstractItemModel::layoutChanged, this, &QAbstractItemModelSourceAdapter::sourceLayoutChanged); if (m_selectionModel) connect(m_selectionModel, &QItemSelectionModel::currentChanged, this, &QAbstractItemModelSourceAdapter::sourceCurrentChanged); } @@ -248,6 +249,14 @@ void QAbstractItemModelSourceAdapter::sourceCurrentChanged(const QModelIndex & c emit currentChanged(currentIndex, previousIndex); } +void QAbstractItemModelSourceAdapter::sourceLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) +{ + IndexList indexes; + for (const QPersistentModelIndex &idx : parents) + indexes << toModelIndexList((QModelIndex)idx, m_model); + emit layoutChanged(indexes, hint); +} + QVector<IndexValuePair> QAbstractItemModelSourceAdapter::fetchTree(const QModelIndex &parent, size_t &size, const QVector<int> &roles) { QVector<IndexValuePair> entries; diff --git a/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h b/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h index 8eff2c5..05f68b8 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h +++ b/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h @@ -97,7 +97,7 @@ public Q_SLOTS: void sourceRowsRemoved(const QModelIndex & parent, int start, int end); void sourceRowsMoved(const QModelIndex & sourceParent, int sourceRow, int count, const QModelIndex & destinationParent, int destinationChild) const; void sourceCurrentChanged(const QModelIndex & current, const QModelIndex & previous); - + void sourceLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); Q_SIGNALS: void availableRolesChanged(); void dataChanged(IndexList topLeft, IndexList bottomRight, QVector<int> roles) const; @@ -106,6 +106,7 @@ Q_SIGNALS: void rowsMoved(IndexList sourceParent, int sourceRow, int count, IndexList destinationParent, int destinationChild) const; void currentChanged(IndexList current, IndexList previous); void columnsInserted(IndexList parent, int start, int end) const; + void layoutChanged(IndexList parents, QAbstractItemModel::LayoutChangeHint hint); private: QAbstractItemModelSourceAdapter(); @@ -128,7 +129,7 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap m_properties[0] = 2; m_properties[1] = QtPrivate::qtro_property_index<AdapterType>(&AdapterType::availableRoles, static_cast<QVector<int> (QObject::*)()>(0),"availableRoles"); m_properties[2] = QtPrivate::qtro_property_index<AdapterType>(&AdapterType::roleNames, static_cast<QIntHash (QObject::*)()>(0),"roleNames"); - m_signals[0] = 9; + m_signals[0] = 10; m_signals[1] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::availableRolesChanged, static_cast<void (QObject::*)()>(0),m_signalArgCount+0,&m_signalArgTypes[0]); m_signals[2] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::dataChanged, static_cast<void (QObject::*)(IndexList,IndexList,QVector<int>)>(0),m_signalArgCount+1,&m_signalArgTypes[1]); m_signals[3] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::rowsInserted, static_cast<void (QObject::*)(IndexList,int,int)>(0),m_signalArgCount+2,&m_signalArgTypes[2]); @@ -138,6 +139,7 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap m_signals[7] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::modelReset, static_cast<void (QObject::*)()>(0),m_signalArgCount+6,&m_signalArgTypes[6]); m_signals[8] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::headerDataChanged, static_cast<void (QObject::*)(Qt::Orientation,int,int)>(0),m_signalArgCount+7,&m_signalArgTypes[7]); m_signals[9] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::columnsInserted, static_cast<void (QObject::*)(IndexList,int,int)>(0),m_signalArgCount+8,&m_signalArgTypes[8]); + m_signals[10] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::layoutChanged, static_cast<void (QObject::*)(IndexList,QAbstractItemModel::LayoutChangeHint)>(nullptr),m_signalArgCount+9,&m_signalArgTypes[9]); m_methods[0] = 6; m_methods[1] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaSizeRequest, static_cast<void (QObject::*)(IndexList)>(0),"replicaSizeRequest(IndexList)",m_methodArgCount+0,&m_methodArgTypes[0]); m_methods[2] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaRowRequest, static_cast<void (QObject::*)(IndexList,IndexList,QVector<int>)>(0),"replicaRowRequest(IndexList,IndexList,QVector<int>)",m_methodArgCount+1,&m_methodArgTypes[1]); @@ -213,6 +215,7 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap case 6: return QByteArrayLiteral("resetModel()"); case 7: return QByteArrayLiteral("headerDataChanged(Qt::Orientation,int,int)"); case 8: return QByteArrayLiteral("columnsInserted(IndexList,int,int)"); + case 9: return QByteArrayLiteral("layoutChanged(IndexList,QAbstractItemModel::LayoutChangeHint)"); } return QByteArrayLiteral(""); } @@ -264,6 +267,7 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap case 4: case 5: case 8: + case 9: return true; } return false; @@ -292,10 +296,10 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap } int m_properties[3]; - int m_signals[10]; + int m_signals[11]; int m_methods[7]; - int m_signalArgCount[9]; - const int* m_signalArgTypes[9]; + int m_signalArgCount[10]; + const int* m_signalArgTypes[10]; int m_methodArgCount[6]; const int* m_methodArgTypes[6]; QString m_name; diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp index 27851c8..cfcaf3c 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp +++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp @@ -141,6 +141,8 @@ void QAbstractItemModelReplicaImplementation::initializeModelConnections() connect(this, &QAbstractItemModelReplicaImplementation::currentChanged, this, &QAbstractItemModelReplicaImplementation::onCurrentChanged); connect(this, &QAbstractItemModelReplicaImplementation::modelReset, this, &QAbstractItemModelReplicaImplementation::onModelReset); connect(this, &QAbstractItemModelReplicaImplementation::headerDataChanged, this, &QAbstractItemModelReplicaImplementation::onHeaderDataChanged); + connect(this, &QAbstractItemModelReplicaImplementation::layoutChanged, this, &QAbstractItemModelReplicaImplementation::onLayoutChanged); + } inline void removeIndexFromRow(const QModelIndex &index, const QVector<int> &roles, CachedRowEntry *entry) @@ -693,6 +695,41 @@ void QAbstractItemModelReplicaImplementation::fetchPendingHeaderData() m_pendingRequests.push_back(watcher); } +void QAbstractItemModelReplicaImplementation::onLayoutChanged(const IndexList &parents, + QAbstractItemModel::LayoutChangeHint hint) +{ + QList<QPersistentModelIndex> indexes; + for (const ModelIndex &parent : qAsConst(parents)) { + const QModelIndex parentIndex = toQModelIndex(IndexList{parent}, q); + indexes << QPersistentModelIndex(parentIndex); + } + QRemoteObjectPendingCallWatcher *watcher; + auto call = replicaCacheRequest(m_rootItem.children.cacheSize, m_initialFetchRolesHint); + watcher = new QRemoteObjectPendingCallWatcher(call); + m_pendingRequests.push_back(watcher); + connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, [this, watcher, indexes, hint]() { + Q_ASSERT(watcher->returnValue().canConvert<MetaAndDataEntries>()); + const QSize size = watcher->returnValue().value<MetaAndDataEntries>().size; + + q->layoutAboutToBeChanged(indexes, hint); + m_rootItem.clear(); + if (size.height() > 0) { + m_rootItem.rowCount = size.height(); + m_rootItem.hasChildren = true; + } + + m_rootItem.columnCount = size.width(); + if (m_initialAction == QtRemoteObjects::PrefetchData) { + auto entries = watcher->returnValue().value<MetaAndDataEntries>(); + for (int i = 0; i < entries.data.size(); ++i) + fillCache(entries.data[i], entries.roles); + } + m_pendingRequests.removeAll(watcher); + watcher->deleteLater(); + emit q->layoutChanged(indexes, hint); + }); +} + static inline QVector<QPair<int, int> > listRanges(const QVector<int> &list) { QVector<QPair<int, int> > result; diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h b/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h index 8f13091..bfa3c45 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h +++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h @@ -360,7 +360,7 @@ Q_SIGNALS: void modelReset(); void headerDataChanged(Qt::Orientation,int,int); void columnsInserted(IndexList parent, int first, int last); - + void layoutChanged(IndexList parents, QAbstractItemModel::LayoutChangeHint hint); public Q_SLOTS: QRemoteObjectPendingReply<QSize> replicaSizeRequest(IndexList parentList) { @@ -422,7 +422,7 @@ public Q_SLOTS: void handleSizeDone(QRemoteObjectPendingCallWatcher *watcher); void onReplicaCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous); void fillCache(const IndexValuePair &pair,const QVector<int> &roles); - + void onLayoutChanged(const IndexList &parents, QAbstractItemModel::LayoutChangeHint hint); public: QScopedPointer<QItemSelectionModel> m_selectionModel; QVector<CacheEntry> m_headerData[2]; diff --git a/tests/auto/modelreplica/tst_modelreplicatest.cpp b/tests/auto/modelreplica/tst_modelreplicatest.cpp index 40b622e..c3760e0 100644 --- a/tests/auto/modelreplica/tst_modelreplicatest.cpp +++ b/tests/auto/modelreplica/tst_modelreplicatest.cpp @@ -41,6 +41,10 @@ private Q_SLOTS: void basicFunctions(); void basicFunctions_data(); void nullModel(); + void nestedSortFilterProxyModel_data() { basicFunctions_data(); } + void nestedSortFilterProxyModel(); + void sortFilterProxyModel_data(); + void sortFilterProxyModel(); }; void ModelreplicaTest::basicFunctions_data() @@ -113,6 +117,91 @@ void ModelreplicaTest::nullModel() QTRY_COMPARE(replica->tracks()->data(replica->tracks()->index(3, 0)), "New Track4"); } +void ModelreplicaTest::nestedSortFilterProxyModel() +{ + QFETCH(bool, templated); + + QRemoteObjectRegistryHost host(QUrl("tcp://localhost:5555")); + auto model = new QStringListModel(this); + model->setStringList(QStringList() << "CCC" << "AAA" << "BBB"); + auto proxyModel = new QSortFilterProxyModel(this); + proxyModel->setSourceModel(model); + + MediaSimpleSource source; + source.setTracks(proxyModel); + if (templated) + host.enableRemoting<MediaSourceAPI>(&source); + else + host.enableRemoting(&source); + + QRemoteObjectNode client(QUrl("tcp://localhost:5555")); + const QScopedPointer<MediaReplica> replica(client.acquire<MediaReplica>()); + QSignalSpy tracksSpy(replica->tracks(), &QAbstractItemModelReplica::initialized); + QVERIFY(replica->waitForSource(300)); + QVERIFY(tracksSpy.wait()); + // Rep file only uses display role + QCOMPARE(QVector<int>{Qt::DisplayRole}, replica->tracks()->availableRoles()); + + QCOMPARE(proxyModel->rowCount(), replica->tracks()->rowCount()); + for (int i = 0; i < replica->tracks()->rowCount(); i++) { + // We haven't received any data yet + QCOMPARE(QVariant(), replica->tracks()->data(replica->tracks()->index(i, 0))); + } + + // Wait for data to be fetch and confirm + QCOMPARE(proxyModel->rowCount(), replica->tracks()->rowCount()); + for (int i = 0; i < replica->tracks()->rowCount(); i++) + QTRY_COMPARE(proxyModel->data(proxyModel->index(i, 0), Qt::DisplayRole), replica->tracks()->data(replica->tracks()->index(i, 0))); + + proxyModel->sort(0, Qt::AscendingOrder); + QCOMPARE(proxyModel->rowCount(), replica->tracks()->rowCount()); + for (int i = 0; i < replica->tracks()->rowCount(); i++) + QTRY_COMPARE(proxyModel->data(proxyModel->index(i, 0), Qt::DisplayRole), replica->tracks()->data(replica->tracks()->index(i, 0))); +} + +void ModelreplicaTest::sortFilterProxyModel_data() +{ + QTest::addColumn<bool>("prefetch"); + + QTest::newRow("size only") << false; + QTest::newRow("prefetch") << true; +} + +void ModelreplicaTest::sortFilterProxyModel() +{ + QFETCH(bool, prefetch); + + QRemoteObjectRegistryHost host(QUrl("tcp://localhost:5555")); + auto model = new QStringListModel(this); + model->setStringList(QStringList() << "CCC" << "AAA" << "BBB"); + auto proxyModel = new QSortFilterProxyModel(this); + proxyModel->setSourceModel(model); + + QVector<int> roles = { Qt::DisplayRole }; + host.enableRemoting(proxyModel, "test", roles); + + auto fetchMode = prefetch ? QtRemoteObjects::PrefetchData : QtRemoteObjects::FetchRootSize; + QRemoteObjectNode client(QUrl("tcp://localhost:5555")); + QScopedPointer<QAbstractItemModelReplica> replica(client.acquireModel("test", fetchMode)); + QSignalSpy initSpy(replica.get(), &QAbstractItemModelReplica::initialized); + QVERIFY(initSpy.wait()); + + QCOMPARE(roles, replica->availableRoles()); + + // Wait for data to be fetch and confirm + QCOMPARE(proxyModel->rowCount(), replica->rowCount()); + for (int i = 0; i < replica->rowCount(); i++) + QTRY_COMPARE(proxyModel->data(proxyModel->index(i, 0), Qt::DisplayRole), + replica->data(replica->index(i, 0))); + + proxyModel->sort(0, Qt::AscendingOrder); + QCOMPARE(proxyModel->rowCount(), replica->rowCount()); + + for (int i = 0; i < replica->rowCount(); i++) + QTRY_COMPARE(proxyModel->data(proxyModel->index(i, 0), Qt::DisplayRole), + replica->data(replica->index(i, 0))); +} + QTEST_MAIN(ModelreplicaTest) #include "tst_modelreplicatest.moc" |