X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/013ca76a31c3a4c897a505732748e7c66426f535..3338c2834af81e00c3f2b73ad7061fefce89f226:/src/kitemviews/kfileitemmodel.cpp diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index 0f5cffed1..5ac6f9be1 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -8,24 +8,24 @@ #include "kfileitemmodel.h" +#include "dolphin_contentdisplaysettings.h" #include "dolphin_generalsettings.h" -#include "dolphin_detailsmodesettings.h" #include "dolphindebug.h" #include "private/kfileitemmodelsortalgorithm.h" #include #include -#include #include #include +#include #include +#include #include #include +#include #include #include -#include -#include #include #include @@ -33,25 +33,25 @@ Q_GLOBAL_STATIC(QRecursiveMutex, s_collatorMutex) // #define KFILEITEMMODEL_DEBUG -KFileItemModel::KFileItemModel(QObject* parent) : - KItemModelBase("text", parent), - m_dirLister(nullptr), - m_sortDirsFirst(true), - m_sortHiddenLast(false), - m_sortRole(NameRole), - m_sortingProgressPercent(-1), - m_roles(), - m_itemData(), - m_items(), - m_filter(), - m_filteredItems(), - m_requestRole(), - m_maximumUpdateIntervalTimer(nullptr), - m_resortAllItemsTimer(nullptr), - m_pendingItemsToInsert(), - m_groups(), - m_expandedDirs(), - m_urlsToExpand() +KFileItemModel::KFileItemModel(QObject *parent) + : KItemModelBase("text", parent) + , m_dirLister(nullptr) + , m_sortDirsFirst(true) + , m_sortHiddenLast(false) + , m_sortRole(NameRole) + , m_sortingProgressPercent(-1) + , m_roles() + , m_itemData() + , m_items() + , m_filter() + , m_filteredItems() + , m_requestRole() + , m_maximumUpdateIntervalTimer(nullptr) + , m_resortAllItemsTimer(nullptr) + , m_pendingItemsToInsert() + , m_groups() + , m_expandedDirs() + , m_urlsToExpand() { m_collator.setNumericMode(true); @@ -61,7 +61,7 @@ KFileItemModel::KFileItemModel(QObject* parent) : m_dirLister->setAutoErrorHandlingEnabled(false); m_dirLister->setDelayedMimeTypes(true); - const QWidget* parentWidget = qobject_cast(parent); + const QWidget *parentWidget = qobject_cast(parent); if (parentWidget) { m_dirLister->setMainWindow(parentWidget->window()); } @@ -129,6 +129,8 @@ void KFileItemModel::refreshDirectory(const QUrl &url) } m_dirLister->openUrl(url, KDirLister::Reload); + + Q_EMIT directoryRefreshing(); } QUrl KFileItemModel::directory() const @@ -149,7 +151,7 @@ int KFileItemModel::count() const QHash KFileItemModel::data(int index) const { if (index >= 0 && index < count()) { - ItemData* data = m_itemData.at(index); + ItemData *data = m_itemData.at(index); if (data->values.isEmpty()) { data->values = retrieveData(data->item, data->parent); } else if (data->values.count() <= 2 && data->values.value("isExpanded").toBool()) { @@ -171,7 +173,7 @@ QHash KFileItemModel::data(int index) const return QHash(); } -bool KFileItemModel::setData(int index, const QHash& values) +bool KFileItemModel::setData(int index, const QHash &values) { if (index < 0 || index >= count()) { return false; @@ -238,7 +240,11 @@ bool KFileItemModel::sortHiddenLast() const void KFileItemModel::setShowHiddenFiles(bool show) { +#if KIO_VERSION < QT_VERSION_CHECK(5, 100, 0) m_dirLister->setShowingDotFiles(show); +#else + m_dirLister->setShowHiddenFiles(show); +#endif m_dirLister->emitChanges(); if (show) { dispatchPendingItemsToInsert(); @@ -247,7 +253,11 @@ void KFileItemModel::setShowHiddenFiles(bool show) bool KFileItemModel::showHiddenFiles() const { +#if KIO_VERSION < QT_VERSION_CHECK(5, 100, 0) return m_dirLister->showingDotFiles(); +#else + return m_dirLister->showHiddenFiles(); +#endif } void KFileItemModel::setShowDirectoriesOnly(bool enabled) @@ -260,20 +270,20 @@ bool KFileItemModel::showDirectoriesOnly() const return m_dirLister->dirOnlyMode(); } -QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const +QMimeData *KFileItemModel::createMimeData(const KItemSet &indexes) const { - QMimeData* data = new QMimeData(); + QMimeData *data = new QMimeData(); // The following code has been taken from KDirModel::mimeData() // (kdelibs/kio/kio/kdirmodel.cpp) // SPDX-FileCopyrightText: 2006 David Faure QList urls; QList mostLocalUrls; - const ItemData* lastAddedItem = nullptr; + const ItemData *lastAddedItem = nullptr; for (int index : indexes) { - const ItemData* itemData = m_itemData.at(index); - const ItemData* parent = itemData->parent; + const ItemData *itemData = m_itemData.at(index); + const ItemData *parent = itemData->parent; while (parent && parent != lastAddedItem) { parent = parent->parent; @@ -285,7 +295,7 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const } lastAddedItem = itemData; - const KFileItem& item = itemData->item; + const KFileItem &item = itemData->item; if (!item.isNull()) { urls << item.url(); @@ -298,7 +308,7 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const return data; } -int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromIndex) const +int KFileItemModel::indexForKeyboardSearch(const QString &text, int startFromIndex) const { startFromIndex = qMax(0, startFromIndex); for (int i = startFromIndex; i < count(); ++i) { @@ -316,16 +326,21 @@ int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromInd bool KFileItemModel::supportsDropping(int index) const { - const KFileItem item = fileItem(index); - return !item.isNull() && (item.isDir() || item.isDesktopFile()); + KFileItem item; + if (index == -1) { + item = rootItem(); + } else { + item = fileItem(index); + } + return !item.isNull() && ((item.isDir() && item.isWritable()) || item.isDesktopFile()); } -QString KFileItemModel::roleDescription(const QByteArray& role) const +QString KFileItemModel::roleDescription(const QByteArray &role) const { static QHash description; if (description.isEmpty()) { int count = 0; - const RoleInfoMap* map = rolesInfoMap(count); + const RoleInfoMap *map = rolesInfoMap(count); for (int i = 0; i < count; ++i) { if (map[i].roleTranslation.isEmpty()) { continue; @@ -337,7 +352,7 @@ QString KFileItemModel::roleDescription(const QByteArray& role) const return description.value(role); } -QList > KFileItemModel::groups() const +QList> KFileItemModel::groups() const { if (!m_itemData.isEmpty() && m_groups.isEmpty()) { #ifdef KFILEITEMMODEL_DEBUG @@ -345,8 +360,12 @@ QList > KFileItemModel::groups() const timer.start(); #endif switch (typeForRole(sortRole())) { - case NameRole: m_groups = nameRoleGroups(); break; - case SizeRole: m_groups = sizeRoleGroups(); break; + case NameRole: + m_groups = nameRoleGroups(); + break; + case SizeRole: + m_groups = sizeRoleGroups(); + break; case ModificationTimeRole: m_groups = timeRoleGroups([](const ItemData *item) { return item->item.time(KFileItem::ModificationTime); @@ -367,9 +386,15 @@ QList > KFileItemModel::groups() const return item->values.value("deletiontime").toDateTime(); }); break; - case PermissionsRole: m_groups = permissionRoleGroups(); break; - case RatingRole: m_groups = ratingRoleGroups(); break; - default: m_groups = genericStringRoleGroups(sortRole()); break; + case PermissionsRole: + m_groups = permissionRoleGroups(); + break; + case RatingRole: + m_groups = ratingRoleGroups(); + break; + default: + m_groups = genericStringRoleGroups(sortRole()); + break; } #ifdef KFILEITEMMODEL_DEBUG @@ -398,12 +423,12 @@ KFileItem KFileItemModel::fileItem(const QUrl &url) const return KFileItem(); } -int KFileItemModel::index(const KFileItem& item) const +int KFileItemModel::index(const KFileItem &item) const { return index(item.url()); } -int KFileItemModel::index(const QUrl& url) const +int KFileItemModel::index(const QUrl &url) const { const QUrl urlToFind = url.adjusted(QUrl::StripTrailingSlash); @@ -453,13 +478,13 @@ int KFileItemModel::index(const QUrl& url) const } const auto uniqueKeys = indexesForUrl.uniqueKeys(); - for (const QUrl& url : uniqueKeys) { + for (const QUrl &url : uniqueKeys) { if (indexesForUrl.count(url) > 1) { qCWarning(DolphinDebug) << "Multiple items found with the URL" << url; auto it = indexesForUrl.find(url); while (it != indexesForUrl.end() && it.key() == url) { - const ItemData* data = m_itemData.at(it.value()); + const ItemData *data = m_itemData.at(it.value()); qCWarning(DolphinDebug) << "index" << it.value() << ":" << data->item; if (data->parent) { qCWarning(DolphinDebug) << "parent" << data->parent->item; @@ -484,7 +509,7 @@ void KFileItemModel::clear() slotClear(); } -void KFileItemModel::setRoles(const QSet& roles) +void KFileItemModel::setRoles(const QSet &roles) { if (m_roles == roles) { return; @@ -508,7 +533,7 @@ void KFileItemModel::setRoles(const QSet& roles) QSetIterator it(roles); while (it.hasNext()) { - const QByteArray& role = it.next(); + const QByteArray &role = it.next(); m_requestRole[typeForRole(role)] = true; } @@ -524,8 +549,8 @@ void KFileItemModel::setRoles(const QSet& roles) // Clear the 'values' of all filtered items. They will be re-populated with the // correct roles the next time 'values' will be accessed via data(int). - QHash::iterator filteredIt = m_filteredItems.begin(); - const QHash::iterator filteredEnd = m_filteredItems.end(); + QHash::iterator filteredIt = m_filteredItems.begin(); + const QHash::iterator filteredEnd = m_filteredItems.end(); while (filteredIt != filteredEnd) { (*filteredIt)->values.clear(); ++filteredIt; @@ -557,7 +582,7 @@ bool KFileItemModel::setExpanded(int index, bool expanded) m_dirLister->openUrl(url, KDirLister::Keep); const QVariantList previouslyExpandedChildren = m_itemData.at(index)->values.value("previouslyExpandedChildren").value(); - for (const QVariant& var : previouslyExpandedChildren) { + for (const QVariant &var : previouslyExpandedChildren) { m_urlsToExpand.insert(var.toUrl()); } } else { @@ -587,12 +612,12 @@ bool KFileItemModel::setExpanded(int index, bool expanded) int childIndex = firstChildIndex; while (childIndex < itemCount && expandedParentsCount(childIndex) > parentLevel) { - ItemData* itemData = m_itemData.at(childIndex); + ItemData *itemData = m_itemData.at(childIndex); if (itemData->values.value("isExpanded").toBool()) { const QUrl targetUrl = itemData->item.targetUrl(); const QUrl url = itemData->item.url(); m_expandedDirs.remove(targetUrl); - m_dirLister->stop(url); // TODO: try to unit-test this, see https://bugs.kde.org/show_bug.cgi?id=332102#c11 + m_dirLister->stop(url); // TODO: try to unit-test this, see https://bugs.kde.org/show_bug.cgi?id=332102#c11 #if KIO_VERSION >= QT_VERSION_CHECK(5, 92, 0) m_dirLister->forgetDirs(url); #endif @@ -654,7 +679,6 @@ void KFileItemModel::restoreExpandedDirectories(const QSet &urls) void KFileItemModel::expandParentDirectories(const QUrl &url) { - // Assure that each sub-path of the URL that should be // expanded is added to m_urlsToExpand. KDirLister // does not care whether the parent-URL has already been @@ -688,7 +712,7 @@ void KFileItemModel::expandParentDirectories(const QUrl &url) } } -void KFileItemModel::setNameFilter(const QString& nameFilter) +void KFileItemModel::setNameFilter(const QString &nameFilter) { if (m_filter.pattern() != nameFilter) { dispatchPendingItemsToInsert(); @@ -702,7 +726,7 @@ QString KFileItemModel::nameFilter() const return m_filter.pattern(); } -void KFileItemModel::setMimeTypeFilters(const QStringList& filters) +void KFileItemModel::setMimeTypeFilters(const QStringList &filters) { if (m_filter.mimeTypes() != filters) { dispatchPendingItemsToInsert(); @@ -732,8 +756,7 @@ void KFileItemModel::applyFilters() for (int index = m_itemData.count() - 1; index >= 0; --index) { ItemData *itemData = m_itemData.at(index); - if (m_filter.matches(itemData->item) - || (itemShownBelow && itemShownBelow->parent == itemData)) { + if (m_filter.matches(itemData->item) || (itemShownBelow && itemShownBelow->parent == itemData)) { // We could've entered here for two reasons: // 1. This item passes the filter itself // 2. This is an expanded folder that doesn't pass the filter but sees a filter-passing child just below @@ -768,9 +791,8 @@ void KFileItemModel::applyFilters() // If this is a child of an expanded folder, we must make sure that its whole parental chain will also be shown. // We will go up through its parental chain until we either: - // 1 - reach the "root item" of the current view, i.e the currently opened folder on Dolphin. Their children have their ItemData::parent set to nullptr. - // or - // 2 - we reach an unfiltered parent or a previously discovered ancestor. + // 1 - reach the "root item" of the current view, i.e the currently opened folder on Dolphin. Their children have their ItemData::parent set to + // nullptr. or 2 - we reach an unfiltered parent or a previously discovered ancestor. for (ItemData *parent = it.value()->parent; parent && !ancestorsOfNewVisibleItems.contains(parent->item) && m_filteredItems.contains(parent->item); parent = parent->parent) { // We wish we could remove this parent from m_filteredItems right now, but we are iterating over it @@ -800,7 +822,7 @@ void KFileItemModel::applyFilters() insertItems(newVisibleItems); } -void KFileItemModel::removeFilteredChildren(const KItemRangeList& itemRanges) +void KFileItemModel::removeFilteredChildren(const KItemRangeList &itemRanges) { if (m_filteredItems.isEmpty() || !m_requestRole[ExpandedParentsCountRole]) { // There are either no filtered items, or it is not possible to expand @@ -808,14 +830,14 @@ void KFileItemModel::removeFilteredChildren(const KItemRangeList& itemRanges) return; } - QSet parents; - for (const KItemRange& range : itemRanges) { + QSet parents; + for (const KItemRange &range : itemRanges) { for (int index = range.index; index < range.index + range.count; ++index) { parents.insert(m_itemData.at(index)); } } - QHash::iterator it = m_filteredItems.begin(); + QHash::iterator it = m_filteredItems.begin(); while (it != m_filteredItems.end()) { if (parents.contains(it.value()->parent)) { delete it.value(); @@ -831,7 +853,7 @@ QList KFileItemModel::rolesInformation() static QList rolesInfo; if (rolesInfo.isEmpty()) { int count = 0; - const RoleInfoMap* map = rolesInfoMap(count); + const RoleInfoMap *map = rolesInfoMap(count); for (int i = 0; i < count; ++i) { if (map[i].roleType != NoRole) { RoleInfo info; @@ -847,6 +869,11 @@ QList KFileItemModel::rolesInformation() } 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(); + } rolesInfo.append(info); } } @@ -861,7 +888,7 @@ void KFileItemModel::onGroupedSortingChanged(bool current) m_groups.clear(); } -void KFileItemModel::onSortRoleChanged(const QByteArray& current, const QByteArray& previous, bool resortItems) +void KFileItemModel::onSortRoleChanged(const QByteArray ¤t, const QByteArray &previous, bool resortItems) { Q_UNUSED(previous) m_sortRole = typeForRole(current); @@ -929,7 +956,7 @@ void KFileItemModel::resortAllItems() // been moved because of the resorting. QList oldUrls; oldUrls.reserve(itemCount); - for (const ItemData* itemData : qAsConst(m_itemData)) { + for (const ItemData *itemData : qAsConst(m_itemData)) { oldUrls.append(itemData->item.url()); } @@ -944,8 +971,7 @@ void KFileItemModel::resortAllItems() // Determine the first index that has been moved. int firstMovedIndex = 0; - while (firstMovedIndex < itemCount - && firstMovedIndex == m_items.value(oldUrls.at(firstMovedIndex))) { + while (firstMovedIndex < itemCount && firstMovedIndex == m_items.value(oldUrls.at(firstMovedIndex))) { ++firstMovedIndex; } @@ -954,8 +980,7 @@ void KFileItemModel::resortAllItems() m_groups.clear(); int lastMovedIndex = itemCount - 1; - while (lastMovedIndex > firstMovedIndex - && lastMovedIndex == m_items.value(oldUrls.at(lastMovedIndex))) { + while (lastMovedIndex > firstMovedIndex && lastMovedIndex == m_items.value(oldUrls.at(lastMovedIndex))) { --lastMovedIndex; } @@ -975,7 +1000,7 @@ 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; + const QList> oldGroups = m_groups; m_groups.clear(); if (groups() != oldGroups) { Q_EMIT groupsChanged(); @@ -999,7 +1024,7 @@ void KFileItemModel::slotCompleted() // -> we expand the first visible URL we find in m_restoredExpandedUrls. // Iterate over a const copy because items are deleted and inserted within the loop const auto urlsToExpand = m_urlsToExpand; - for(const QUrl &url : urlsToExpand) { + for (const QUrl &url : urlsToExpand) { const int indexForUrl = index(url); if (indexForUrl >= 0) { m_urlsToExpand.remove(url); @@ -1027,7 +1052,7 @@ void KFileItemModel::slotCanceled() Q_EMIT directoryLoadingCanceled(); } -void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemList& items) +void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemList &items) { Q_ASSERT(!items.isEmpty()); @@ -1060,7 +1085,7 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis } } - const QList itemDataList = createItemDataList(parentUrl, items); + const QList itemDataList = createItemDataList(parentUrl, items); if (!m_filter.hasSetFilters()) { m_pendingItemsToInsert.append(itemDataList); @@ -1070,7 +1095,7 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis // The name or type filter is active. Hide filtered items // before inserting them into the model and remember // the filtered items in m_filteredItems. - for (ItemData* itemData : itemDataList) { + for (ItemData *itemData : itemDataList) { if (m_filter.matches(itemData->item)) { m_pendingItemsToInsert.append(itemData); if (itemData->parent) { @@ -1134,7 +1159,7 @@ int KFileItemModel::filterChildlessParents(KItemRangeList &removedItemRanges, co return filteredParentsCount; } -void KFileItemModel::slotItemsDeleted(const KFileItemList& items) +void KFileItemModel::slotItemsDeleted(const KFileItemList &items) { dispatchPendingItemsToInsert(); @@ -1142,13 +1167,20 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items) indexesToRemove.reserve(items.count()); KFileItemList dirsChanged; - for (const KFileItem& item : items) { + const auto currentDir = directory(); + + for (const KFileItem &item : items) { + if (item.url() == currentDir) { + Q_EMIT currentDirectoryRemoved(); + return; + } + const int indexForItem = index(item); if (indexForItem >= 0) { indexesToRemove.append(indexForItem); } else { // Probably the item has been filtered. - QHash::iterator it = m_filteredItems.find(item); + QHash::iterator it = m_filteredItems.find(item); if (it != m_filteredItems.end()) { delete it.value(); m_filteredItems.erase(it); @@ -1198,7 +1230,7 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items) Q_EMIT fileItemsChanged(dirsChanged); } -void KFileItemModel::slotRefreshItems(const QList >& items) +void KFileItemModel::slotRefreshItems(const QList> &items) { Q_ASSERT(!items.isEmpty()); #ifdef KFILEITEMMODEL_DEBUG @@ -1218,14 +1250,14 @@ void KFileItemModel::slotRefreshItems(const QList >& // Contains currently hidden items that should // get visible and hence removed from m_filteredItems - QList newVisibleItems; + QList newVisibleItems; - QListIterator > it(items); + QListIterator> it(items); while (it.hasNext()) { - const QPair& itemPair = it.next(); - const KFileItem& oldItem = itemPair.first; - const KFileItem& newItem = itemPair.second; + const QPair &itemPair = it.next(); + const KFileItem &oldItem = itemPair.first; + const KFileItem &newItem = itemPair.second; const int indexForItem = index(oldItem); const bool newItemMatchesFilter = m_filter.matches(newItem); if (indexForItem >= 0) { @@ -1233,11 +1265,11 @@ void KFileItemModel::slotRefreshItems(const QList >& // Keep old values as long as possible if they could not retrieved synchronously yet. // The update of the values will be done asynchronously by KFileItemModelRolesUpdater. - ItemData * const itemData = m_itemData.at(indexForItem); + ItemData *const itemData = m_itemData.at(indexForItem); QHashIterator it(retrieveData(newItem, itemData->parent)); while (it.hasNext()) { it.next(); - const QByteArray& role = it.key(); + const QByteArray &role = it.key(); if (itemData->values.value(role) != it.value()) { itemData->values.insert(role, it.value()); changedRoles.insert(role); @@ -1261,7 +1293,7 @@ void KFileItemModel::slotRefreshItems(const QList >& } } else { // Check if 'oldItem' is one of the filtered items. - QHash::iterator it = m_filteredItems.find(oldItem); + QHash::iterator it = m_filteredItems.find(oldItem); if (it != m_filteredItems.end()) { ItemData *const itemData = it.value(); itemData->item = newItem; @@ -1398,7 +1430,7 @@ void KFileItemModel::dispatchPendingItemsToInsert() } } -void KFileItemModel::insertItems(QList& newItems) +void KFileItemModel::insertItems(QList &newItems) { if (newItems.isEmpty()) { return; @@ -1421,8 +1453,7 @@ void KFileItemModel::insertItems(QList& newItems) if (m_sortRole == NameRole) { parallelMergeSort(newItems.begin(), newItems.end(), nameLessThan, QThread::idealThreadCount()); } else if (isRoleValueNatural(m_sortRole)) { - auto lambdaLessThan = [&] (const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) - { + auto lambdaLessThan = [&](const KFileItemModel::ItemData *a, const KFileItemModel::ItemData *b) { const QByteArray role = roleForType(m_sortRole); return a->values.value(role).toString() < b->values.value(role).toString(); }; @@ -1461,7 +1492,7 @@ void KFileItemModel::insertItems(QList& newItems) int rangeCount = 0; while (sourceIndexNewItems >= 0) { - ItemData* newItem = newItems.at(sourceIndexNewItems); + ItemData *newItem = newItems.at(sourceIndexNewItems); if (sourceIndexExistingItems >= 0 && lessThan(newItem, m_itemData.at(sourceIndexExistingItems), m_collator)) { // Move an existing item to its new position. If any new items // are behind it, push the item range to itemRanges. @@ -1501,7 +1532,7 @@ void KFileItemModel::insertItems(QList& newItems) #endif } -void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBehavior behavior) +void KFileItemModel::removeItems(const KItemRangeList &itemRanges, RemoveItemsBehavior behavior) { if (itemRanges.isEmpty()) { return; @@ -1511,7 +1542,7 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe // Step 1: Remove the items from m_itemData, and free the ItemData. int removedItemsCount = 0; - for (const KItemRange& range : itemRanges) { + for (const KItemRange &range : itemRanges) { removedItemsCount += range.count; for (int index = range.index; index < range.index + range.count; ++index) { @@ -1550,7 +1581,7 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe Q_EMIT itemsRemoved(itemRanges); } -QList KFileItemModel::createItemDataList(const QUrl& parentUrl, const KFileItemList& items) const +QList KFileItemModel::createItemDataList(const QUrl &parentUrl, const KFileItemList &items) const { if (m_sortRole == TypeRole) { // Try to resolve the MIME-types synchronously to prevent a reordering of @@ -1563,11 +1594,11 @@ QList KFileItemModel::createItemDataList(const QUrl& const int parentIndex = index(parentUrl); ItemData *parentItem = parentIndex < 0 ? m_filteredItems.value(KFileItem(parentUrl), nullptr) : m_itemData.at(parentIndex); - QList itemDataList; + QList itemDataList; itemDataList.reserve(items.count()); - for (const KFileItem& item : items) { - ItemData* itemData = new ItemData(); + for (const KFileItem &item : items) { + ItemData *itemData = new ItemData(); itemData->item = item; itemData->parent = parentItem; itemDataList.append(itemData); @@ -1576,7 +1607,7 @@ QList KFileItemModel::createItemDataList(const QUrl& return itemDataList; } -void KFileItemModel::prepareItemsForSorting(QList& itemDataList) +void KFileItemModel::prepareItemsForSorting(QList &itemDataList) { switch (m_sortRole) { case ExtensionRole: @@ -1588,7 +1619,7 @@ void KFileItemModel::prepareItemsForSorting(QList& itemDataList) case DeletionTimeRole: // These roles can be determined with retrieveData, and they have to be stored // in the QHash "values" for the sorting. - for (ItemData* itemData : qAsConst(itemDataList)) { + for (ItemData *itemData : qAsConst(itemDataList)) { if (itemData->values.isEmpty()) { itemData->values = retrieveData(itemData->item, itemData->parent); } @@ -1597,7 +1628,7 @@ void KFileItemModel::prepareItemsForSorting(QList& itemDataList) case TypeRole: // At least store the data including the file type for items with known MIME type. - for (ItemData* itemData : qAsConst(itemDataList)) { + for (ItemData *itemData : qAsConst(itemDataList)) { if (itemData->values.isEmpty()) { const KFileItem item = itemData->item; if (item.isDir() || item.isMimeTypeKnown()) { @@ -1617,11 +1648,11 @@ void KFileItemModel::prepareItemsForSorting(QList& itemDataList) } } -int KFileItemModel::expandedParentsCount(const ItemData* data) +int KFileItemModel::expandedParentsCount(const ItemData *data) { // The hash 'values' is only guaranteed to contain the key "expandedParentsCount" // if the corresponding item is expanded, and it is not a top-level item. - const ItemData* parent = data->parent; + const ItemData *parent = data->parent; if (parent) { if (parent->parent) { Q_ASSERT(parent->values.contains("expandedParentsCount")); @@ -1640,7 +1671,7 @@ void KFileItemModel::removeExpandedItems() const int maxIndex = m_itemData.count() - 1; for (int i = 0; i <= maxIndex; ++i) { - const ItemData* itemData = m_itemData.at(i); + const ItemData *itemData = m_itemData.at(i); if (itemData->parent) { indexesToRemove.append(i); } @@ -1650,8 +1681,8 @@ void KFileItemModel::removeExpandedItems() m_expandedDirs.clear(); // Also remove all filtered items which have a parent. - QHash::iterator it = m_filteredItems.begin(); - const QHash::iterator end = m_filteredItems.end(); + QHash::iterator it = m_filteredItems.begin(); + const QHash::iterator end = m_filteredItems.end(); while (it != end) { if (it.value()->parent) { @@ -1663,14 +1694,14 @@ void KFileItemModel::removeExpandedItems() } } -void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList& itemRanges, const QSet& changedRoles) +void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList &itemRanges, const QSet &changedRoles) { Q_EMIT itemsChanged(itemRanges, changedRoles); // Trigger a resorting if necessary. Note that this can happen even if the sort // role has not changed at all because the file name can be used as a fallback. if (changedRoles.contains(sortRole()) || changedRoles.contains(roleForType(NameRole))) { - for (const KItemRange& range : itemRanges) { + for (const KItemRange &range : itemRanges) { bool needsResorting = false; const int first = range.index; @@ -1680,11 +1711,9 @@ void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList& i // (a) The first item in the range is "lessThan" its predecessor, // (b) the successor of the last item is "lessThan" the last item, or // (c) the internal order of the items in the range is incorrect. - if (first > 0 - && lessThan(m_itemData.at(first), m_itemData.at(first - 1), m_collator)) { + if (first > 0 && lessThan(m_itemData.at(first), m_itemData.at(first - 1), m_collator)) { needsResorting = true; - } else if (last < count() - 1 - && lessThan(m_itemData.at(last + 1), m_itemData.at(last), m_collator)) { + } else if (last < count() - 1 && lessThan(m_itemData.at(last + 1), m_itemData.at(last), m_collator)) { needsResorting = true; } else { for (int index = first; index < last; ++index) { @@ -1722,14 +1751,14 @@ void KFileItemModel::resetRoles() } } -KFileItemModel::RoleType KFileItemModel::typeForRole(const QByteArray& role) const +KFileItemModel::RoleType KFileItemModel::typeForRole(const QByteArray &role) const { static QHash roles; if (roles.isEmpty()) { // Insert user visible roles that can be accessed with // KFileItemModel::roleInformation() int count = 0; - const RoleInfoMap* map = rolesInfoMap(count); + const RoleInfoMap *map = rolesInfoMap(count); for (int i = 0; i < count; ++i) { roles.insert(map[i].role, map[i].roleType); } @@ -1756,7 +1785,7 @@ QByteArray KFileItemModel::roleForType(RoleType roleType) const // Insert user visible roles that can be accessed with // KFileItemModel::roleInformation() int count = 0; - const RoleInfoMap* map = rolesInfoMap(count); + const RoleInfoMap *map = rolesInfoMap(count); for (int i = 0; i < count; ++i) { roles.insert(map[i].roleType, map[i].role); } @@ -1776,7 +1805,7 @@ QByteArray KFileItemModel::roleForType(RoleType roleType) const return roles.value(roleType); } -QHash KFileItemModel::retrieveData(const KFileItem& item, const ItemData* parent) const +QHash KFileItemModel::retrieveData(const KFileItem &item, const ItemData *parent) const { // It is important to insert only roles that are fast to retrieve. E.g. // KFileItem::iconName() can be very expensive if the MIME-type is unknown @@ -1801,7 +1830,8 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, data.insert(sharedValue("text"), item.text()); } - if (m_requestRole[ExtensionRole]) { + if (m_requestRole[ExtensionRole] && !isDir) { + // TODO KF6 use KFileItem::suffix 464722 data.insert(sharedValue("extension"), QFileInfo(item.name()).suffix()); } @@ -1834,7 +1864,7 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, } if (m_requestRole[PermissionsRole]) { - data.insert(sharedValue("permissions"), item.permissionsString()); + data.insert(sharedValue("permissions"), QVariantList() << item.permissionsString() << item.permissions()); } if (m_requestRole[OwnerRole]) { @@ -1915,7 +1945,7 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, return data; } -bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b, const QCollator& collator) const +bool KFileItemModel::lessThan(const ItemData *a, const ItemData *b, const QCollator &collator) const { int result = 0; @@ -1961,7 +1991,7 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b, const QColla } } - if (m_sortDirsFirst || (DetailsModeSettings::directorySizeCount() && m_sortRole == SizeRole)) { + if (m_sortDirsFirst || (ContentDisplaySettings::directorySizeCount() && m_sortRole == SizeRole)) { const bool isDirA = a->item.isDir(); const bool isDirB = b->item.isDir(); if (isDirA && !isDirB) { @@ -1976,11 +2006,9 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b, const QColla return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0; } -void KFileItemModel::sort(const QList::iterator &begin, - const QList::iterator &end) const +void KFileItemModel::sort(const QList::iterator &begin, const QList::iterator &end) const { - auto lambdaLessThan = [&] (const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) - { + auto lambdaLessThan = [&](const KFileItemModel::ItemData *a, const KFileItemModel::ItemData *b) { return lessThan(a, b, m_collator); }; @@ -1997,15 +2025,15 @@ void KFileItemModel::sort(const QList::iterator &begi } } -int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const QCollator& collator) const +int KFileItemModel::sortRoleCompare(const ItemData *a, const ItemData *b, const QCollator &collator) const { // This function must never return 0, because that would break stable // sorting, which leads to all kinds of bugs. // See: https://bugs.kde.org/show_bug.cgi?id=433247 // If two items have equal sort values, let the fallbacks at the bottom of // the function handle it. - const KFileItem& itemA = a->item; - const KFileItem& itemB = b->item; + const KFileItem &itemA = a->item; + const KFileItem &itemB = b->item; int result = 0; @@ -2015,7 +2043,7 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const break; case SizeRole: { - if (DetailsModeSettings::directorySizeCount() && itemA.isDir()) { + if (ContentDisplaySettings::directorySizeCount() && itemA.isDir()) { // folders first then // items A and B are folders thanks to lessThan checks auto valueA = a->values.value("count"); @@ -2067,6 +2095,17 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const break; } + case AccessTimeRole: { + const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_ACCESS_TIME, -1); + const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_ACCESS_TIME, -1); + if (dateTimeA < dateTimeB) { + return -1; + } else if (dateTimeA > dateTimeB) { + return +1; + } + break; + } + case CreationTimeRole: { const long long dateTimeA = itemA.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1); const long long dateTimeB = itemB.entry().numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1); @@ -2092,6 +2131,8 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const case RatingRole: case WidthRole: case HeightRole: + case PublisherRole: + case PageCountRole: case WordCountRole: case LineCountRole: case TrackRole: @@ -2100,7 +2141,7 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const break; } - case DimensionsRole: { + case DimensionsRole: { const QByteArray role = roleForType(m_sortRole); const QSize dimensionsA = a->values.value(role).toSize(); const QSize dimensionsB = b->values.value(role).toSize(); @@ -2128,7 +2169,6 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const } break; } - } if (result != 0) { @@ -2154,7 +2194,7 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const return QString::compare(itemA.url().url(), itemB.url().url(), Qt::CaseSensitive); } -int KFileItemModel::stringCompare(const QString& a, const QString& b, const QCollator& collator) const +int KFileItemModel::stringCompare(const QString &a, const QString &b, const QCollator &collator) const { QMutexLocker collatorLock(s_collatorMutex()); @@ -2173,12 +2213,12 @@ int KFileItemModel::stringCompare(const QString& a, const QString& b, const QCol return QString::compare(a, b, Qt::CaseSensitive); } -QList > KFileItemModel::nameRoleGroups() const +QList> KFileItemModel::nameRoleGroups() const { Q_ASSERT(!m_itemData.isEmpty()); const int maxIndex = count() - 1; - QList > groups; + QList> groups; QString groupValue; QChar firstChar; @@ -2198,7 +2238,6 @@ QList > KFileItemModel::nameRoleGroups() const if (firstChar != newFirstChar) { QString newGroupValue; if (newFirstChar.isLetter()) { - 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. @@ -2247,12 +2286,12 @@ QList > KFileItemModel::nameRoleGroups() const return groups; } -QList > KFileItemModel::sizeRoleGroups() const +QList> KFileItemModel::sizeRoleGroups() const { Q_ASSERT(!m_itemData.isEmpty()); const int maxIndex = count() - 1; - QList > groups; + QList> groups; QString groupValue; for (int i = 0; i <= maxIndex; ++i) { @@ -2260,11 +2299,11 @@ QList > KFileItemModel::sizeRoleGroups() const continue; } - const KFileItem& item = m_itemData.at(i)->item; + const KFileItem &item = m_itemData.at(i)->item; KIO::filesize_t fileSize = !item.isNull() ? item.size() : ~0U; QString newGroupValue; if (!item.isNull() && item.isDir()) { - if (DetailsModeSettings::directorySizeCount() || m_sortDirsFirst) { + if (ContentDisplaySettings::directorySizeCount() || m_sortDirsFirst) { newGroupValue = i18nc("@title:group Size", "Folders"); } else { fileSize = m_itemData.at(i)->values.value("size").toULongLong(); @@ -2290,12 +2329,12 @@ QList > KFileItemModel::sizeRoleGroups() const return groups; } -QList > KFileItemModel::timeRoleGroups(const std::function &fileTimeCb) const +QList> KFileItemModel::timeRoleGroups(const std::function &fileTimeCb) const { Q_ASSERT(!m_itemData.isEmpty()); const int maxIndex = count() - 1; - QList > groups; + QList> groups; const QDate currentDate = QDate::currentDate(); @@ -2317,19 +2356,23 @@ QList > KFileItemModel::timeRoleGroups(const std::function< const int daysDistance = fileDate.daysTo(currentDate); QString newGroupValue; - if (currentDate.year() == fileDate.year() && - currentDate.month() == fileDate.month()) { - + if (currentDate.year() == fileDate.year() && currentDate.month() == fileDate.month()) { switch (daysDistance / 7) { case 0: switch (daysDistance) { - case 0: newGroupValue = i18nc("@title:group Date", "Today"); break; - case 1: newGroupValue = i18nc("@title:group Date", "Yesterday"); break; + case 0: + newGroupValue = i18nc("@title:group Date", "Today"); + break; + case 1: + newGroupValue = i18nc("@title:group Date", "Yesterday"); + break; default: - newGroupValue = fileTime.toString( - i18nc("@title:group Date: The week day name: dddd", "dddd")); - newGroupValue = i18nc("Can be used to script translation of \"dddd\"" - "with context @title:group Date", "%1", newGroupValue); + newGroupValue = fileTime.toString(i18nc("@title:group Date: The week day name: dddd", "dddd")); + newGroupValue = i18nc( + "Can be used to script translation of \"dddd\"" + "with context @title:group Date", + "%1", + newGroupValue); } break; case 1: @@ -2350,100 +2393,135 @@ QList > KFileItemModel::timeRoleGroups(const std::function< } } else { const QDate lastMonthDate = currentDate.addMonths(-1); - if (lastMonthDate.year() == fileDate.year() && - lastMonthDate.month() == fileDate.month()) { - + if (lastMonthDate.year() == fileDate.year() && lastMonthDate.month() == fileDate.month()) { if (daysDistance == 1) { - const KLocalizedString format = ki18nc("@title:group Date: " - "MMMM is full month name in current locale, and yyyy is " - "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a part of the text that should not be formatted as a date", "'Yesterday' (MMMM, yyyy)"); + const KLocalizedString format = ki18nc( + "@title:group Date: " + "MMMM is full month name in current locale, and yyyy is " + "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a " + "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) { newGroupValue = fileTime.toString(translatedFormat); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = i18nc( + "Can be used to script translation of " "\"'Yesterday' (MMMM, yyyy)\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } else { - qCWarning(DolphinDebug).nospace() << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; - const QString untranslatedFormat = format.toString({ QLatin1String("en_US") }); + qCWarning(DolphinDebug).nospace() + << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; + const QString untranslatedFormat = format.toString({QLatin1String("en_US")}); newGroupValue = fileTime.toString(untranslatedFormat); } } else if (daysDistance <= 7) { - newGroupValue = fileTime.toString(i18nc("@title:group Date: " - "The week day name: dddd, MMMM is full month name " - "in current locale, and yyyy is full year number.", - "dddd (MMMM, yyyy)")); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = + fileTime.toString(i18nc("@title:group Date: " + "The week day name: dddd, MMMM is full month name " + "in current locale, and yyyy is full year number.", + "dddd (MMMM, yyyy)")); + newGroupValue = i18nc( + "Can be used to script translation of " "\"dddd (MMMM, yyyy)\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } else if (daysDistance <= 7 * 2) { - const KLocalizedString format = ki18nc("@title:group Date: " - "MMMM is full month name in current locale, and yyyy is " - "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a part of the text that should not be formatted as a date", "'One Week Ago' (MMMM, yyyy)"); + const KLocalizedString format = ki18nc( + "@title:group Date: " + "MMMM is full month name in current locale, and yyyy is " + "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a " + "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) { newGroupValue = fileTime.toString(translatedFormat); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = i18nc( + "Can be used to script translation of " "\"'One Week Ago' (MMMM, yyyy)\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } else { - qCWarning(DolphinDebug).nospace() << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; - const QString untranslatedFormat = format.toString({ QLatin1String("en_US") }); + qCWarning(DolphinDebug).nospace() + << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; + const QString untranslatedFormat = format.toString({QLatin1String("en_US")}); newGroupValue = fileTime.toString(untranslatedFormat); } } else if (daysDistance <= 7 * 3) { - const KLocalizedString format = ki18nc("@title:group Date: " - "MMMM is full month name in current locale, and yyyy is " - "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a part of the text that should not be formatted as a date", "'Two Weeks Ago' (MMMM, yyyy)"); + const KLocalizedString format = ki18nc( + "@title:group Date: " + "MMMM is full month name in current locale, and yyyy is " + "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a " + "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) { newGroupValue = fileTime.toString(translatedFormat); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = i18nc( + "Can be used to script translation of " "\"'Two Weeks Ago' (MMMM, yyyy)\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } else { - qCWarning(DolphinDebug).nospace() << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; - const QString untranslatedFormat = format.toString({ QLatin1String("en_US") }); + qCWarning(DolphinDebug).nospace() + << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; + const QString untranslatedFormat = format.toString({QLatin1String("en_US")}); newGroupValue = fileTime.toString(untranslatedFormat); } } else if (daysDistance <= 7 * 4) { - const KLocalizedString format = ki18nc("@title:group Date: " - "MMMM is full month name in current locale, and yyyy is " - "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a part of the text that should not be formatted as a date", "'Three Weeks Ago' (MMMM, yyyy)"); + const KLocalizedString format = ki18nc( + "@title:group Date: " + "MMMM is full month name in current locale, and yyyy is " + "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a " + "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) { newGroupValue = fileTime.toString(translatedFormat); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = i18nc( + "Can be used to script translation of " "\"'Three Weeks Ago' (MMMM, yyyy)\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } else { - qCWarning(DolphinDebug).nospace() << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; - const QString untranslatedFormat = format.toString({ QLatin1String("en_US") }); + qCWarning(DolphinDebug).nospace() + << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; + const QString untranslatedFormat = format.toString({QLatin1String("en_US")}); newGroupValue = fileTime.toString(untranslatedFormat); } } else { - const KLocalizedString format = ki18nc("@title:group Date: " - "MMMM is full month name in current locale, and yyyy is " - "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a part of the text that should not be formatted as a date", "'Earlier on' MMMM, yyyy"); + const KLocalizedString format = ki18nc( + "@title:group Date: " + "MMMM is full month name in current locale, and yyyy is " + "full year number. You must keep the ' don't use any fancy \" or « or similar. The ' is not shown to the user, it's there to mark a " + "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) { newGroupValue = fileTime.toString(translatedFormat); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = i18nc( + "Can be used to script translation of " "\"'Earlier on' MMMM, yyyy\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } else { - qCWarning(DolphinDebug).nospace() << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; - const QString untranslatedFormat = format.toString({ QLatin1String("en_US") }); + qCWarning(DolphinDebug).nospace() + << "A wrong translation was found: " << translatedFormat << ". Please file a bug report at bugs.kde.org"; + const QString untranslatedFormat = format.toString({QLatin1String("en_US")}); newGroupValue = fileTime.toString(untranslatedFormat); } } } else { - newGroupValue = fileTime.toString(i18nc("@title:group " - "The month and year: MMMM is full month name in current locale, " - "and yyyy is full year number", "MMMM, yyyy")); - newGroupValue = i18nc("Can be used to script translation of " + newGroupValue = + fileTime.toString(i18nc("@title:group " + "The month and year: MMMM is full month name in current locale, " + "and yyyy is full year number", + "MMMM, yyyy")); + newGroupValue = i18nc( + "Can be used to script translation of " "\"MMMM, yyyy\" with context @title:group Date", - "%1", newGroupValue); + "%1", + newGroupValue); } } @@ -2456,12 +2534,12 @@ QList > KFileItemModel::timeRoleGroups(const std::function< return groups; } -QList > KFileItemModel::permissionRoleGroups() const +QList> KFileItemModel::permissionRoleGroups() const { Q_ASSERT(!m_itemData.isEmpty()); const int maxIndex = count() - 1; - QList > groups; + QList> groups; QString permissionsString; QString groupValue; @@ -2470,7 +2548,7 @@ QList > KFileItemModel::permissionRoleGroups() const continue; } - const ItemData* itemData = m_itemData.at(i); + const ItemData *itemData = m_itemData.at(i); const QString newPermissionsString = itemData->values.value("permissions").toString(); if (newPermissionsString == permissionsString) { continue; @@ -2528,12 +2606,12 @@ QList > KFileItemModel::permissionRoleGroups() const return groups; } -QList > KFileItemModel::ratingRoleGroups() const +QList> KFileItemModel::ratingRoleGroups() const { Q_ASSERT(!m_itemData.isEmpty()); const int maxIndex = count() - 1; - QList > groups; + QList> groups; int groupValue = -1; for (int i = 0; i <= maxIndex; ++i) { @@ -2550,12 +2628,12 @@ QList > KFileItemModel::ratingRoleGroups() const return groups; } -QList > KFileItemModel::genericStringRoleGroups(const QByteArray& role) const +QList> KFileItemModel::genericStringRoleGroups(const QByteArray &role) const { Q_ASSERT(!m_itemData.isEmpty()); const int maxIndex = count() - 1; - QList > groups; + QList> groups; bool isFirstGroupValue = true; QString groupValue; @@ -2602,57 +2680,61 @@ void KFileItemModel::emitSortProgress(int resolvedCount) } } -const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count) +const KFileItemModel::RoleInfoMap *KFileItemModel::rolesInfoMap(int &count) { static const RoleInfoMap rolesInfoMap[] = { - // | role | roleType | role translation | group translation | requires Baloo | requires indexer - { nullptr, NoRole, KLazyLocalizedString(), KLazyLocalizedString(), false, false }, - { "text", NameRole, kli18nc("@label", "Name"), KLazyLocalizedString(), false, false }, - { "size", SizeRole, kli18nc("@label", "Size"), KLazyLocalizedString(), false, false }, - { "modificationtime", ModificationTimeRole, kli18nc("@label", "Modified"), KLazyLocalizedString(), false, false }, - { "creationtime", CreationTimeRole, kli18nc("@label", "Created"), KLazyLocalizedString(), false, false }, - { "accesstime", AccessTimeRole, kli18nc("@label", "Accessed"), KLazyLocalizedString(), false, false }, - { "type", TypeRole, kli18nc("@label", "Type"), KLazyLocalizedString(), false, false }, - { "rating", RatingRole, kli18nc("@label", "Rating"), KLazyLocalizedString(), true, false }, - { "tags", TagsRole, kli18nc("@label", "Tags"), KLazyLocalizedString(), true, false }, - { "comment", CommentRole, kli18nc("@label", "Comment"), KLazyLocalizedString(), true, false }, - { "title", TitleRole, kli18nc("@label", "Title"), kli18nc("@label", "Document"), true, true }, - { "author", AuthorRole, kli18nc("@label", "Author"), kli18nc("@label", "Document"), true, true }, - { "wordCount", WordCountRole, kli18nc("@label", "Word Count"), kli18nc("@label", "Document"), true, true }, - { "lineCount", LineCountRole, kli18nc("@label", "Line Count"), kli18nc("@label", "Document"), true, true }, - { "imageDateTime", ImageDateTimeRole, kli18nc("@label", "Date Photographed"), kli18nc("@label", "Image"), true, true }, - { "dimensions", DimensionsRole, kli18nc("@label width x height", "Dimensions"), kli18nc("@label", "Image"), true, true }, - { "width", WidthRole, kli18nc("@label", "Width"), kli18nc("@label", "Image"), true, true }, - { "height", HeightRole, kli18nc("@label", "Height"), kli18nc("@label", "Image"), true, true }, - { "orientation", OrientationRole, kli18nc("@label", "Orientation"), kli18nc("@label", "Image"), true, true }, - { "artist", ArtistRole, kli18nc("@label", "Artist"), kli18nc("@label", "Audio"), true, true }, - { "genre", GenreRole, kli18nc("@label", "Genre"), kli18nc("@label", "Audio"), true, true }, - { "album", AlbumRole, kli18nc("@label", "Album"), kli18nc("@label", "Audio"), true, true }, - { "duration", DurationRole, kli18nc("@label", "Duration"), kli18nc("@label", "Audio"), true, true }, - { "bitrate", BitrateRole, kli18nc("@label", "Bitrate"), kli18nc("@label", "Audio"), true, true }, - { "track", TrackRole, kli18nc("@label", "Track"), kli18nc("@label", "Audio"), true, true }, - { "releaseYear", ReleaseYearRole, kli18nc("@label", "Release Year"), kli18nc("@label", "Audio"), true, true }, - { "aspectRatio", AspectRatioRole, kli18nc("@label", "Aspect Ratio"), kli18nc("@label", "Video"), true, true }, - { "frameRate", FrameRateRole, kli18nc("@label", "Frame Rate"), kli18nc("@label", "Video"), true, true }, - { "path", PathRole, kli18nc("@label", "Path"), kli18nc("@label", "Other"), false, false }, - { "extension", ExtensionRole, kli18nc("@label", "File Extension"), kli18nc("@label", "Other"), false, false }, - { "deletiontime", DeletionTimeRole, kli18nc("@label", "Deletion Time"), kli18nc("@label", "Other"), false, false }, - { "destination", DestinationRole, kli18nc("@label", "Link Destination"), kli18nc("@label", "Other"), false, false }, - { "originUrl", OriginUrlRole, kli18nc("@label", "Downloaded From"), kli18nc("@label", "Other"), true, false }, - { "permissions", PermissionsRole, kli18nc("@label", "Permissions"), kli18nc("@label", "Other"), false, false }, - { "owner", OwnerRole, kli18nc("@label", "Owner"), kli18nc("@label", "Other"), false, false }, - { "group", GroupRole, kli18nc("@label", "User Group"), kli18nc("@label", "Other"), false, false }, + // clang-format off + // | role | roleType | role translation | group translation | requires Baloo | requires indexer + { nullptr, NoRole, KLazyLocalizedString(), 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 }, + { "creationtime", CreationTimeRole, kli18nc("@label", "Created"), KLazyLocalizedString(), kli18nc("@tooltip", "The date format can be selected in settings."), false, false }, + { "accesstime", AccessTimeRole, kli18nc("@label", "Accessed"), KLazyLocalizedString(), kli18nc("@tooltip", "The date format can be selected in settings."), false, false }, + { "type", TypeRole, kli18nc("@label", "Type"), KLazyLocalizedString(), KLazyLocalizedString(), false, false }, + { "rating", RatingRole, kli18nc("@label", "Rating"), KLazyLocalizedString(), KLazyLocalizedString(), true, false }, + { "tags", TagsRole, kli18nc("@label", "Tags"), KLazyLocalizedString(), KLazyLocalizedString(), true, false }, + { "comment", CommentRole, kli18nc("@label", "Comment"), KLazyLocalizedString(), KLazyLocalizedString(), true, false }, + { "title", TitleRole, kli18nc("@label", "Title"), kli18nc("@label", "Document"), KLazyLocalizedString(), true, true }, + { "author", AuthorRole, kli18nc("@label", "Author"), kli18nc("@label", "Document"), KLazyLocalizedString(), true, true }, + { "publisher", PublisherRole, kli18nc("@label", "Publisher"), kli18nc("@label", "Document"), KLazyLocalizedString(), true, true }, + { "pageCount", PageCountRole, kli18nc("@label", "Page Count"), kli18nc("@label", "Document"), KLazyLocalizedString(), true, true }, + { "wordCount", WordCountRole, kli18nc("@label", "Word Count"), kli18nc("@label", "Document"), KLazyLocalizedString(), true, true }, + { "lineCount", LineCountRole, kli18nc("@label", "Line Count"), kli18nc("@label", "Document"), KLazyLocalizedString(), true, true }, + { "imageDateTime", ImageDateTimeRole, kli18nc("@label", "Date Photographed"), kli18nc("@label", "Image"), KLazyLocalizedString(), true, true }, + { "dimensions", DimensionsRole, kli18nc("@label width x height", "Dimensions"), kli18nc("@label", "Image"), KLazyLocalizedString(), true, true }, + { "width", WidthRole, kli18nc("@label", "Width"), kli18nc("@label", "Image"), KLazyLocalizedString(), true, true }, + { "height", HeightRole, kli18nc("@label", "Height"), kli18nc("@label", "Image"), KLazyLocalizedString(), true, true }, + { "orientation", OrientationRole, kli18nc("@label", "Orientation"), kli18nc("@label", "Image"), KLazyLocalizedString(), true, true }, + { "artist", ArtistRole, kli18nc("@label", "Artist"), kli18nc("@label", "Audio"), KLazyLocalizedString(), true, true }, + { "genre", GenreRole, kli18nc("@label", "Genre"), kli18nc("@label", "Audio"), KLazyLocalizedString(), true, true }, + { "album", AlbumRole, kli18nc("@label", "Album"), kli18nc("@label", "Audio"), KLazyLocalizedString(), true, true }, + { "duration", DurationRole, kli18nc("@label", "Duration"), kli18nc("@label", "Audio"), KLazyLocalizedString(), true, true }, + { "bitrate", BitrateRole, kli18nc("@label", "Bitrate"), kli18nc("@label", "Audio"), KLazyLocalizedString(), true, true }, + { "track", TrackRole, kli18nc("@label", "Track"), kli18nc("@label", "Audio"), KLazyLocalizedString(), true, true }, + { "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 }, + { "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 }, + { "destination", DestinationRole, kli18nc("@label", "Link Destination"), kli18nc("@label", "Other"), KLazyLocalizedString(), false, false }, + { "originUrl", OriginUrlRole, kli18nc("@label", "Downloaded From"), kli18nc("@label", "Other"), KLazyLocalizedString(), true, false }, + { "permissions", PermissionsRole, kli18nc("@label", "Permissions"), kli18nc("@label", "Other"), kli18nc("@tooltip", "The permission format can be changed in settings. Options are Symbolic, Numeric (Octal) or Combined formats"), false, false }, + { "owner", OwnerRole, kli18nc("@label", "Owner"), kli18nc("@label", "Other"), KLazyLocalizedString(), false, false }, + { "group", GroupRole, kli18nc("@label", "User Group"), kli18nc("@label", "Other"), KLazyLocalizedString(), false, false }, }; + // clang-format on count = sizeof(rolesInfoMap) / sizeof(RoleInfoMap); return rolesInfoMap; } -void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout) +void KFileItemModel::determineMimeTypes(const KFileItemList &items, int timeout) { QElapsedTimer timer; timer.start(); - for (const KFileItem& item : items) { + for (const KFileItem &item : items) { // Only determine mime types for files here. For directories, // KFileItem::determineMimeType() reads the .directory file inside to // load the icon, but this is not necessary at all if we just need the @@ -2670,7 +2752,7 @@ void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout) } } -QByteArray KFileItemModel::sharedValue(const QByteArray& value) +QByteArray KFileItemModel::sharedValue(const QByteArray &value) { static QSet pool; const QSet::const_iterator it = pool.constFind(value); @@ -2707,14 +2789,13 @@ bool KFileItemModel::isConsistent() const // Check if the items are sorted correctly. if (i > 0 && !lessThan(m_itemData.at(i - 1), m_itemData.at(i), m_collator)) { - qCWarning(DolphinDebug) << "The order of items" << i - 1 << "and" << i << "is wrong:" - << fileItem(i - 1) << fileItem(i); + qCWarning(DolphinDebug) << "The order of items" << i - 1 << "and" << i << "is wrong:" << fileItem(i - 1) << fileItem(i); return false; } // Check if all parent-child relationships are consistent. - const ItemData* data = m_itemData.at(i); - const ItemData* parent = data->parent; + const ItemData *data = m_itemData.at(i); + const ItemData *parent = data->parent; if (parent) { if (expandedParentsCount(data) != expandedParentsCount(parent) + 1) { qCWarning(DolphinDebug) << "expandedParentsCount is inconsistent for parent" << parent->item << "and child" << data->item; @@ -2723,7 +2804,8 @@ bool KFileItemModel::isConsistent() const const int parentIndex = index(parent->item); if (parentIndex >= i) { - qCWarning(DolphinDebug) << "Index" << parentIndex << "of parent" << parent->item << "is not smaller than index" << i << "of child" << data->item; + qCWarning(DolphinDebug) << "Index" << parentIndex << "of parent" << parent->item << "is not smaller than index" << i << "of child" + << data->item; return false; } }