X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/b1f9c2e5c90548f391477fa17889ff8d1abf8f53..9281664e5b1e492087604264b145b390e8880e81:/src/kitemviews/kfileitemmodelrolesupdater.cpp diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index e2d32265e..497c13b52 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -13,8 +13,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -368,19 +370,28 @@ void KFileItemModelRolesUpdater::slotItemsInserted(const KItemRangeList &itemRan // Determine the sort role synchronously for as many items as possible. if (m_resolvableRoles.contains(m_model->sortRole())) { + QList dirsWithAddedItems; + int insertedCount = 0; for (const KItemRange &range : itemRanges) { const int lastIndex = insertedCount + range.index + range.count - 1; for (int i = insertedCount + range.index; i <= lastIndex; ++i) { + const auto fileItem = m_model->fileItem(i); + const auto fileItemParentFolderUrl = fileItem.url().adjusted(QUrl::RemoveFilename); + if (!dirsWithAddedItems.contains(fileItemParentFolderUrl)) { + dirsWithAddedItems.append(fileItemParentFolderUrl); + } if (timer.elapsed() < MaxBlockTimeout) { applySortRole(i); } else { - m_pendingSortRoleItems.insert(m_model->fileItem(i)); + m_pendingSortRoleItems.insert(fileItem); } } insertedCount += range.count; } + recountDirectoryItems(dirsWithAddedItems); + applySortProgressToModel(); // If there are still items whose sort role is unknown, check if the @@ -437,17 +448,25 @@ void KFileItemModelRolesUpdater::slotItemsRemoved(const KItemRangeList &itemRang m_directoryContentsCounter->stopWorker(); } } else { + QList dirsWithDeletedItems; // Only remove the items from m_finishedItems. They will be removed // from the other sets later on. QSet::iterator it = m_finishedItems.begin(); while (it != m_finishedItems.end()) { if (m_model->index(*it) < 0) { + // Get the folder path of the file. + const auto folderUrl = it->url().adjusted(QUrl::RemoveFilename); + if (!dirsWithDeletedItems.contains(folderUrl)) { + dirsWithDeletedItems.append(folderUrl); + } it = m_finishedItems.erase(it); } else { ++it; } } + recountDirectoryItems(dirsWithDeletedItems); + // Removed items won't have hover previews loaded anymore. for (const KItemRange &itemRange : itemRanges) { int index = itemRange.index; @@ -549,32 +568,14 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem &item, const QPi return; } - QPixmap scaledPixmap = transformPreviewPixmap(pixmap); - QHash data = rolesData(item, index); - - const QStringList overlays = data["iconOverlays"].toStringList(); - // Strangely KFileItem::overlays() returns empty string-values, so - // we need to check first whether an overlay must be drawn at all. - // It is more efficient to do it here, as KIconLoader::drawOverlays() - // assumes that an overlay will be drawn and has some additional - // setup time. - if (!scaledPixmap.isNull()) { - for (const QString &overlay : overlays) { - if (!overlay.isEmpty()) { - // There is at least one overlay, draw all overlays above m_pixmap - // and cancel the check - KIconLoader::global()->drawOverlays(overlays, scaledPixmap, KIconLoader::Desktop); - break; - } - } - } - - data.insert("iconPixmap", scaledPixmap); + data.insert("iconPixmap", transformPreviewPixmap(pixmap)); + data.insert("supportsSequencing", m_previewJob->handlesSequences()); disconnect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); m_model->setData(index, data); connect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); + Q_EMIT previewJobFinished(); // For unit testing m_finishedItems.insert(item); } @@ -976,13 +977,6 @@ void KFileItemModelRolesUpdater::startPreviewJob() return; } - // PreviewJob internally caches items always with the size of - // 128 x 128 pixels or 256 x 256 pixels. A (slow) downscaling is done - // by PreviewJob if a smaller size is requested. For images KFileItemModelRolesUpdater must - // do a downscaling anyhow because of the frame, so in this case only the provided - // cache sizes are requested. - const QSize cacheSize = (m_iconSize.width() > 128) || (m_iconSize.height() > 128) ? QSize(256, 256) : QSize(128, 128); - // KIO::filePreview() will request the MIME-type of all passed items, which (in the // worst case) might block the application for several seconds. To prevent such // a blocking, we only pass items with known mime type to the preview job. @@ -1011,7 +1005,7 @@ void KFileItemModelRolesUpdater::startPreviewJob() } while (!m_pendingPreviewItems.isEmpty() && timer.elapsed() < MaxBlockTimeout); } - KIO::PreviewJob *job = new KIO::PreviewJob(itemSubSet, cacheSize, &m_enabledPlugins); + KIO::PreviewJob *job = new KIO::PreviewJob(itemSubSet, cacheSize(), &m_enabledPlugins); job->setDevicePixelRatio(m_devicePixelRatio); job->setIgnoreMaximumSize(itemSubSet.first().isLocalFile() && !itemSubSet.first().isSlow() && m_localFileSizePreviewLimit <= 0); if (job->uiDelegate()) { @@ -1029,7 +1023,11 @@ QPixmap KFileItemModelRolesUpdater::transformPreviewPixmap(const QPixmap &pixmap { QPixmap scaledPixmap = pixmap; - if (!pixmap.hasAlpha() && !pixmap.isNull() && m_iconSize.width() > KIconLoader::SizeSmallMedium && m_iconSize.height() > KIconLoader::SizeSmallMedium) { + if (pixmap.isNull()) { + return scaledPixmap; + } + + if (!pixmap.hasAlpha() && m_iconSize.width() > KIconLoader::SizeSmallMedium && m_iconSize.height() > KIconLoader::SizeSmallMedium) { if (m_enlargeSmallPreviews) { KPixmapModifier::applyFrame(scaledPixmap, m_iconSize); } else { @@ -1057,7 +1055,7 @@ QPixmap KFileItemModelRolesUpdater::transformPreviewPixmap(const QPixmap &pixmap KPixmapModifier::applyFrame(scaledPixmap, m_iconSize); } } - } else if (!pixmap.isNull()) { + } else { KPixmapModifier::scale(scaledPixmap, m_iconSize * m_devicePixelRatio); scaledPixmap.setDevicePixelRatio(m_devicePixelRatio); } @@ -1065,6 +1063,16 @@ QPixmap KFileItemModelRolesUpdater::transformPreviewPixmap(const QPixmap &pixmap return scaledPixmap; } +QSize KFileItemModelRolesUpdater::cacheSize() +{ + // PreviewJob internally caches items always with the size of + // 128 x 128 pixels or 256 x 256 pixels. A (slow) downscaling is done + // by PreviewJob if a smaller size is requested. For images KFileItemModelRolesUpdater must + // do a downscaling anyhow because of the frame, so in this case only the provided + // cache sizes are requested. + return (m_iconSize.width() > 128) || (m_iconSize.height() > 128) ? QSize(256, 256) : QSize(128, 128); +} + void KFileItemModelRolesUpdater::loadNextHoverSequencePreview() { if (m_hoverSequenceItem.isNull() || m_hoverSequencePreviewJob) { @@ -1105,14 +1113,7 @@ void KFileItemModelRolesUpdater::loadNextHoverSequencePreview() return; } - // PreviewJob internally caches items always with the size of - // 128 x 128 pixels or 256 x 256 pixels. A (slow) downscaling is done - // by PreviewJob if a smaller size is requested. For images KFileItemModelRolesUpdater must - // do a downscaling anyhow because of the frame, so in this case only the provided - // cache sizes are requested. - const QSize cacheSize = (m_iconSize.width() > 128) || (m_iconSize.height() > 128) ? QSize(256, 256) : QSize(128, 128); - - KIO::PreviewJob *job = new KIO::PreviewJob({m_hoverSequenceItem}, cacheSize, &m_enabledPlugins); + KIO::PreviewJob *job = new KIO::PreviewJob({m_hoverSequenceItem}, cacheSize(), &m_enabledPlugins); job->setSequenceIndex(loadSeqIdx); job->setIgnoreMaximumSize(m_hoverSequenceItem.isLocalFile() && !m_hoverSequenceItem.isSlow() && m_localFileSizePreviewLimit <= 0); @@ -1287,13 +1288,20 @@ bool KFileItemModelRolesUpdater::applyResolvedRoles(int index, ResolveHint hint) void KFileItemModelRolesUpdater::startDirectorySizeCounting(const KFileItem &item, int index) { + if (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::None) { + return; + } + + // Set any remote files to unknown size (-1). if (!item.isLocalFile()) { + resetSizeData(index, -1); return; + } else { + resetSizeData(index); } - if (ContentDisplaySettings::directorySizeCount() || item.isSlow()) { + if (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount || item.isSlow()) { // fastpath no recursion necessary - auto data = m_model->data(index); if (data.value("size") == -2) { // means job already started @@ -1313,38 +1321,49 @@ void KFileItemModelRolesUpdater::startDirectorySizeCounting(const KFileItem &ite connect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); auto listJob = KIO::listDir(url, KIO::HideProgressInfo); - QObject::connect(listJob, &KIO::ListJob::entries, this, [this, item](const KJob * /*job*/, const KIO::UDSEntryList &list) { + + QObject::connect(listJob, &KIO::ListJob::entries, this, [this, item](const KJob *job, const KIO::UDSEntryList &list) { int index = m_model->index(item); if (index < 0) { return; } auto data = m_model->data(index); int origCount = data.value("count").toInt(); - int entryCount = origCount; + // Get the amount of processed items... + int entryCount = job->processedAmount(KJob::Bytes); + // ...and then remove the unwanted items from the amount. for (const KIO::UDSEntry &entry : list) { const auto name = entry.stringValue(KIO::UDSEntry::UDS_NAME); if (name == QStringLiteral("..") || name == QStringLiteral(".")) { + --entryCount; continue; } if (!m_model->showHiddenFiles() && name.startsWith(QLatin1Char('.'))) { + --entryCount; continue; } if (m_model->showDirectoriesOnly() && !entry.isDir()) { + --entryCount; continue; } - ++entryCount; } - // count has changed - if (origCount < entryCount) { - QHash data; - data.insert("isExpandable", entryCount > 0); - data.insert("count", entryCount); + QHash newData; + QVariant expandable = data.value("isExpandable"); + if (expandable.isNull() || expandable.toBool() != (entryCount > 0)) { + // if expandable has changed + newData.insert("isExpandable", entryCount > 0); + } + + if (origCount != entryCount) { + newData.insert("count", entryCount); + } + if (!newData.isEmpty()) { disconnect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); - m_model->setData(index, data); + m_model->setData(index, newData); connect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); } }); @@ -1521,4 +1540,27 @@ void KFileItemModelRolesUpdater::trimHoverSequenceLoadedItems() } } +void KFileItemModelRolesUpdater::resetSizeData(const int index, const int size) +{ + disconnect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); + auto data = m_model->data(index); + data.insert("size", size); + m_model->setData(index, data); + connect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); +} + +void KFileItemModelRolesUpdater::recountDirectoryItems(const QList directories) +{ + for (const auto &dir : directories) { + auto index = m_model->index(dir); + if (index < 0) { + continue; + } + auto item = m_model->fileItem(index); + if (item.isDir()) { + startDirectorySizeCounting(item, index); + } + } +} + #include "moc_kfileitemmodelrolesupdater.cpp"