]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodel.cpp
Merge remote-tracking branch 'fork/work/zakharafoniam/useful-groups'
[dolphin.git] / src / kitemviews / kfileitemmodel.cpp
index a6f90b9f5adcf4ad0158ffe43c92b293eb456720..603c16e0d37ff816488aa69b9122308335a36d45 100644 (file)
@@ -20,6 +20,9 @@
 #include <KLocalizedString>
 #include <KUrlMimeData>
 
+#ifndef QT_NO_ACCESSIBILITY
+#include <QAccessible>
+#endif
 #include <QElapsedTimer>
 #include <QIcon>
 #include <QMimeData>
@@ -203,13 +206,20 @@ bool KFileItemModel::setData(int index, const QHash<QByteArray, QVariant> &value
         return false;
     }
 
-    m_itemData[index]->values = currentValues;
     if (changedRoles.contains("text")) {
         QUrl url = m_itemData[index]->item.url();
+        m_items.remove(url);
         url = url.adjusted(QUrl::RemoveFilename);
         url.setPath(url.path() + currentValues["text"].toString());
         m_itemData[index]->item.setUrl(url);
+        m_items.insert(url, index);
+
+        if (!changedRoles.contains("url")) {
+            changedRoles.insert("url");
+            currentValues["url"] = url;
+        }
     }
+    m_itemData[index]->values = currentValues;
 
     emitItemsChangedAndTriggerResorting(KItemRangeList() << KItemRange(index, 1), changedRoles);
 
@@ -326,16 +336,32 @@ QMimeData *KFileItemModel::createMimeData(const KItemSet &indexes) const
     return data;
 }
 
+namespace
+{
+QString removeMarks(const QString &original)
+{
+    const auto normalized = original.normalized(QString::NormalizationForm_D);
+    QString res;
+    for (auto ch : normalized) {
+        if (!ch.isMark()) {
+            res.append(ch);
+        }
+    }
+    return res;
+}
+}
+
 int KFileItemModel::indexForKeyboardSearch(const QString &text, int startFromIndex) const
 {
+    const auto noMarkText = removeMarks(text);
     startFromIndex = qMax(0, startFromIndex);
     for (int i = startFromIndex; i < count(); ++i) {
-        if (fileItem(i).text().startsWith(text, Qt::CaseInsensitive)) {
+        if (removeMarks(fileItem(i).text()).startsWith(noMarkText, Qt::CaseInsensitive)) {
             return i;
         }
     }
     for (int i = 0; i < startFromIndex; ++i) {
-        if (fileItem(i).text().startsWith(text, Qt::CaseInsensitive)) {
+        if (removeMarks(fileItem(i).text()).startsWith(noMarkText, Qt::CaseInsensitive)) {
             return i;
         }
     }
@@ -2424,7 +2450,24 @@ int KFileItemModel::stringCompare(const QString &a, const QString &b, const QCol
     QMutexLocker collatorLock(s_collatorMutex());
 
     if (m_naturalSorting) {
-        return collator.compare(a, b);
+        // 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('.', 0, 0, flags);
+        const QString bBaseName = b.section('.', 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()));
     }
 
     const int result = QString::compare(a, b, collator.caseSensitivity());
@@ -2658,7 +2701,7 @@ KFileItemModel::timeRoleGroup(const std::function<QDateTime(const ItemData *)> &
                         "part of the text that should not be formatted as a date",
                         "'Yesterday' (MMMM, yyyy)");
                     const QString translatedFormat = format.toString();
-                    if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+                    if (const int count = translatedFormat.count(QLatin1Char('\'')); count >= 2 && count % 2 == 0) {
                         newGroupValue = locale.toString(fileTime, translatedFormat);
                         newGroupValue = i18nc(
                             "Can be used to script translation of "
@@ -2690,7 +2733,7 @@ KFileItemModel::timeRoleGroup(const std::function<QDateTime(const ItemData *)> &
                         "part of the text that should not be formatted as a date",
                         "'One Week Ago' (MMMM, yyyy)");
                     const QString translatedFormat = format.toString();
-                    if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+                    if (const int count = translatedFormat.count(QLatin1Char('\'')); count >= 2 && count % 2 == 0) {
                         newGroupValue = locale.toString(fileTime, translatedFormat);
                         newGroupValue = i18nc(
                             "Can be used to script translation of "
@@ -2711,7 +2754,7 @@ KFileItemModel::timeRoleGroup(const std::function<QDateTime(const ItemData *)> &
                         "part of the text that should not be formatted as a date",
                         "'Two Weeks Ago' (MMMM, yyyy)");
                     const QString translatedFormat = format.toString();
-                    if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+                    if (const int count = translatedFormat.count(QLatin1Char('\'')); count >= 2 && count % 2 == 0) {
                         newGroupValue = locale.toString(fileTime, translatedFormat);
                         newGroupValue = i18nc(
                             "Can be used to script translation of "
@@ -2732,7 +2775,7 @@ KFileItemModel::timeRoleGroup(const std::function<QDateTime(const ItemData *)> &
                         "part of the text that should not be formatted as a date",
                         "'Three Weeks Ago' (MMMM, yyyy)");
                     const QString translatedFormat = format.toString();
-                    if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+                    if (const int count = translatedFormat.count(QLatin1Char('\'')); count >= 2 && count % 2 == 0) {
                         newGroupValue = locale.toString(fileTime, translatedFormat);
                         newGroupValue = i18nc(
                             "Can be used to script translation of "
@@ -2753,7 +2796,7 @@ KFileItemModel::timeRoleGroup(const std::function<QDateTime(const ItemData *)> &
                         "part of the text that should not be formatted as a date",
                         "'Earlier on' MMMM, yyyy");
                     const QString translatedFormat = format.toString();
-                    if (translatedFormat.count(QLatin1Char('\'')) == 2) {
+                    if (const int count = translatedFormat.count(QLatin1Char('\'')); count >= 2 && count % 2 == 0) {
                         newGroupValue = locale.toString(fileTime, translatedFormat);
                         newGroupValue = i18nc(
                             "Can be used to script translation of "
@@ -3082,6 +3125,7 @@ const KFileItemModel::RoleInfoMap *KFileItemModel::rolesInfoMap(int &count)
         { "releaseYear",         ReleaseYearRole,         kli18nc("@label", "Release Year"),         kli18nc("@label", "Audio"),    KLazyLocalizedString(),                    true,            true  },
         { "aspectRatio",         AspectRatioRole,         kli18nc("@label", "Aspect Ratio"),         kli18nc("@label", "Video"),    KLazyLocalizedString(),                    true,            true  },
         { "frameRate",           FrameRateRole,           kli18nc("@label", "Frame Rate"),           kli18nc("@label", "Video"),    KLazyLocalizedString(),                    true,            true  },
+        { "duration",            DurationRole,            kli18nc("@label", "Duration"),             kli18nc("@label", "Video"),    KLazyLocalizedString(),                    true,            true  },
         { "path",                PathRole,                kli18nc("@label", "Path"),                 kli18nc("@label", "Other"),    KLazyLocalizedString(),                    false,           false },
         { "extension",           ExtensionRole,           kli18nc("@label", "File Extension"),       kli18nc("@label", "Other"),    KLazyLocalizedString(),                    false,           false },
         { "deletiontime",        DeletionTimeRole,        kli18nc("@label", "Deletion Time"),        kli18nc("@label", "Other"),    KLazyLocalizedString(),                    false,           false },