Skip to content

Commit

Permalink
QConcatenateTablesProxyModel: react to row and column moves
Browse files Browse the repository at this point in the history
Fixes: QTBUG-128742
Pick-to: 6.8
Change-Id: I6282c3c9f27c435da5d511c61fbb051da127229c
Reviewed-by: Christian Ehrlicher <[email protected]>
  • Loading branch information
dfaure-kdab committed Sep 12, 2024
1 parent cbc5b4f commit b9ba283
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 1 deletion.
70 changes: 69 additions & 1 deletion src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,18 @@ class QConcatenateTablesProxyModelPrivate : public QAbstractItemModelPrivate
void slotRowsInserted(const QModelIndex &, int start, int end);
void slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end);
void slotRowsRemoved(const QModelIndex &, int start, int end);
void slotRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
const QModelIndex &destinationParent, int destinationRow);
void slotRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
const QModelIndex &destinationParent, int destinationRow);
void slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
void slotColumnsInserted(const QModelIndex &parent, int, int);
void slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void slotColumnsRemoved(const QModelIndex &parent, int, int);
void slotColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
const QModelIndex &destinationParent, int destination);
void slotColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
const QModelIndex &destinationParent, int destination);
void slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QList<int> &roles);
void slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
void slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
Expand All @@ -46,7 +54,7 @@ class QConcatenateTablesProxyModelPrivate : public QAbstractItemModelPrivate
int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const;

struct ModelInfo {
using ConnArray = std::array<QMetaObject::Connection, 13>;
using ConnArray = std::array<QMetaObject::Connection, 17>;
ModelInfo(QAbstractItemModel *m, ConnArray &&con)
: model(m), connections(std::move(con)) {}
QAbstractItemModel *model = nullptr;
Expand Down Expand Up @@ -472,6 +480,10 @@ void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceMode
d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeInserted),
QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeRemoved),
QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsMoved,
d, &QConcatenateTablesProxyModelPrivate::slotRowsMoved),
QObjectPrivate::connect(sourceModel, &QAbstractItemModel::rowsAboutToBeMoved,
d, &QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeMoved),

QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsInserted,
d, &QConcatenateTablesProxyModelPrivate::slotColumnsInserted),
Expand All @@ -481,6 +493,10 @@ void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceMode
d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeInserted),
QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsAboutToBeRemoved,
d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeRemoved),
QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsMoved,
d, &QConcatenateTablesProxyModelPrivate::slotColumnsMoved),
QObjectPrivate::connect(sourceModel, &QAbstractItemModel::columnsAboutToBeMoved,
d, &QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeMoved),

QObjectPrivate::connect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged,
d, &QConcatenateTablesProxyModelPrivate::slotSourceLayoutAboutToBeChanged),
Expand Down Expand Up @@ -565,6 +581,33 @@ void QConcatenateTablesProxyModelPrivate::slotRowsRemoved(const QModelIndex &par
q->endRemoveRows();
}

void QConcatenateTablesProxyModelPrivate::slotRowsAboutToBeMoved(
const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
const QModelIndex &destinationParent, int destinationRow)
{
Q_Q(QConcatenateTablesProxyModel);
if (sourceParent.isValid() || destinationParent.isValid())
return;
const QAbstractItemModel *const model = static_cast<QAbstractItemModel *>(q->sender());
const int rowsPrior = computeRowsPrior(model);
q->beginMoveRows(sourceParent, rowsPrior + sourceStart, rowsPrior + sourceEnd,
destinationParent, rowsPrior + destinationRow);
}

void QConcatenateTablesProxyModelPrivate::slotRowsMoved(const QModelIndex &sourceParent,
int sourceStart, int sourceEnd,
const QModelIndex &destinationParent,
int destinationRow)
{
Q_Q(QConcatenateTablesProxyModel);
Q_UNUSED(sourceStart)
Q_UNUSED(sourceEnd)
Q_UNUSED(destinationRow)
if (sourceParent.isValid() || destinationParent.isValid())
return;
q->endMoveRows();
}

void QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeInserted(const QModelIndex &parent,
int start, int end)
{
Expand Down Expand Up @@ -625,6 +668,31 @@ void QConcatenateTablesProxyModelPrivate::slotColumnsRemoved(const QModelIndex &
}
}

void QConcatenateTablesProxyModelPrivate::slotColumnsAboutToBeMoved(
const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
const QModelIndex &destinationParent, int destination)
{
Q_UNUSED(sourceStart)
Q_UNUSED(sourceEnd)
Q_UNUSED(destination)
if (sourceParent.isValid() || destinationParent.isValid())
return;
slotSourceLayoutAboutToBeChanged({}, QAbstractItemModel::HorizontalSortHint);
}

