diff options
| author | Pan Zhang <[email protected]> | 2026-05-13 18:40:25 +0800 |
|---|---|---|
| committer | Méven Car <[email protected]> | 2026-05-13 10:40:25 +0000 |
| commit | 914cd9010b52125a01e607c0b0f08401be225106 (patch) | |
| tree | ce3406a5c132b7745742cda6ac58b04dc7704089 | |
| parent | 66e66b7c2881cfb182ec4bf0b18a959371748300 (diff) | |
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
| -rw-r--r-- | src/kitemviews/kfileitemmodelrolesupdater.cpp | 46 |
1 files 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<int>(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<QByteArray, QVariant> newData; QVariant expandable = data.value("isExpandable"); if (expandable.isNull() || expandable.toBool() != (entryCount > 0)) { |
