]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodel.cpp
"Group by" exists, group sorting rule is separate from sorting rule. Very WIP and...
[dolphin.git] / src / kitemviews / kfileitemmodel.cpp
index c694da9f256f041f91d1ed0712032474db7266c8..ad0fb31a7f703dfae86ddf0b369d2e15f2b2ea79 100644 (file)
@@ -34,7 +34,7 @@ Q_GLOBAL_STATIC(QRecursiveMutex, s_collatorMutex)
 // #define KFILEITEMMODEL_DEBUG
 
 KFileItemModel::KFileItemModel(QObject *parent)
-    : KItemModelBase("text", parent)
+    : KItemModelBase("text", "text", parent)
     , m_dirLister(nullptr)
     , m_sortDirsFirst(true)
     , m_sortHiddenLast(false)
@@ -387,7 +387,10 @@ QList<QPair<int, QVariant>> KFileItemModel::groups() const
         QElapsedTimer timer;
         timer.start();
 #endif
-        switch (typeForRole(sortRole())) {
+        switch (typeForRole(groupRole())) {
+        case NoRole:
+            m_groups.clear();
+            break;
         case NameRole:
             m_groups = nameRoleGroups();
             break;
@@ -421,7 +424,7 @@ QList<QPair<int, QVariant>> KFileItemModel::groups() const
             m_groups = ratingRoleGroups();
             break;
         default:
-            m_groups = genericStringRoleGroups(sortRole());
+            m_groups = genericStringRoleGroups(groupRole());
             break;
         }
 
@@ -886,6 +889,39 @@ void KFileItemModel::removeFilteredChildren(const KItemRangeList &itemRanges)
     }
 }
 
+KFileItemModel::RoleInfo KFileItemModel::roleInformation(const QByteArray &role)
+{
+    static QHash<QByteArray, RoleInfo> information;
+    if (information.isEmpty()) {
+        int count = 0;
+        const RoleInfoMap *map = rolesInfoMap(count);
+        for (int i = 0; i < count; ++i) {
+            RoleInfo info;
+            info.role = map[i].role;
+            info.translation = map[i].roleTranslation.toString();
+            if (!map[i].groupTranslation.isEmpty()) {
+                info.group = map[i].groupTranslation.toString();
+            } else {
+                // For top level roles, groupTranslation is 0. We must make sure that
+                // info.group is an empty string then because the code that generates
+                // menus tries to put the actions into sub menus otherwise.
+                info.group = QString();
+            }
+            info.requiresBaloo = map[i].requiresBaloo;
+            info.requiresIndexer = map[i].requiresIndexer;
+            if (!map[i].tooltipTranslation.isEmpty()) {
+                info.tooltip = map[i].tooltipTranslation.toString();
+            } else {
+                info.tooltip = QString();
+            }
+
+            information.insert(map[i].role, info);
+        }
+    }
+
+    return information.value(role);
+}
+
 QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation()
 {
     static QList<RoleInfo> rolesInfo;
@@ -894,24 +930,7 @@ QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation()
         const RoleInfoMap *map = rolesInfoMap(count);
         for (int i = 0; i < count; ++i) {
             if (map[i].roleType != NoRole) {
-                RoleInfo info;
-                info.role = map[i].role;
-                info.translation = map[i].roleTranslation.toString();
-                if (!map[i].groupTranslation.isEmpty()) {
-                    info.group = map[i].groupTranslation.toString();
-                } else {
-                    // For top level roles, groupTranslation is 0. We must make sure that
-                    // info.group is an empty string then because the code that generates
-                    // menus tries to put the actions into sub menus otherwise.
-                    info.group = QString();
-                }
-                info.requiresBaloo = map[i].requiresBaloo;
-                info.requiresIndexer = map[i].requiresIndexer;
-                if (!map[i].tooltipTranslation.isEmpty()) {
-                    info.tooltip = map[i].tooltipTranslation.toString();
-                } else {
-                    info.tooltip = QString();
-                }
+                RoleInfo info = roleInformation(map[i].role);
                 rolesInfo.append(info);
             }
         }
@@ -942,11 +961,40 @@ void KFileItemModel::onSortRoleChanged(const QByteArray &current, const QByteArr
     }
 }
 
-void KFileItemModel::onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous)
+void KFileItemModel::onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous, bool resortItems)
 {
     Q_UNUSED(current)
     Q_UNUSED(previous)
-    resortAllItems();
+
+    if (resortItems) {
+        resortAllItems();
+    }
+}
+
+void KFileItemModel::onGroupRoleChanged(const QByteArray &current, const QByteArray &previous, bool resortItems)
+{
+    Q_UNUSED(previous)
+    m_groupRole = typeForRole(current);
+
+    if (!m_requestRole[m_sortRole]) {
+        QSet<QByteArray> newRoles = m_roles;
+        newRoles << current;
+        setRoles(newRoles);
+    }
+
+    if (resortItems) {
+        resortAllItems();
+    }
+}
+
+void KFileItemModel::onGroupOrderChanged(Qt::SortOrder current, Qt::SortOrder previous, bool resortItems)
+{
+    Q_UNUSED(current)
+    Q_UNUSED(previous)
+
+    if (resortItems) {
+        resortAllItems();
+    }
 }
 
 void KFileItemModel::loadSortingSettings()
