File: upstream_55b6d6e6_Implement-Dolphin-style-natural-string-sorting.patch

package info (click to toggle)
ark 4%3A25.04.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 12,408 kB
  • sloc: cpp: 19,256; xml: 453; ansic: 244; sh: 12; makefile: 7
file content (105 lines) | stat: -rw-r--r-- 3,979 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
From 55b6d6e68616f2102fe3b7a4b4182ec6e403a3b1 Mon Sep 17 00:00:00 2001
From: Vladislav Kachegov <vladkachegov@gmail.com>
Date: Mon, 24 Feb 2025 15:02:49 +0300
Subject: [PATCH] Implement Dolphin-style natural string sorting

Enabled natural string sorting to match Dolphin's order, improving human-friendly
string comparison. Updated the function comment for clarity and noted potential
refactoring to a framework utility for maintainability.

BUG: 387969
---
 part/archivesortfiltermodel.cpp | 42 +++++++++++++++++++++++++++++++++
 part/archivesortfiltermodel.h   |  4 ++++
 2 files changed, 46 insertions(+)

diff --git a/part/archivesortfiltermodel.cpp b/part/archivesortfiltermodel.cpp
index dabac5ce6..b2fa8a489 100644
--- a/part/archivesortfiltermodel.cpp
+++ b/part/archivesortfiltermodel.cpp
@@ -10,11 +10,48 @@
 
 using namespace Kerfuffle;
 
+namespace
+{
+/**
+ * Performs a natural string comparison.
+ * This function compares strings in a way that is similar to natural human sorting order.
+ * It is adapted from the Dolphin KFileItemModel::stringCompare implementation.
+ *
+ * @note Consider refactoring this logic to a framework-level utility
+ * for improved maintainability and reusability across multiple projects.
+ *
+ * @return Integer less than, equal to, or greater than zero if the first argument is
+ * found, respectively, to be less than, to match, or be greater than the second.
+ */
+int naturalStringCompare(const QString &a, const QString &b, const QCollator &collator)
+{
+    // Split extension, taking into account it can be empty
+    constexpr QString::SectionFlags flags = QString::SectionSkipEmpty | QString::SectionIncludeLeadingSep;
+
+    // Sort by baseName first
+    const QString aBaseName = a.section(QLatin1Char('.'), 0, 0, flags);
+    const QString bBaseName = b.section(QLatin1Char('.'), 0, 0, flags);
+
+    const int res = collator.compare(aBaseName, bBaseName);
+    if (res != 0 || (aBaseName.length() == a.length() && bBaseName.length() == b.length())) {
+        return res;
+    }
+
+    // sliced() has undefined behavior when pos < 0 or pos > size().
+    Q_ASSERT(aBaseName.length() <= a.length() && aBaseName.length() >= 0);
+    Q_ASSERT(bBaseName.length() <= b.length() && bBaseName.length() >= 0);
+
+    // baseNames were equal, sort by extension
+    return collator.compare(a.sliced(aBaseName.length()), b.sliced(bBaseName.length()));
+}
+}
+
 ArchiveSortFilterModel::ArchiveSortFilterModel(QObject *parent)
     : QSortFilterProxyModel(parent)
 {
     // always enable recursive fitlering
     setRecursiveFilteringEnabled(true);
+    m_collator.setNumericMode(true);
 }
 
 ArchiveSortFilterModel::~ArchiveSortFilterModel()
@@ -36,6 +73,11 @@ bool ArchiveSortFilterModel::lessThan(const QModelIndex &leftIndex, const QModel
         return false;
     } else {
         switch (col) {
+        case DisplayName: {
+            const auto leftFullName = left->property(property.constData()).toString();
+            const auto rightFullName = right->property(property.constData()).toString();
+            return naturalStringCompare(leftFullName, rightFullName, m_collator) < 0;
+        }
         case Size:
         case CompressedSize:
             if (left->property(property.constData()).toULongLong() < right->property(property.constData()).toULongLong()) {
diff --git a/part/archivesortfiltermodel.h b/part/archivesortfiltermodel.h
index 3fa392d1b..3cd30b3ff 100644
--- a/part/archivesortfiltermodel.h
+++ b/part/archivesortfiltermodel.h
@@ -6,6 +6,7 @@
 #ifndef ARCHIVESORTFILTERMODEL_H
 #define ARCHIVESORTFILTERMODEL_H
 
+#include <QCollator>
 #include <QSortFilterProxyModel>
 
 class ArchiveSortFilterModel : public QSortFilterProxyModel
@@ -17,6 +18,9 @@ public:
     ~ArchiveSortFilterModel() override;
 
     bool lessThan(const QModelIndex &leftIndex, const QModelIndex &rightIndex) const override;
+
+private:
+    QCollator m_collator;
 };
 
 #endif // ARCHIVESORTFILTERMODEL_H
-- 
GitLab