Fix sorted QSortFilterProxyModel filter update

When changing a filter so that a previously empty proxy model becomes
populated sorting was not applied correctly.

This was caused by using mapToSource for getting source_sort_column
from proxy_sort_column. For an empty proxy model this won't work because
no valid proxy index can be created in this case.

We now directly use the root index column mapping instead by doing
essentially the same as QSortFilterProxyModelPrivate::proxy_to_source
but without the sanity checks needed for external use.

The sorting feature of QSortFilterProxyModel has always assumed that
the number of columns is specified by columnCount(QModelIndex()) so
the behavior doesn't change.

[ChangeLog][QtCore][QSortFilterProxyModel] Fixed sorting when a
previously empty proxy model becomes populated because of a change in
the filter.

Task-number: QTBUG-30662
Change-Id: I21322122e127889dfadc02f838f0119ed322dcab
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
bb10
Nils Jeisecke 2013-12-06 19:00:59 +01:00 committed by The Qt Project
parent 72259baa76
commit 6894bc0f3f
2 changed files with 42 additions and 3 deletions

View File

@ -458,10 +458,21 @@ void QSortFilterProxyModelPrivate::sort()
*/
bool QSortFilterProxyModelPrivate::update_source_sort_column()
{
Q_Q(QSortFilterProxyModel);
QModelIndex proxy_index = q->index(0, proxy_sort_column, QModelIndex());
int old_source_sort_column = source_sort_column;
source_sort_column = q->mapToSource(proxy_index).column();
if (proxy_sort_column == -1) {
source_sort_column = -1;
} else {
// We cannot use index mapping here because in case of a still-empty
// proxy model there's no valid proxy index we could map to source.
// So always use the root mapping directly instead.
Mapping *m = create_mapping(QModelIndex()).value();
if (proxy_sort_column < m->source_columns.size())
source_sort_column = m->source_columns.at(proxy_sort_column);
else
source_sort_column = -1;
}
return old_source_sort_column != source_sort_column;
}

View File

@ -92,6 +92,7 @@ private slots:
void filterTable();
void filterCurrent();
void filter_qtbug30662();
void changeSourceLayout();
void removeSourceRows_data();
@ -1480,6 +1481,33 @@ void tst_QSortFilterProxyModel::filterCurrent()
QCOMPARE(spy.count(), 2);
}
void tst_QSortFilterProxyModel::filter_qtbug30662()
{
QStringListModel model;
QSortFilterProxyModel proxy;
proxy.setSourceModel(&model);
// make sure the filter does not match any entry
proxy.setFilterRegExp(QRegExp("[0-9]+"));
QStringList slSource;
slSource << "z" << "x" << "a" << "b";
proxy.setDynamicSortFilter(true);
proxy.sort(0);
model.setStringList(slSource);
// without fix for QTBUG-30662 this will make all entries visible - but unsorted
proxy.setFilterRegExp(QRegExp("[a-z]+"));
QStringList slResult;
for (int i = 0; i < proxy.rowCount(); ++i)
slResult.append(proxy.index(i, 0).data().toString());
slSource.sort();
QCOMPARE(slResult, slSource);
}
void tst_QSortFilterProxyModel::changeSourceLayout()
{
QStandardItemModel model(2, 1);