From 914cd9010b52125a01e607c0b0f08401be225106 Mon Sep 17 00:00:00 2001 From: Pan Zhang Date: Wed, 13 May 2026 18:40:25 +0800 Subject: kfileitemmodelrolesupdater: fix directory item count for large folders Dolphin reported an incorrect item count in the "Size" column for directories containing 200 or more entries. Use KIO::ListJob::ListFlag::ExcludeDotAndDotDot and ExcludeHidden to filter entries at the source. Use a local counter (totalCount) captured via std::shared_ptr in the lambda to ensure each scan job starts from zero and maintains its own state. Add a fast path using list.size() when showDirectoriesOnly is false to improve performance. BUG: 509150 --- src/kitemviews/kfileitemmodelrolesupdater.cpp | 46 +++++++++++++++------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 0f4816424..38fa58436 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -1288,36 +1288,40 @@ void KFileItemModelRolesUpdater::startDirectorySizeCounting(const KFileItem &ite m_model->setData(index, data); connect(m_model, &KFileItemModel::itemsChanged, this, &KFileItemModelRolesUpdater::slotItemsChanged); - auto listJob = KIO::listDir(url, KIO::HideProgressInfo); + // Use KIO flags to exclude dot entries at the source to simplify counting + KIO::ListJob::ListFlags flags = KIO::ListJob::ListFlag::ExcludeDotAndDotDot; + if (!m_model->showHiddenFiles()) { + flags |= KIO::ListJob::ListFlag::ExcludeHidden; + } + + auto listJob = KIO::listDir(url, KIO::HideProgressInfo, flags); - QObject::connect(listJob, &KIO::ListJob::entries, this, [this, item](const KJob *job, const KIO::UDSEntryList &list) { + // Define a local counter to accumulate results for THIS specific job instance. + // Using a shared pointer allows the lambda batches to share and update the same state. + auto totalCount = std::make_shared(0); + + QObject::connect(listJob, &KIO::ListJob::entries, this, [this, item, totalCount](const KJob *job, const KIO::UDSEntryList &list) { + Q_UNUSED(job) int index = m_model->index(item); if (index < 0) { return; } - auto data = m_model->data(index); - int origCount = data.value("count").toInt(); - // 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; + // Accumulate entries for this batch into our job-specific counter + if (!m_model->showDirectoriesOnly()) { + *totalCount += list.size(); + } else { + for (const KIO::UDSEntry &entry : list) { + if (entry.isDir()) { + (*totalCount)++; + } } } + const int entryCount = *totalCount; + auto data = m_model->data(index); + int origCount = data.value("count").toInt(); + QHash newData; QVariant expandable = data.value("isExpandable"); if (expandable.isNull() || expandable.toBool() != (entryCount > 0)) { -- cgit v1.3.1