Unsolved how to sort numbers for qstandarditemmodel
-
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(this->customWidget->model()); this->customWidget->ui->valueTableView()->setModel(proxyModel); this->customWidget->model()->sort(0);
My data would be number and I want to sort them.
e.g. 6, 22 , 2, 64
result: 2, 22, 6, 64
seems that the result is sorting string. Does anyone can give some examples for sorting number? Thank you. -
@clementNg
Are you sure you added the data items as numbers, not text, into the model? I can't remember, but it might be that they are treated as numbers if you do so, though possibly not......In which case, subclass
QSortFilterProxyModel
and override virtual https://doc.qt.io/qt-5/qsortfilterproxymodel.html#lessThan to convert arguments to numbers and do integer comparison.An alternative is to use https://doc.qt.io/qt-5/qsortfilterproxymodel.html#sortRole-prop to change the role used for sorting from
DisplayRole
to one for which you make your model'sdata(index, role)
accessor return a number, if you prefer that approach. -
@JonB
Thank you for your reply.
How can i set item as number? It can only insert string for the QStandardItem.Would you mind to give some explanations or examples for the second approach? What data should I set to sortRole so that It can sort by number?
-
@clementNg
Yes, it looks likeQStandardItem
only hassetText()
/text()
methods.So simplest is: subclass
QSortFilterProxyModel
, and use your class, so that we can overridelessThan()
, which is what is called by Qt to do sorting. Then that will look something like:virtual bool MySortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override { if (source_left.isValid() && source_right.isValid()) if (source_left.column() == 0) // whatever column(s) you store numbers in return source_left.data().toInt() < source_right.data().toInt(); return QSortFilterProxyModel::lessThan(source_left, source_right); }
I haven't put all the error checking in, but the important thing is see how we make numeric columns compare
toInt()
on their values, while other columns call the base class, which does string comparison. This is how we make the sort respect numbers as numbers. -
@JonB said in how to sort numbers for qstandarditemmodel:
Yes, it looks like QStandardItem only has setText()/text() methods.
-
@Christian-Ehrlicher
I didn't spotQStandardItemModel::setData()
either. I don't know where I sawsetText()
from.So: do you know whether the default
QSortFilterProxyModel::lessThan()
will (try to) compare as numbers instead of strings (if both sides are found to be numbers?), or what?@clementNg
How (which call exactly) puts your "numbers" into your (source) model? -
When the QVariant is an integer / double then it will be treated as such: https://code.woboq.org/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp.html#_ZN25QAbstractItemModelPrivate17isVariantLessThanERK8QVariantS2_N2Qt15CaseSensitivityEb
-
@Christian-Ehrlicher
Yep! Looks like it's all based on the type of the left item :) -
@Christian-Ehrlicher
you notify me that I have triggered to edit the row so the data converted from number to QString . If I didn't do anything and sort the list, it can be sorted. The main problem is to ensure the data type is number but I dun know how to guarantee that. -
@clementNg said in how to sort numbers for qstandarditemmodel:
The main problem is to ensure the data type is number but I dun know how to guarantee that.
Depending on where you get your number from, if it's a string, convert it to a number before
setData()
, like we said. -
I have one more question. are there any differences between
setData(QVariant::fromValue(integer))
and
setData(QVariant(integer))
? -
@clementNg
They will both store an integer, they are the same. But you don't need to do that conversion anyway. Just doint intValue = 999; setData(intValue);
and that will work, it (C++) will do aQVariant(intValue)
behind the scenes. AndQString::toInt()
will convert a string to an integer.If you have subclassed the model, or the model items, write yourself a
bool setIntValue(int value)
and aint intValue()
appropriately, and use those to set/get all your integer values (instead ofsetData()
/data()
), then you will know what it is you are storing in the data for sure.