Reputation: 1111
How to sort the following numbers that are in the column of QTableView
? I use QSortFilterProxyModel
for sorting.
123 B
1 KB
131 KB
3 GB
322 GB
337 KB
3 MB
555 KB
52 TB
Upvotes: 2
Views: 439
Reputation: 11555
Basically subclass QSortFilterProxyModel
and implement lessThan
.
Also, it would be better if you use a separate model's role to store the actual size in bytes instead of converting the displayed value. In this case, the comparison method would be something like
class MySortFilterProxyModel : public QSortFilterProxyModel
{
public:
MySortFilterProxyModel(QObject *parent = 0);
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override {
const auto left_bytes = left.data(SIZE_IN_BYTES_ROLE).toULongLong();
const auto right_bytes = right.data(SIZE_IN_BYTES_ROLE).toULongLong();
return left_bytes < right_bytes;
}
};
If, for any reason, you still use the display role, you should get the text from the indices and convert the string to bytes before comparing. For the conversion function, you have several options, like splitting the string into the number and the unit, and then using a look-up table to get the multiplier factor of the unit.
class MySortFilterProxyModel : public QSortFilterProxyModel
{
public:
MySortFilterProxyModel(QObject *parent = 0);
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override {
const auto left_bytes = toBytes(left.data().toString());
const auto right_bytes = toBytes(right.data().toString());
return left_bytes < right_bytes;
}
private:
static int64_t toBytes(const QString& size)
{
static const QMap<QString, int64_t> s_sizes = {
{"b", 1},
{"kb", 1024},
{"mb", 1024 * 1024},
{"gb", 1024 * 1024 * 1204},
{"tb", 1024 * 1024 * 1204 * 1024},
};
const auto tokens = size.toLower().split(' ', QString::SkipEmptyParts);
if (tokens.size() == 0) return 0; // error
const auto number = tokens[0].toInt();
if (tokens.size() == 1) return number; // assume bytes
return number * s_sizes.value(tokens[1], 0); // 0 for unknown units
}
};
You can check a more complete example of how to subclass QSortFilterProxyModel
here.
Upvotes: 2
Reputation: 61
When I have to define my comparison I write some model inherited from QSortFilterProxyModel and override virtual function QSortFilterProxyModel::lessThan.
Upvotes: 0