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 <QVariant>
#include <memory>
template<typename T>
class ModelSyncedContainer
{
public:
void setModel(QAbstractItemModel* model)
{
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)
return;
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)
{
if (parent.isValid())
@ -28,7 +33,7 @@ public:
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)
{
if (parent.isValid())
@ -45,8 +50,8 @@ public:
std::make_move_iterator(toBeInserted.end()));
});
QObject::connect(model, &QAbstractItemModel::rowsAboutToBeMoved, &m_ctx,
[this, model] (const QModelIndex& parent)
QObject::connect(model, &QAbstractItemModel::rowsAboutToBeMoved,
m_ctx.get(), [this, model] (const QModelIndex& parent)
{
if (parent.isValid())
return;
@ -55,7 +60,7 @@ public:
});
QObject::connect(model, &QAbstractItemModel::rowsMoved,
&m_ctx, [this] (const QModelIndex& parent)
m_ctx.get(), [this] (const QModelIndex& parent)
{
if (parent.isValid())
return;
@ -67,26 +72,26 @@ public:
});
QObject::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
&m_ctx, [this, model]
m_ctx.get(), [this, model]
{
storePersistentIndexes(model);
});
QObject::connect(model, &QAbstractItemModel::layoutChanged,
&m_ctx, [this]
m_ctx.get(), [this]
{
updateFromPersistentIndexes();
});
QObject::connect(model, &QAbstractItemModel::modelReset,
&m_ctx, [this, model]
m_ctx.get(), [this, model]
{
m_container.clear();
m_container.resize(model->rowCount());
});
QObject::connect(model, &QAbstractItemModel::destroyed,
&m_ctx, [this, model]
m_ctx.get(), [this, model]
{
m_container.clear();
});
@ -144,5 +149,6 @@ private:
QList<QPersistentModelIndex> m_persistentIndexes;
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);
}
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()
{
QQmlEngine engine;