X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/e6ea3ab4c41dcc115143a237aafd3a1152849433..9e8e58147:/src/kitemviews/kfileitemmodel.cpp diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index 5e9603ba1..b000d649c 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -1,23 +1,10 @@ -/***************************************************************************** - * Copyright (C) 2011 by Peter Penz * - * Copyright (C) 2013 by Frank Reininghaus * - * Copyright (C) 2013 by Emmanuel Pescosta * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - *****************************************************************************/ +/* + * SPDX-FileCopyrightText: 2011 Peter Penz + * SPDX-FileCopyrightText: 2013 Frank Reininghaus + * SPDX-FileCopyrightText: 2013 Emmanuel Pescosta + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "kfileitemmodel.h" @@ -27,16 +14,19 @@ #include "private/kfileitemmodeldirlister.h" #include "private/kfileitemmodelsortalgorithm.h" +#include #include #include #include #include +#include #include #include -#include +#include +#include -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, s_collatorMutex, (QMutex::Recursive)) +Q_GLOBAL_STATIC(QRecursiveMutex, s_collatorMutex) // #define KFILEITEMMODEL_DEBUG @@ -73,7 +63,6 @@ KFileItemModel::KFileItemModel(QObject* parent) : connect(m_dirLister, &KFileItemModelDirLister::started, this, &KFileItemModel::directoryLoadingStarted); connect(m_dirLister, QOverload<>::of(&KCoreDirLister::canceled), this, &KFileItemModel::slotCanceled); - connect(m_dirLister, QOverload::of(&KCoreDirLister::completed), this, &KFileItemModel::slotCompleted); connect(m_dirLister, &KFileItemModelDirLister::itemsAdded, this, &KFileItemModel::slotItemsAdded); connect(m_dirLister, &KFileItemModelDirLister::itemsDeleted, this, &KFileItemModel::slotItemsDeleted); connect(m_dirLister, &KFileItemModelDirLister::refreshItems, this, &KFileItemModel::slotRefreshItems); @@ -84,6 +73,12 @@ KFileItemModel::KFileItemModel(QObject* parent) : connect(m_dirLister, QOverload::of(&KCoreDirLister::redirection), this, &KFileItemModel::directoryRedirection); connect(m_dirLister, &KFileItemModelDirLister::urlIsFileError, this, &KFileItemModel::urlIsFileError); +#if KIO_VERSION < QT_VERSION_CHECK(5, 79, 0) + connect(m_dirLister, QOverload::of(&KCoreDirLister::completed), this, &KFileItemModel::slotCompleted); +#else + connect(m_dirLister, &KCoreDirLister::listingDirCompleted, this, &KFileItemModel::slotCompleted); +#endif + // Apply default roles that should be determined resetRoles(); m_requestRole[NameRole] = true; @@ -247,7 +242,7 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const // The following code has been taken from KDirModel::mimeData() // (kdelibs/kio/kio/kdirmodel.cpp) - // Copyright (C) 2006 David Faure + // SPDX-FileCopyrightText: 2006 David Faure QList urls; QList mostLocalUrls; const ItemData* lastAddedItem = nullptr; @@ -433,7 +428,8 @@ int KFileItemModel::index(const QUrl& url) const indexesForUrl.insert(m_itemData.at(i)->item.url(), i); } - foreach (const QUrl& url, indexesForUrl.uniqueKeys()) { + const auto uniqueKeys = indexesForUrl.uniqueKeys(); + for (const QUrl& url : uniqueKeys) { if (indexesForUrl.count(url) > 1) { qCWarning(DolphinDebug) << "Multiple items found with the URL" << url; @@ -499,7 +495,7 @@ void KFileItemModel::setRoles(const QSet& roles) m_itemData[i]->values = retrieveData(m_itemData.at(i)->item, m_itemData.at(i)->parent); } - emit itemsChanged(KItemRangeList() << KItemRange(0, count()), changedRoles); + Q_EMIT itemsChanged(KItemRangeList() << KItemRange(0, count()), changedRoles); } // Clear the 'values' of all filtered items. They will be re-populated with the @@ -537,7 +533,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(); - foreach (const QVariant& var, previouslyExpandedChildren) { + for (const QVariant& var : previouslyExpandedChildren) { m_urlsToExpand.insert(var.toUrl()); } } else { @@ -639,7 +635,7 @@ void KFileItemModel::expandParentDirectories(const QUrl &url) // first subdir can be empty, if m_dirLister->url().path() does not end with '/' // this happens if baseUrl is not root but a home directory, see FoldersPanel, // so using QString::SkipEmptyParts - const QStringList subDirs = url.path().mid(pos).split(QDir::separator(), QString::SkipEmptyParts); + const QStringList subDirs = url.path().mid(pos).split(QDir::separator(), Qt::SkipEmptyParts); for (int i = 0; i < subDirs.count() - 1; ++i) { QString path = urlToExpand.path(); if (!path.endsWith(QLatin1Char('/'))) { @@ -741,7 +737,7 @@ void KFileItemModel::removeFilteredChildren(const KItemRangeList& itemRanges) } QSet parents; - foreach (const KItemRange& range, itemRanges) { + for (const KItemRange& range : itemRanges) { for (int index = range.index; index < range.index + range.count; ++index) { parents.insert(m_itemData.at(index)); } @@ -861,7 +857,7 @@ void KFileItemModel::resortAllItems() // been moved because of the resorting. QList oldUrls; oldUrls.reserve(itemCount); - foreach (const ItemData* itemData, m_itemData) { + for (const ItemData* itemData : qAsConst(m_itemData)) { oldUrls.append(itemData->item.url()); } @@ -904,13 +900,13 @@ void KFileItemModel::resortAllItems() movedToIndexes.append(newIndex); } - emit itemsMoved(KItemRange(firstMovedIndex, movedItemsCount), movedToIndexes); + 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) { - emit groupsChanged(); + Q_EMIT groupsChanged(); } } @@ -929,7 +925,9 @@ void KFileItemModel::slotCompleted() // Note that the parent folder must be expanded before any of its subfolders become visible. // Therefore, some URLs in m_restoredExpandedUrls might not be visible yet // -> we expand the first visible URL we find in m_restoredExpandedUrls. - foreach (const QUrl& url, m_urlsToExpand) { + // Iterate over a const copy because items are deleted and inserted within the loop + const auto urlsToExpand = m_urlsToExpand; + for(const QUrl &url : urlsToExpand) { const int indexForUrl = index(url); if (indexForUrl >= 0) { m_urlsToExpand.remove(url); @@ -946,7 +944,7 @@ void KFileItemModel::slotCompleted() m_urlsToExpand.clear(); } - emit directoryLoadingCompleted(); + Q_EMIT directoryLoadingCompleted(); } void KFileItemModel::slotCanceled() @@ -954,7 +952,7 @@ void KFileItemModel::slotCanceled() m_maximumUpdateIntervalTimer->stop(); dispatchPendingItemsToInsert(); - emit directoryLoadingCanceled(); + Q_EMIT directoryLoadingCanceled(); } void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemList& items) @@ -995,7 +993,7 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis } } - QList itemDataList = createItemDataList(parentUrl, items); + const QList itemDataList = createItemDataList(parentUrl, items); if (!m_filter.hasSetFilters()) { m_pendingItemsToInsert.append(itemDataList); @@ -1003,7 +1001,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. - foreach (ItemData* itemData, itemDataList) { + for (ItemData* itemData : itemDataList) { if (m_filter.matches(itemData->item)) { m_pendingItemsToInsert.append(itemData); } else { @@ -1026,7 +1024,7 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items) QVector indexesToRemove; indexesToRemove.reserve(items.count()); - foreach (const KFileItem& item, items) { + for (const KFileItem& item : items) { const int indexForItem = index(item); if (indexForItem >= 0) { indexesToRemove.append(indexForItem); @@ -1048,7 +1046,7 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items) indexesToRemoveWithChildren.reserve(m_itemData.count()); const int itemCount = m_itemData.count(); - foreach (int index, indexesToRemove) { + for (int index : qAsConst(indexesToRemove)) { indexesToRemoveWithChildren.append(index); const int parentLevel = expandedParentsCount(index); @@ -1155,7 +1153,7 @@ void KFileItemModel::slotClear() qDeleteAll(m_itemData); m_itemData.clear(); m_items.clear(); - emit itemsRemoved(KItemRangeList() << KItemRange(0, removedCount)); + Q_EMIT itemsRemoved(KItemRangeList() << KItemRange(0, removedCount)); } m_expandedDirs.clear(); @@ -1271,7 +1269,7 @@ void KFileItemModel::insertItems(QList& newItems) // It will be re-populated with the updated indices if index(const QUrl&) is called. m_items.clear(); - emit itemsInserted(itemRanges); + Q_EMIT itemsInserted(itemRanges); #ifdef KFILEITEMMODEL_DEBUG qCDebug(DolphinDebug) << "[TIME] Inserting of" << newItems.count() << "items:" << timer.elapsed(); @@ -1288,7 +1286,7 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe // Step 1: Remove the items from m_itemData, and free the ItemData. int removedItemsCount = 0; - foreach (const KItemRange& range, itemRanges) { + for (const KItemRange& range : itemRanges) { removedItemsCount += range.count; for (int index = range.index; index < range.index + range.count; ++index) { @@ -1324,7 +1322,7 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe // It will be re-populated with the updated indices if index(const QUrl&) is called. m_items.clear(); - emit itemsRemoved(itemRanges); + Q_EMIT itemsRemoved(itemRanges); } QList KFileItemModel::createItemDataList(const QUrl& parentUrl, const KFileItemList& items) const @@ -1342,7 +1340,7 @@ QList KFileItemModel::createItemDataList(const QUrl& QList itemDataList; itemDataList.reserve(items.count()); - foreach (const KFileItem& item, items) { + for (const KFileItem& item : items) { ItemData* itemData = new ItemData(); itemData->item = item; itemData->parent = parentItem; @@ -1363,7 +1361,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. - foreach (ItemData* itemData, itemDataList) { + for (ItemData* itemData : qAsConst(itemDataList)) { if (itemData->values.isEmpty()) { itemData->values = retrieveData(itemData->item, itemData->parent); } @@ -1372,7 +1370,7 @@ void KFileItemModel::prepareItemsForSorting(QList& itemDataList) case TypeRole: // At least store the data including the file type for items with known MIME type. - foreach (ItemData* itemData, itemDataList) { + for (ItemData* itemData : qAsConst(itemDataList)) { if (itemData->values.isEmpty()) { const KFileItem item = itemData->item; if (item.isDir() || item.isMimeTypeKnown()) { @@ -1440,12 +1438,12 @@ void KFileItemModel::removeExpandedItems() void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList& itemRanges, const QSet& changedRoles) { - emit itemsChanged(itemRanges, 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))) { - foreach (const KItemRange& range, itemRanges) { + for (const KItemRange& range : itemRanges) { bool needsResorting = false; const int first = range.index; @@ -1667,7 +1665,13 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, } if (item.isMimeTypeKnown()) { - data.insert(sharedValue("iconName"), item.iconName()); + QString iconName = item.iconName(); + if (!QIcon::hasThemeIcon(iconName)) { + QMimeType mimeType = QMimeDatabase().mimeTypeForName(item.mimetype()); + iconName = mimeType.genericIconName(); + } + + data.insert(sharedValue("iconName"), iconName); if (m_requestRole[TypeRole]) { data.insert(sharedValue("type"), item.mimeComment()); @@ -1715,7 +1719,7 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b, const QColla } } - if (m_sortDirsFirst || m_sortRole == SizeRole) { + if (m_sortDirsFirst) { const bool isDirA = a->item.isDir(); const bool isDirB = b->item.isDir(); if (isDirA && !isDirB) { @@ -1764,45 +1768,51 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const break; case SizeRole: { - if (itemA.isDir()) { - // See "if (m_sortFoldersFirst || m_sortRole == SizeRole)" in KFileItemModel::lessThan(): - Q_ASSERT(itemB.isDir()); - - QVariant valueA, valueB; - if (DetailsModeSettings::directorySizeCount()) { - // use dir size then - valueA = a->values.value("size"); - valueB = b->values.value("size"); - } else { - valueA = a->values.value("count"); - valueB = b->values.value("count"); - } - if (valueA.isNull() && valueB.isNull()) { - result = 0; - } else if (valueA.isNull()) { - result = -1; - } else if (valueB.isNull()) { - result = +1; - } else { - if (valueA < valueB) { - return -1; - } else { + if (DetailsModeSettings::directorySizeCount() && (itemA.isDir() || itemB.isDir())) { + // folders first then + if (itemA.isDir() && itemB.isDir()) { + auto valueA = a->values.value("count"); + auto valueB = b->values.value("count"); + if (valueA.isNull()) { + if (valueB.isNull()) { + return 0; + } else { + return -1; + } + } else if (valueB.isNull()) { return +1; + } else { + if (valueA.toLongLong() < valueB.toLongLong()) { + return -1; + } else { + return +1; + } } - } - } else { - // See "if (m_sortFoldersFirst || m_sortRole == SizeRole)" in KFileItemModel::lessThan(): - Q_ASSERT(!itemB.isDir()); - const KIO::filesize_t sizeA = itemA.size(); - const KIO::filesize_t sizeB = itemB.size(); - if (sizeA > sizeB) { - result = +1; - } else if (sizeA < sizeB) { - result = -1; + } else if (itemA.isDir()) { + return 1; } else { - result = 0; + return -1; } } + KIO::filesize_t sizeA = 0; + if (itemA.isDir()) { + sizeA = a->values.value("size").toULongLong(); + } else { + sizeA = itemA.size(); + } + KIO::filesize_t sizeB = 0; + if (itemB.isDir()) { + sizeB = b->values.value("size").toULongLong(); + } else { + sizeB = itemB.size(); + } + if (sizeA > sizeB) { + result = +1; + } else if (sizeA < sizeB) { + result = -1; + } else { + result = 0; + } break; } @@ -2319,14 +2329,14 @@ void KFileItemModel::emitSortProgress(int resolvedCount) resortAllItems(); } - emit directorySortingProgress(100); + Q_EMIT directorySortingProgress(100); } else if (itemCount > 0) { resolvedCount = qBound(0, resolvedCount, itemCount); const int progress = resolvedCount * 100 / itemCount; if (m_sortingProgressPercent != progress) { m_sortingProgressPercent = progress; - emit directorySortingProgress(progress); + Q_EMIT directorySortingProgress(progress); } } } @@ -2378,7 +2388,7 @@ void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout) { QElapsedTimer timer; timer.start(); - foreach (const KFileItem& item, items) { // krazy:exclude=foreach + 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