Reputation: 2418
In my project, I have a model displayed in a treeview. I used QSortFilterProxyModel to sort the model based on an ID set in Qt::UserRole+1. This divides my list by "type" (as you can tell by the icons used):
However I also want each "type" to be sorted alphabetically. I initially tried to sort things alphabetically FIRST and THEN sort it by type to see if it would rearrange things to work properly, but it stays the same. Is there any way to tell my program to sort with two sort roles AND determine which one "goes first?"
proxy->setSortRole(Qt::DisplayRole);
proxy->setSortRole(Qt::UserRole+1);
Upvotes: 4
Views: 6755
Reputation: 2418
All I needed to do was create a proxy model of another proxy model. The first proxy ordered things alphabetically, the second proxy ordered the first proxy by UserRole+1.
QSortFilterProxyModel* proxy = new QSortFilterProxyModel(ui->treeNBT);
proxy->setSourceModel(model);
proxy->setDynamicSortFilter(false);
proxy->sort(0, Qt::AscendingOrder);
proxy->setSortCaseSensitivity(Qt::CaseInsensitive);
proxy->setSortRole(Qt::DisplayRole);
QSortFilterProxyModel* proxy2 = new QSortFilterProxyModel(ui->treeNBT);
proxy2->setSourceModel(proxy);
proxy2->setDynamicSortFilter(false);
proxy2->sort(0, Qt::AscendingOrder);
proxy2->setSortRole(Qt::UserRole+1);
ui->treeNBT->setModel(proxy2);
Much simpler than writing custom sort logic in a reimplemented class. There is no noticeable performance hit, so this is what I'm using.
Edit: Changed my answer... looking back at my old questions, and this isn't the best way to go about this. Reimplementing the class was the better (and obvious) way. oops.
Upvotes: 6
Reputation: 1336
You need to subclass the proxy and implement your own lessThan()
.
The QSortFilterProxyModel uses a virtual lessThan
method to determine the ordering between model indexes. Only the default implementation of lessThan
respects the role set by setSortRole
. You can override it to provide custom sorting behavior, in which case setSortRole
is obsolete.
The official documentation has a section on custom sorting along with a code sample: http://doc.qt.io/qt-5/qsortfilterproxymodel.html#details
Upvotes: 1
Reputation: 53173
Since my duplicate urls were nuked, here goes the working example right from the official example after some minor adjustment:
class MySortFilterProxyModel Q_DECL_FINAL : public QSortFilterProxyModel
{
Q_OBJECT
public:
MySortFilterProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
{
}
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE
{
QVariant leftData = sourceModel()->data(left);
QVariant rightData = sourceModel()->data(right);
// Do custom logic in here, e.g.:
return QString::localeAwareCompare(leftData.toString(), rightData.toString()) < 0;
}
};
Then, this custom class would be used normally in place of the original as a drop-in replacement. That is it!
Upvotes: 1