Fix invalid QSortFilterProxyModel::dataChanged parameters
QSortFilterModel shouldn't forward dataChanged() when the source model changes data in columns that the filter model refuses Fixes: QTBUG-86850 Pick-to: 5.15 Change-Id: I26565d119d2aa36ea07b3de0c15f1b137bc002f8 Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
parent
5b3cc25492
commit
66acca3316
@ -1404,17 +1404,21 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
|
|||||||
while (source_left_column < source_bottom_right.column()
|
while (source_left_column < source_bottom_right.column()
|
||||||
&& m->proxy_columns.at(source_left_column) == -1)
|
&& m->proxy_columns.at(source_left_column) == -1)
|
||||||
++source_left_column;
|
++source_left_column;
|
||||||
|
if (m->proxy_columns.at(source_left_column) != -1) {
|
||||||
const QModelIndex proxy_top_left = create_index(
|
const QModelIndex proxy_top_left = create_index(
|
||||||
proxy_start_row, m->proxy_columns.at(source_left_column), it);
|
proxy_start_row, m->proxy_columns.at(source_left_column), it);
|
||||||
int source_right_column = source_bottom_right.column();
|
int source_right_column = source_bottom_right.column();
|
||||||
while (source_right_column > source_top_left.column()
|
while (source_right_column > source_top_left.column()
|
||||||
&& m->proxy_columns.at(source_right_column) == -1)
|
&& m->proxy_columns.at(source_right_column) == -1)
|
||||||
--source_right_column;
|
--source_right_column;
|
||||||
|
if (m->proxy_columns.at(source_right_column) != -1) {
|
||||||
const QModelIndex proxy_bottom_right = create_index(
|
const QModelIndex proxy_bottom_right = create_index(
|
||||||
proxy_end_row, m->proxy_columns.at(source_right_column), it);
|
proxy_end_row, m->proxy_columns.at(source_right_column), it);
|
||||||
emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
|
emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!source_rows_insert.isEmpty()) {
|
if (!source_rows_insert.isEmpty()) {
|
||||||
sort_source_rows(source_rows_insert, source_parent);
|
sort_source_rows(source_rows_insert, source_parent);
|
||||||
|
@ -2192,6 +2192,172 @@ void tst_QSortFilterProxyModel::changeSourceDataProxySendDataChanged_qtbug87781(
|
|||||||
QCOMPARE(afterDataChangedSpy.size(), 1);
|
QCOMPARE(afterDataChangedSpy.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QSortFilterProxyModel::changeSourceDataProxyFilterSingleColumn()
|
||||||
|
{
|
||||||
|
enum modelRow { Row0, Row1, RowCount };
|
||||||
|
enum modelColumn { Column0, Column1, Column2, Column3, Column4, Column5, ColumnCount };
|
||||||
|
|
||||||
|
class FilterProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override {
|
||||||
|
Q_UNUSED(source_parent);
|
||||||
|
switch (source_column) {
|
||||||
|
case Column2:
|
||||||
|
case Column4:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QStandardItemModel model;
|
||||||
|
FilterProxyModel proxy;
|
||||||
|
proxy.setSourceModel(&model);
|
||||||
|
model.insertRows(0, RowCount);
|
||||||
|
model.insertColumns(0, ColumnCount);
|
||||||
|
|
||||||
|
QSignalSpy modelDataChangedSpy(&model, &QSortFilterProxyModel::dataChanged);
|
||||||
|
QSignalSpy proxyDataChangedSpy(&proxy, &FilterProxyModel::dataChanged);
|
||||||
|
|
||||||
|
QVERIFY(modelDataChangedSpy.isValid());
|
||||||
|
QVERIFY(proxyDataChangedSpy.isValid());
|
||||||
|
|
||||||
|
modelDataChangedSpy.clear();
|
||||||
|
proxyDataChangedSpy.clear();
|
||||||
|
model.setData(model.index(Row0, Column1), QStringLiteral("new data"), Qt::DisplayRole);
|
||||||
|
QCOMPARE(modelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyDataChangedSpy.size(), 0);
|
||||||
|
|
||||||
|
modelDataChangedSpy.clear();
|
||||||
|
proxyDataChangedSpy.clear();
|
||||||
|
model.setData(model.index(Row0, Column2), QStringLiteral("new data"), Qt::DisplayRole);
|
||||||
|
QCOMPARE(modelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyDataChangedSpy.size(), 1);
|
||||||
|
|
||||||
|
modelDataChangedSpy.clear();
|
||||||
|
proxyDataChangedSpy.clear();
|
||||||
|
model.setData(model.index(Row0, Column3), QStringLiteral("new data"), Qt::DisplayRole);
|
||||||
|
QCOMPARE(modelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyDataChangedSpy.size(), 0);
|
||||||
|
|
||||||
|
modelDataChangedSpy.clear();
|
||||||
|
proxyDataChangedSpy.clear();
|
||||||
|
model.setData(model.index(Row0, Column4), QStringLiteral("new data"), Qt::DisplayRole);
|
||||||
|
QCOMPARE(modelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyDataChangedSpy.size(), 1);
|
||||||
|
|
||||||
|
modelDataChangedSpy.clear();
|
||||||
|
proxyDataChangedSpy.clear();
|
||||||
|
model.setData(model.index(Row0, Column5), QStringLiteral("new data"), Qt::DisplayRole);
|
||||||
|
QCOMPARE(modelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyDataChangedSpy.size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QSortFilterProxyModel::changeSourceDataProxyFilterMultipleColumns()
|
||||||
|
{
|
||||||
|
class FilterProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override {
|
||||||
|
Q_UNUSED(source_parent);
|
||||||
|
switch (source_column) {
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyTableModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MyTableModel() = default;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override {
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
|
||||||
|
Q_UNUSED(index)
|
||||||
|
Q_UNUSED(role)
|
||||||
|
return QString("testData");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDataChanged(const int topLeftRow, const int topLeftColumn, const int bottomRightRow, const int bottomRightColumn) {
|
||||||
|
QModelIndex topLeft = index(topLeftRow, topLeftColumn);
|
||||||
|
QModelIndex bottomRight = index(bottomRightRow, bottomRightColumn);
|
||||||
|
QVERIFY(topLeft.isValid());
|
||||||
|
QVERIFY(bottomRight.isValid());
|
||||||
|
emit dataChanged(topLeft, bottomRight);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MyTableModel baseModel;
|
||||||
|
FilterProxyModel proxyModel;
|
||||||
|
|
||||||
|
proxyModel.setSourceModel(&baseModel);
|
||||||
|
|
||||||
|
QSignalSpy baseModelDataChangedSpy(&baseModel, &MyTableModel::dataChanged);
|
||||||
|
QSignalSpy proxyModelDataChangedSpy(&proxyModel, &FilterProxyModel::dataChanged);
|
||||||
|
|
||||||
|
connect(&proxyModel, &FilterProxyModel::dataChanged, [=](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
|
||||||
|
QVERIFY(topLeft.isValid());
|
||||||
|
QVERIFY(bottomRight.isValid());
|
||||||
|
|
||||||
|
//make sure every element is valid
|
||||||
|
int topLeftRow = topLeft.row();
|
||||||
|
int topLeftColumn = topLeft.column();
|
||||||
|
int bottomRightRow = bottomRight.row();
|
||||||
|
int bottomRightColumn = bottomRight.column();
|
||||||
|
for (int row = topLeftRow; row <= bottomRightRow; ++row) {
|
||||||
|
for (int column = topLeftColumn; column <= bottomRightColumn; ++column) {
|
||||||
|
QModelIndex index = topLeft.model()->index(row, column);
|
||||||
|
QVERIFY(index.isValid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QVERIFY(baseModelDataChangedSpy.isValid());
|
||||||
|
QVERIFY(proxyModelDataChangedSpy.isValid());
|
||||||
|
|
||||||
|
baseModelDataChangedSpy.clear();
|
||||||
|
proxyModelDataChangedSpy.clear();
|
||||||
|
baseModel.testDataChanged(0, 0, 1, 1);
|
||||||
|
QCOMPARE(baseModelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyModelDataChangedSpy.size(), 0);
|
||||||
|
|
||||||
|
baseModelDataChangedSpy.clear();
|
||||||
|
proxyModelDataChangedSpy.clear();
|
||||||
|
baseModel.testDataChanged(0, 0, 1, 2);
|
||||||
|
QCOMPARE(baseModelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyModelDataChangedSpy.size(), 1);
|
||||||
|
|
||||||
|
baseModelDataChangedSpy.clear();
|
||||||
|
proxyModelDataChangedSpy.clear();
|
||||||
|
baseModel.testDataChanged(0, 3, 1, 3);
|
||||||
|
QCOMPARE(baseModelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyModelDataChangedSpy.size(), 0);
|
||||||
|
|
||||||
|
baseModelDataChangedSpy.clear();
|
||||||
|
proxyModelDataChangedSpy.clear();
|
||||||
|
baseModel.testDataChanged(0, 3, 1, 5);
|
||||||
|
QCOMPARE(baseModelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyModelDataChangedSpy.size(), 1);
|
||||||
|
|
||||||
|
baseModelDataChangedSpy.clear();
|
||||||
|
proxyModelDataChangedSpy.clear();
|
||||||
|
baseModel.testDataChanged(0, 0, 1, 5);
|
||||||
|
QCOMPARE(baseModelDataChangedSpy.size(), 1);
|
||||||
|
QCOMPARE(proxyModelDataChangedSpy.size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QSortFilterProxyModel::sortFilterRole()
|
void tst_QSortFilterProxyModel::sortFilterRole()
|
||||||
{
|
{
|
||||||
QStandardItemModel model;
|
QStandardItemModel model;
|
||||||
|
@ -91,6 +91,8 @@ private slots:
|
|||||||
void changeSourceDataKeepsStableSorting_qtbug1548();
|
void changeSourceDataKeepsStableSorting_qtbug1548();
|
||||||
void changeSourceDataForwardsRoles_qtbug35440();
|
void changeSourceDataForwardsRoles_qtbug35440();
|
||||||
void changeSourceDataProxySendDataChanged_qtbug87781();
|
void changeSourceDataProxySendDataChanged_qtbug87781();
|
||||||
|
void changeSourceDataProxyFilterSingleColumn();
|
||||||
|
void changeSourceDataProxyFilterMultipleColumns();
|
||||||
void resortingDoesNotBreakTreeModels();
|
void resortingDoesNotBreakTreeModels();
|
||||||
void dynamicFilterWithoutSort();
|
void dynamicFilterWithoutSort();
|
||||||
void sortFilterRole();
|
void sortFilterRole();
|
||||||
|
Loading…
Reference in New Issue
Block a user