]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodel.cpp
Make non-empty textual columns come first in sorting
[dolphin.git] / src / kitemviews / kfileitemmodel.cpp
index 3cc140701634770d1d82d4d5d21de17a0d60babe..091044c06c4e00480db701157891d3dbd49a525f 100644 (file)
@@ -917,6 +917,7 @@ void KFileItemModel::resortAllItems()
 
 void KFileItemModel::slotCompleted()
 {
+    m_maximumUpdateIntervalTimer->stop();
     dispatchPendingItemsToInsert();
 
     if (!m_urlsToExpand.isEmpty()) {
@@ -1007,7 +1008,7 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis
         }
     }
 
-    if (useMaximumUpdateInterval() && !m_maximumUpdateIntervalTimer->isActive()) {
+    if (!m_maximumUpdateIntervalTimer->isActive()) {
         // Assure that items get dispatched if no completed() or canceled() signal is
         // emitted during the maximum update interval.
         m_maximumUpdateIntervalTimer->start();
@@ -1828,8 +1829,15 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const
 
     default: {
         const QByteArray role = roleForType(m_sortRole);
-        result = QString::compare(a->values.value(role).toString(),
-                                  b->values.value(role).toString());
+        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 = QString::compare(roleValueA, roleValueB);
+        }
         break;
     }
 
@@ -1875,11 +1883,6 @@ int KFileItemModel::stringCompare(const QString& a, const QString& b, const QCol
     return QString::compare(a, b, Qt::CaseSensitive);
 }
 
-bool KFileItemModel::useMaximumUpdateInterval() const
-{
-    return !m_dirLister->url().isLocalFile();
-}
-
 QList<QPair<int, QVariant> > KFileItemModel::nameRoleGroups() const
 {
     Q_ASSERT(!m_itemData.isEmpty());
@@ -1905,8 +1908,37 @@ QList<QPair<int, QVariant> > KFileItemModel::nameRoleGroups() const
         if (firstChar != newFirstChar) {
             QString newGroupValue;
             if (newFirstChar.isLetter()) {
-                // Put together compatibility equivalent letters like latin 'A' and umlaut 'A' from the German locale
-                newGroupValue = QString(newFirstChar).normalized(QString::NormalizationForm_KD).at(0);
+
+                if (m_collator.compare(newFirstChar, QChar(QLatin1Char('A'))) >= 0 && m_collator.compare(newFirstChar, QChar(QLatin1Char('Z'))) <= 0) {
+                    // WARNING! Symbols based on latin 'Z' like 'Z' with acute are treated wrong as non Latin and put in a new group.
+
+                    // Try to find a matching group in the range 'A' to 'Z'.
+                    static std::vector<QChar> lettersAtoZ;
+                    lettersAtoZ.reserve('Z' - 'A' + 1);
+                    if (lettersAtoZ.empty()) {
+                        for (char c = 'A'; c <= 'Z'; ++c) {
+                            lettersAtoZ.push_back(QLatin1Char(c));
+                        }
+                    }
+
+                    auto localeAwareLessThan = [this](QChar c1, QChar c2) -> bool {
+                        return m_collator.compare(c1, c2) < 0;
+                    };
+
+                    std::vector<QChar>::iterator it = std::lower_bound(lettersAtoZ.begin(), lettersAtoZ.end(), newFirstChar, localeAwareLessThan);
+                    if (it != lettersAtoZ.end()) {
+                        if (localeAwareLessThan(newFirstChar, *it)) {
+                            // newFirstChar belongs to the group preceding *it.
+                            // Example: for an umlaut 'A' in the German locale, *it would be 'B' now.
+                            --it;
+                        }
+                        newGroupValue = *it;
+                    }
+
+                } else {
+                    // Symbols from non Latin-based scripts
+                    newGroupValue = newFirstChar;
+                }
             } else if (newFirstChar >= QLatin1Char('0') && newFirstChar <= QLatin1Char('9')) {
                 // Apply group '0 - 9' for any name that starts with a digit
                 newGroupValue = i18nc("@title:group Groups that start with a digit", "0 - 9");