X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/bfacf4218a30c5e4dbe49305d67e6bc63bfbf05b..cdccbf471a88a34d7673712f6f6bead559dcc5be:/src/kitemviews/kfileitemmodel.cpp diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index c694da9f2..ad0fb31a7 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -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> 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> 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 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::rolesInformation() { static QList rolesInfo; @@ -894,24 +930,7 @@ QList 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 ¤t, 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 ¤t, const QByteArray &previous, bool resortItems) +{ + Q_UNUSED(previous) + m_groupRole = typeForRole(current); + + if (!m_requestRole[m_sortRole]) { + QSet 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> 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> 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 &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 },