PDA

View Full Version : QSortFilterProxyModel - lessThan sorts wrong column



ghorwin
1st July 2008, 13:57
Hi there,

this post is about Qt 4.3.3.

I inherited a QSortFilterProxyModel and reimplemeted both filterAcceptsColumn() and lessThan(). setSortingEnabled(true) is set for my table view.

Things work fine to the point when I remove a column in filterAcceptsColumn(). Say, I have 5 columns in my model and in filterAcceptsColumn() I write:



bool MaterialDBSortModel::filterAcceptsColumn(int source_column, const QModelIndex & source_parent ) const {
if (source_column == 2)
return false;
return true;
}


to remove the third column. Now my table shows only 4 columns and here is the problem. When I click on column number 3 (corresponding to column 4 in my source model), it sorts the table based on the content of column #3 in the source model (my lessThan() function gets the data for the source model).

That is, if I use the following code:



bool MaterialDBSortModel::lessThan(const QModelIndex & left, const QModelIndex & right) const {
QVariant leftData = sourceModel()->data(left);
QVariant rightData = sourceModel()->data(right);

qDebug() << left.column(); // prints 2 when I clicked on the third column
// but since I filtered the third column (index 2), I expected a print out of 3 !?!

// ... snip ... do comparison
// ... snip
}


just as in the example. So, I'm wondering whether lessThan() gets source ModelIndices or proxy ModelIndices. Since when I click on column 3 the model index left has the column 3, so my guess is that I get proxyIndex. But using QSortFilterProxy::data() or mapToSource() with the either parameter 'left' or 'right' always results in a crash.

What is the correct way to get the correct column data or the correct source model indices?

Thanks,
Andreas

caduel
1st July 2008, 17:12
Sounds like a bug in Qt to me. Did you report it?

ghorwin
21st July 2008, 09:06
It's a bug. Reported for 4.4.0 rc1 (and previous versions of Qt), here's the link to the tracker:

TaskTracker entry 219948 (http://trolltech.com/developer/task-tracker/index_html?id=219948&method=entry)

Workaround: Manually remember the number of filtered columns.

Most efficient way to do this:

Whenever a filter property of your QSortFilterProxyModel model changes, update a vector of type:

filteredColumnCount[proxy_column]

Example: you have 5 columns, column with index 2 is filtered out, the vector has the content:



filteredColumnCount[0] = 0
filteredColumnCount[1] = 0
filteredColumnCount[2] = 1
filteredColumnCount[3] = 1


and the sort code needs to manually shift the sort column:



bool DemoSortFilterProxyModel::lessThan(const QModelIndex & left, const QModelIndex & right) const {
// get the column to filter
int col = left.column();
// shift column to match source model column
col += filteredColumnCount[col];
return mydata(left.row(), col) < mydata(right.row(), col);
}