void QConcatenateTablesProxyModelPrivate::slotColumnsMoved(const QModelIndex &sourceParent,
int sourceStart, int sourceEnd,
const QModelIndex &destinationParent,
int destination)
{
Q_UNUSED(sourceStart)
Q_UNUSED(sourceEnd)
Q_UNUSED(destination)
if (sourceParent.isValid() || destinationParent.isValid())
return;
slotSourceLayoutChanged({}, QAbstractItemModel::HorizontalSortHint);
}

void QConcatenateTablesProxyModelPrivate::slotDataChanged(const QModelIndex &from,
const QModelIndex &to,
const QList<int> &roles)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <QMimeData>
#include <QStringListModel>
#include <QAbstractItemModelTester>
#include <QTransposeProxyModel>

#include <qconcatenatetablesproxymodel.h>

Expand Down Expand Up @@ -72,6 +73,8 @@ private Q_SLOTS:
void shouldIncreaseColumnCountWhenRemovingFirstModel();
void shouldHandleColumnInsertionAndRemoval();
void shouldPropagateLayoutChanged();
void shouldPropagateRowMove();
void shouldPropagateColumnMove();
void shouldReactToModelReset();
void shouldUpdateColumnsOnModelReset();
void shouldPropagateDropOnItem_data();
Expand Down Expand Up @@ -545,6 +548,68 @@ void tst_QConcatenateTablesProxyModel::shouldPropagateLayoutChanged()
}
}

void tst_QConcatenateTablesProxyModel::shouldPropagateRowMove()
{
// Given two source models (which support moving rows)
QStringListModel model1({ "0", "1", "2" });
QStringListModel model2({ "A", "B", "C" });
QConcatenateTablesProxyModel proxy;
new QAbstractItemModelTester(&proxy, &proxy);
proxy.addSourceModel(&model1);
proxy.addSourceModel(&model2);
QCOMPARE(extractColumnTexts(&proxy, 0), QStringLiteral("012ABC"));
QSignalSpy rowsATBMSpy(&proxy, &QAbstractItemModel::rowsAboutToBeMoved);
QSignalSpy rowsMovedSpy(&proxy, &QAbstractItemModel::rowsMoved);

// When moving a row
QVERIFY(model2.moveRow({}, 0, {}, 2));

// Then
QCOMPARE(extractColumnTexts(&proxy, 0), QStringLiteral("012BAC"));
QCOMPARE(rowsATBMSpy.count(), 1);
QCOMPARE(rowsMovedSpy.count(), 1);
QCOMPARE(rowsATBMSpy[0][1].toInt(), 3); // sourceStart
QCOMPARE(rowsATBMSpy[0][2].toInt(), 3); // sourceEnd
QCOMPARE(rowsATBMSpy[0][4].toInt(), 5); // destinationRow
QCOMPARE(rowsMovedSpy[0][1].toInt(), 3); // sourceStart
QCOMPARE(rowsMovedSpy[0][2].toInt(), 3); // sourceEnd
QCOMPARE(rowsMovedSpy[0][4].toInt(), 5); // destinationRow
}

void tst_QConcatenateTablesProxyModel::shouldPropagateColumnMove()
{
// Given two source models (which support moving rows)
// and two transpose proxies (so it becomes columns)
QStringListModel model1({ "0", "1", "2" });
QStringListModel model2({ "A", "B", "C" });
QTransposeProxyModel transpose1;
QTransposeProxyModel transpose2;
transpose1.setSourceModel(&model1);
transpose2.setSourceModel(&model2);

QConcatenateTablesProxyModel proxy;
new QAbstractItemModelTester(&proxy, &proxy);
proxy.addSourceModel(&transpose1);
proxy.addSourceModel(&transpose2);
QCOMPARE(extractRowTexts(&proxy, 0), QStringLiteral("012"));
QCOMPARE(extractRowTexts(&proxy, 1), QStringLiteral("ABC"));
QSignalSpy columnsATBMSpy(&proxy, &QAbstractItemModel::columnsAboutToBeMoved);
QSignalSpy columnsMovedSpy(&proxy, &QAbstractItemModel::columnsMoved);
QPersistentModelIndex A(proxy.index(1, 0));
QCOMPARE(A.data().toString(), "A");

// When moving a row in a stringlist model, which moves a column in a transpose proxy
QVERIFY(model2.moveRow({}, 0, {}, 2));

// Then, well, we didn't fully move a column in the concatenate proxy.
// It will emit layoutChanged and update persistent indexes, instead.
QCOMPARE(extractRowTexts(&proxy, 0), QStringLiteral("012"));
QCOMPARE(extractRowTexts(&proxy, 1), QStringLiteral("BAC"));
QCOMPARE(columnsATBMSpy.count(), 0);
QCOMPARE(columnsMovedSpy.count(), 0);
QCOMPARE(A.data().toString(), "A");
}

void tst_QConcatenateTablesProxyModel::shouldReactToModelReset()
{
// Given two source models, the second one being a QSFPM
Expand Down

0 comments on commit b9ba283

Please sign in to comment.