Index: src/kitemviews/kfileitemmodel.h =================================================================== --- src/kitemviews/kfileitemmodel.h +++ src/kitemviews/kfileitemmodel.h @@ -355,6 +355,11 @@ QHash retrieveData(const KFileItem& item, const ItemData* parent) const; + /** + * @return True if we need role values to QString for sorting. + */ + static bool stringRolesTrue(const RoleType roleType); + /** * @return True if \a a has a KFileItem whose text is 'less than' the one * of \a b according to QString::operator<(const QString&). @@ -504,6 +509,22 @@ friend class DolphinPart; // Accesses m_dirLister }; +inline bool KFileItemModel::stringRolesTrue(RoleType roleType) +{ + return (roleType == TypeRole || + roleType == TagsRole || + roleType == CommentRole || + roleType == TitleRole || + roleType == ArtistRole || + roleType == GenreRole || + roleType == AlbumRole || + roleType == PathRole || + roleType == DestinationRole || + roleType == OriginUrlRole || + roleType == OwnerRole || + roleType == GroupRole); +} + inline bool KFileItemModel::nameLessThan(const ItemData* a, const ItemData* b) { return a->item.text() < b->item.text(); Index: src/kitemviews/kfileitemmodel.cpp =================================================================== --- src/kitemviews/kfileitemmodel.cpp +++ src/kitemviews/kfileitemmodel.cpp @@ -1187,12 +1187,20 @@ m_groups.clear(); prepareItemsForSorting(newItems); - if (m_sortRole == NameRole && m_naturalSorting) { - // Natural sorting of items can be very slow. However, it becomes much - // faster if the input sequence is already mostly sorted. Therefore, we - // first sort 'newItems' according to the QStrings returned by - // KFileItem::text() using QString::operator<(), which is quite fast. - parallelMergeSort(newItems.begin(), newItems.end(), nameLessThan, QThread::idealThreadCount()); + // Natural sorting of items can be very slow. However, it becomes much faster + // if the input sequence is already mostly sorted. Therefore, we first sort + // 'newItems' according to the QStrings using QString::operator<(), which is quite fast. + if (m_naturalSorting) { + if (m_sortRole == NameRole) { + parallelMergeSort(newItems.begin(), newItems.end(), nameLessThan, QThread::idealThreadCount()); + } else if (stringRolesTrue(m_sortRole)) { + auto lambdaLessThan = [&] (const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) + { + const QByteArray role = roleForType(m_sortRole); + return a->values.value(role).toString() < b->values.value(role).toString(); + }; + parallelMergeSort(newItems.begin(), newItems.end(), lambdaLessThan, QThread::idealThreadCount()); + } } sort(newItems.begin(), newItems.end()); @@ -1726,8 +1734,8 @@ return lessThan(a, b, m_collator); }; - if (m_sortRole == NameRole) { - // Sorting by name can be expensive, in particular if natural sorting is + if (m_sortRole == NameRole || stringRolesTrue(m_sortRole)) { + // Sorting by string can be expensive, in particular if natural sorting is // enabled. Use all CPU cores to speed up the sorting process. static const int numberOfThreads = QThread::idealThreadCount(); parallelMergeSort(begin, end, lambdaLessThan, numberOfThreads); @@ -1827,6 +1835,31 @@ break; } + case TypeRole: + case TagsRole: + case CommentRole: + case TitleRole: + case ArtistRole: + case GenreRole: + case AlbumRole: + case PathRole: + case DestinationRole: + case OriginUrlRole: + case OwnerRole: + case GroupRole: { + const QByteArray role = roleForType(m_sortRole); + const QString roleValueA = a->values.value(role).toString(); + const QString roleValueB = b->values.value(role).toString(); + if (!roleValueA.isEmpty() && roleValueB.isEmpty()) { + result = -1; + } else if (roleValueA.isEmpty() && !roleValueB.isEmpty()) { + result = +1; + } else { + result = stringCompare(roleValueA, roleValueB, collator); + } + break; + } + default: { const QByteArray role = roleForType(m_sortRole); const QString roleValueA = a->values.value(role).toString();