Add natural sorting and case-insensitive sorting for all role-types

Summary:
 Add natural sorting and case-insensitive sorting, for all role-types
that benefit from.

BUG: 406296
FIXED-IN: 19.12.2

Test Plan:
Sort by any role type specified in `isRoleValueNatural()`
Before: Sorting is always case sensitive
After: Sorting according to 'Sorting mode' in configuration.

Reviewers: #dolphin, nicolasfella, meven, elvisangelaccio, ngraham

Reviewed By: #dolphin, meven, elvisangelaccio, ngraham

Subscribers: cfeck, meven, kfm-devel

Tags: #dolphin

Differential Revision: https://phabricator.kde.org/D25741
This commit is contained in:
George Vogiatzis 2020-01-28 08:50:06 -07:00 committed by Nate Graham
parent c2fa8ae9ab
commit 9e3418bd55
2 changed files with 39 additions and 9 deletions

View file

@ -1187,12 +1187,20 @@ void KFileItemModel::insertItems(QList<ItemData*>& newItems)
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 (isRoleValueNatural(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 @@ void KFileItemModel::sort(const QList<KFileItemModel::ItemData*>::iterator &begi
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 || isRoleValueNatural(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);
@ -1835,6 +1843,8 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const
result = -1;
} else if (roleValueA.isEmpty() && !roleValueB.isEmpty()) {
result = +1;
} else if (isRoleValueNatural(m_sortRole)) {
result = stringCompare(roleValueA, roleValueB, collator);
} else {
result = QString::compare(roleValueA, roleValueB);
}

View file

@ -355,6 +355,11 @@ private:
QHash<QByteArray, QVariant> retrieveData(const KFileItem& item, const ItemData* parent) const;
/**
* @return True if role values benefit from natural or case insensitive sorting.
*/
static bool isRoleValueNatural(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,12 +509,27 @@ private:
friend class DolphinPart; // Accesses m_dirLister
};
inline bool KFileItemModel::isRoleValueNatural(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();
}
inline bool KFileItemModel::isChildItem(int index) const
{
if (m_itemData.at(index)->parent) {