@@ -1001,8 +1049,44 @@ void KFileItemModel::resortAllItems()
     m_items.clear();
     m_items.reserve(itemCount);
 
-    // Resort the items
-    sort(m_itemData.begin(), m_itemData.end());
+    const QList<QPair<int, QVariant>> oldGroups = m_groups;
+
+    if (groupedSorting() && m_groupRole) {
+        // Hacky way to implement grouped sorting without rewriting more code.
+        // 1. Sort all items by grouping criteria. "Folders first" priority to be ignored.
+        // 2. Generate groups, which will stay usable after in-group sorting.
+        // 3. Perform sorts by the original sorting criteria inside groups.
+
+        RoleType originalSortRole = m_sortRole;
+        Qt::SortOrder originalSortOrder = sortOrder();
+        bool originalSortDirsFirst = m_sortDirsFirst;
+        m_sortRole = m_groupRole;
+        setSortOrder(groupOrder(), false);
+        m_sortDirsFirst = false;
+
+        sort(m_itemData.begin(), m_itemData.end());
+        m_groups.clear();
+        groups();
+
+        m_sortRole = originalSortRole;
+        setSortOrder(originalSortOrder, false);
+        m_sortDirsFirst = originalSortDirsFirst;
+
+        int lastIndex = 0, newIndex = 0;
+        for (int i = 0; i < m_groups.count() - 1; ++i) {
+            qCritical() << m_groups[i];
+            fflush(stderr);
+            newIndex = m_groups[i + 1].first;
+            sort(m_itemData.begin() + lastIndex, m_itemData.begin() + newIndex);
+            lastIndex = newIndex;
+        }
+    } else {
+        if (!m_groups.isEmpty()) {
+            m_groups.clear();
+        }
+        sort(m_itemData.begin(), m_itemData.end());
+    }
+
     for (int i = 0; i < itemCount; ++i) {
         m_items.insert(m_itemData.at(i)->item.url(), i);
     }
@@ -1037,15 +1121,12 @@ void KFileItemModel::resortAllItems()
 
         Q_EMIT itemsMoved(KItemRange(firstMovedIndex, movedItemsCount), movedToIndexes);
     } else if (groupedSorting()) {
-        // The groups might have changed even if the order of the items has not.
-        const QList<QPair<int, QVariant>> oldGroups = m_groups;
-        m_groups.clear();
-        if (groups() != oldGroups) {
+        if (m_groups != oldGroups) {
             Q_EMIT groupsChanged();
         }
     }
 
-#ifdef KFILEITEMMODEL_DEBUG
+#ifdef KFILEITEMMODEL_DEBUGf
     qCDebug(DolphinDebug) << "[TIME] Resorting of" << itemCount << "items:" << timer.elapsed();
 #endif
 }
@@ -1559,6 +1640,8 @@ void KFileItemModel::insertItems(QList<ItemData *> &newItems)
         std::reverse(itemRanges.begin(), itemRanges.end());
     }
 
+    // N
+    //resortAllItems();
     // The indexes in m_items are not correct anymore. Therefore, we clear m_items.
     // It will be re-populated with the updated indices if index(const QUrl&) is called.
     m_items.clear();
@@ -2725,7 +2808,7 @@ const KFileItemModel::RoleInfoMap *KFileItemModel::rolesInfoMap(int &count)
     static const RoleInfoMap rolesInfoMap[] = {
         // clang-format off
     //  |         role           |        roleType        |                role translation          |         group translation                                        | requires Baloo | requires indexer
-        { nullptr,               NoRole,                  KLazyLocalizedString(),                    KLazyLocalizedString(),        KLazyLocalizedString(),                    false,           false },
+        { nullptr,               NoRole,                  kli18nc("@label", "None"),                 KLazyLocalizedString(),        KLazyLocalizedString(),                    false,           false },
         { "text",                NameRole,                kli18nc("@label", "Name"),                 KLazyLocalizedString(),        KLazyLocalizedString(),                    false,           false },
         { "size",                SizeRole,                kli18nc("@label", "Size"),                 KLazyLocalizedString(),        KLazyLocalizedString(),                    false,           false },
         { "modificationtime",    ModificationTimeRole,    kli18nc("@label", "Modified"),             KLazyLocalizedString(),        kli18nc("@tooltip", "The date format can be selected in settings."),                    false,           false },