fix(ModelSyncedContainer): Proper disconnection from previously used model

This commit is contained in:
Michał Cieślak 2024-06-05 10:12:50 +02:00 committed by Michał
parent 675ef05eaa
commit 2868d22a3a
2 changed files with 53 additions and 11 deletions

View File

@ -4,21 +4,26 @@
#include <QObject> #include <QObject>
#include <QVariant> #include <QVariant>
#include <memory>
template<typename T> template<typename T>
class ModelSyncedContainer class ModelSyncedContainer
{ {
public: public:
void setModel(QAbstractItemModel* model) void setModel(QAbstractItemModel* model)
{ {
m_container.clear(); m_container.clear();
// create context object for connections, disconnect from previous model
// by destroying previous context object if present
m_ctx = std::make_unique<QObject>();
if (model == nullptr) if (model == nullptr)
return; return;
m_container.resize(model->rowCount()); m_container.resize(model->rowCount());
QObject::connect(model, &QAbstractItemModel::rowsRemoved, &m_ctx, QObject::connect(model, &QAbstractItemModel::rowsRemoved, m_ctx.get(),
[this] (const QModelIndex& parent, int first, int last) [this] (const QModelIndex& parent, int first, int last)
{ {
if (parent.isValid()) if (parent.isValid())
@ -28,7 +33,7 @@ public:
m_container.cbegin() + last + 1); m_container.cbegin() + last + 1);
}); });
QObject::connect(model, &QAbstractItemModel::rowsInserted, &m_ctx, QObject::connect(model, &QAbstractItemModel::rowsInserted, m_ctx.get(),
[this] (const QModelIndex& parent, int first, int last) [this] (const QModelIndex& parent, int first, int last)
{ {
if (parent.isValid()) if (parent.isValid())
@ -45,8 +50,8 @@ public:
std::make_move_iterator(toBeInserted.end())); std::make_move_iterator(toBeInserted.end()));
}); });
QObject::connect(model, &QAbstractItemModel::rowsAboutToBeMoved, &m_ctx, QObject::connect(model, &QAbstractItemModel::rowsAboutToBeMoved,
[this, model] (const QModelIndex& parent) m_ctx.get(), [this, model] (const QModelIndex& parent)
{ {
if (parent.isValid()) if (parent.isValid())
return; return;
@ -55,7 +60,7 @@ public:
}); });
QObject::connect(model, &QAbstractItemModel::rowsMoved, QObject::connect(model, &QAbstractItemModel::rowsMoved,
&m_ctx, [this] (const QModelIndex& parent) m_ctx.get(), [this] (const QModelIndex& parent)
{ {
if (parent.isValid()) if (parent.isValid())
return; return;
@ -67,26 +72,26 @@ public:
}); });
QObject::connect(model, &QAbstractItemModel::layoutAboutToBeChanged, QObject::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
&m_ctx, [this, model] m_ctx.get(), [this, model]
{ {
storePersistentIndexes(model); storePersistentIndexes(model);
}); });
QObject::connect(model, &QAbstractItemModel::layoutChanged, QObject::connect(model, &QAbstractItemModel::layoutChanged,
&m_ctx, [this] m_ctx.get(), [this]
{ {
updateFromPersistentIndexes(); updateFromPersistentIndexes();
}); });
QObject::connect(model, &QAbstractItemModel::modelReset, QObject::connect(model, &QAbstractItemModel::modelReset,
&m_ctx, [this, model] m_ctx.get(), [this, model]
{ {
m_container.clear(); m_container.clear();
m_container.resize(model->rowCount()); m_container.resize(model->rowCount());
}); });
QObject::connect(model, &QAbstractItemModel::destroyed, QObject::connect(model, &QAbstractItemModel::destroyed,
&m_ctx, [this, model] m_ctx.get(), [this, model]
{ {
m_container.clear(); m_container.clear();
}); });
@ -144,5 +149,6 @@ private:
QList<QPersistentModelIndex> m_persistentIndexes; QList<QPersistentModelIndex> m_persistentIndexes;
std::vector<T> m_container; std::vector<T> m_container;
QObject m_ctx;
std::unique_ptr<QObject> m_ctx;
}; };

View File

@ -59,6 +59,42 @@ private slots:
QCOMPARE(container.size(), 0); QCOMPARE(container.size(), 0);
} }
void modelChangeDisconnectionTest()
{
struct Model : public QIdentityProxyModel
{
void connectNotify(const QMetaMethod&) override
{
connectionsCount++;
}
void disconnectNotify(const QMetaMethod&) override
{
connectionsCount--;
}
int connectionsCount = 0;
};
Model model1, model2;
ModelSyncedContainer<int> container;
QCOMPARE(model1.connectionsCount, 0);
container.setModel(&model1);
QVERIFY(model1.connectionsCount > 0);
container.setModel(nullptr);
QCOMPARE(model1.connectionsCount, 0);
container.setModel(&model1);
QVERIFY(model1.connectionsCount > 0);
container.setModel(&model2);
QCOMPARE(model1.connectionsCount, 0);
QVERIFY(model2.connectionsCount > 0);
}
void appendTest() void appendTest()
{ {
QQmlEngine engine; QQmlEngine engine;