Sorting QSortFilterProxyModel based on two sorting roles?
In my project, I have a model displayed in a tree. I used QSortFilterProxyModel to sort the model based on the ID set in Qt :: UserRole + 1. This divides my list by "type" (as you can tell from the icons used):
However, I also want each "type" to be sorted alphabetically. I first tried to sort things alphabetically by FIRST and THEN, sorting by type to see if it would change the order of things, but it stays the same. Is there a way to tell my program to sort with two sorting roles and determine which one "comes first?"
proxy->setSortRole(Qt::DisplayRole);
proxy->setSortRole(Qt::UserRole+1);
source to share
Since my duplicate urls have been removed, here is a working example straight from the official example after some minor adjustments:
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;
}
};
This custom class will then be used normally instead of the original as a replacement. That's all!
source to share
All I had to do was create a proxy model of another proxy model. The first proxy ordered things alphabetically, the second proxy ordered the first proxy 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 easier than writing custom sorting logic in an overridden class. There is no noticeable performance improvement, so this is what I am using.
Edit: changed my answer ... looking back at my old questions and this is not the best way to do it. Re-executing the class was the best (and obvious) way. oops.
source to share
You need to subclass the proxy and implement your own lessThan()
.
QSortFilterProxyModel uses a virtual lessThan
method to determine the ordering between model indexes. Only the standard implementation lessThan
matches the role that is established setSortRole
. You can override it to provide custom sorting behavior, in which case it is setSortRole
deprecated.
The official documentation has a section on custom sorting and sample code: http://doc.qt.io/qt-5/qsortfilterproxymodel.html#details
source to share