Returns from function as soon as we encounter a decisive comparison,
while ensuring the fallbacks provide a stable sorting. Added comment
to clarify the situation.
int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const QCollator& collator) const
{
int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const QCollator& collator) const
{
+ // This function must never return 0, because that would break stable
+ // sorting, which leads to all kinds of bugs.
+ // See: https://bugs.kde.org/show_bug.cgi?id=433247
+ // If two items have equal sort values, let the fallbacks at the bottom of
+ // the function handle it.
const KFileItem& itemA = a->item;
const KFileItem& itemB = b->item;
const KFileItem& itemA = a->item;
const KFileItem& itemB = b->item;
auto valueA = a->values.value("count");
auto valueB = b->values.value("count");
if (valueA.isNull()) {
auto valueA = a->values.value("count");
auto valueB = b->values.value("count");
if (valueA.isNull()) {
- if (valueB.isNull()) {
- result = 0;
- break;
- } else {
- result = -1;
- break;
+ if (!valueB.isNull()) {
+ return -1;
}
} else if (valueB.isNull()) {
}
} else if (valueB.isNull()) {
} else {
if (valueA.toLongLong() < valueB.toLongLong()) {
} else {
if (valueA.toLongLong() < valueB.toLongLong()) {
} else if (valueA.toLongLong() > valueB.toLongLong()) {
} else if (valueA.toLongLong() > valueB.toLongLong()) {
- result = +1;
- break;
- } else {
- result = 0;
- break;
KIO::filesize_t sizeA = 0;
if (itemA.isDir()) {
sizeA = a->values.value("size").toULongLong();
KIO::filesize_t sizeA = 0;
if (itemA.isDir()) {
sizeA = a->values.value("size").toULongLong();
} else {
sizeB = itemB.size();
}
} else {
sizeB = itemB.size();
}
- if (sizeA > sizeB) {
- result = +1;
- } else if (sizeA < sizeB) {
- result = -1;
- } else {
- result = 0;
+ if (sizeA < sizeB) {
+ return -1;
+ } else if (sizeA > sizeB) {
+ return +1;
const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
if (dateTimeA < dateTimeB) {
const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
if (dateTimeA < dateTimeB) {
} else if (dateTimeA > dateTimeB) {
} else if (dateTimeA > dateTimeB) {
const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
if (dateTimeA < dateTimeB) {
const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
if (dateTimeA < dateTimeB) {
} else if (dateTimeA > dateTimeB) {
} else if (dateTimeA > dateTimeB) {
const QDateTime dateTimeA = a->values.value("deletiontime").toDateTime();
const QDateTime dateTimeB = b->values.value("deletiontime").toDateTime();
if (dateTimeA < dateTimeB) {
const QDateTime dateTimeA = a->values.value("deletiontime").toDateTime();
const QDateTime dateTimeB = b->values.value("deletiontime").toDateTime();
if (dateTimeA < dateTimeB) {
} else if (dateTimeA > dateTimeB) {
} else if (dateTimeA > dateTimeB) {
const QString roleValueA = a->values.value(role).toString();
const QString roleValueB = b->values.value(role).toString();
if (!roleValueA.isEmpty() && roleValueB.isEmpty()) {
const QString roleValueA = a->values.value(role).toString();
const QString roleValueB = b->values.value(role).toString();
if (!roleValueA.isEmpty() && roleValueB.isEmpty()) {
} else if (roleValueA.isEmpty() && !roleValueB.isEmpty()) {
} else if (roleValueA.isEmpty() && !roleValueB.isEmpty()) {
} else if (isRoleValueNatural(m_sortRole)) {
result = stringCompare(roleValueA, roleValueB, collator);
} else {
} else if (isRoleValueNatural(m_sortRole)) {
result = stringCompare(roleValueA, roleValueB, collator);
} else {