diff options
| author | Méven Car <[email protected]> | 2020-05-04 07:26:26 +0200 |
|---|---|---|
| committer | Méven Car <[email protected]> | 2020-05-04 07:26:59 +0200 |
| commit | e6ea3ab4c41dcc115143a237aafd3a1152849433 (patch) | |
| tree | 73c849d42ac69d2c0dc8412228c6203963ffa6f9 /src/kitemviews/private/kdirectorycontentscounter.cpp | |
| parent | d34559d1c12a152afa235af8ba6eeb536aa31a9e (diff) | |
[Details mode] Allow to fill the column size of directories with actual size
Summary:
Allow to compute the recursive size of directories to fill the details view size column.
A setting allow to set a limit to the recursive level, allowing the user to have some power over the setting.
When sorting by size and the feature is on, we get progressive ordering as the directory size are gathered.
KDirectoryContentsCounter uses a cache internally to keep results so that it can display directory size faster, but counts the dir size of directories each time it is asked to count the size a directory nevertheless and when the size has changed, it is updated.
KDirectoryContentsCounter uses one worker per instance only, meaning one process per view makes the disk spin.
FIXED-IN: 20.08
BUG: 190580
BUG: 158090
Test Plan:
With some recursion allowed:
{F8267580}
Without any recursion allowed (default):
{F8267581}
Reviewers: elvisangelaccio, ngraham, #dolphin
Reviewed By: elvisangelaccio, ngraham, #dolphin
Subscribers: feverfew, anthonyfieroni, iasensio, kfm-devel
Tags: #dolphin
Differential Revision: https://phabricator.kde.org/D25335
Diffstat (limited to 'src/kitemviews/private/kdirectorycontentscounter.cpp')
| -rw-r--r-- | src/kitemviews/private/kdirectorycontentscounter.cpp | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/src/kitemviews/private/kdirectorycontentscounter.cpp b/src/kitemviews/private/kdirectorycontentscounter.cpp index bd204fe8e..a19bce8b3 100644 --- a/src/kitemviews/private/kdirectorycontentscounter.cpp +++ b/src/kitemviews/private/kdirectorycontentscounter.cpp @@ -24,8 +24,14 @@ #include <KDirWatch> #include <QFileInfo> +#include <QDir> #include <QThread> +namespace { + /// cache of directory counting result + static QHash<QString, QPair<int, long>> *s_cache; +} + KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObject* parent) : QObject(parent), m_model(model), @@ -43,9 +49,12 @@ KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObj m_workerThread->start(); } + if (s_cache == nullptr) { + s_cache = new QHash<QString, QPair<int, long>>(); + } + m_worker = new KDirectoryContentsCounterWorker(); m_worker->moveToThread(m_workerThread); - ++m_workersCount; connect(this, &KDirectoryContentsCounter::requestDirectoryContentsCount, m_worker, &KDirectoryContentsCounterWorker::countDirectoryContents); @@ -58,9 +67,7 @@ KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObj KDirectoryContentsCounter::~KDirectoryContentsCounter() { - --m_workersCount; - - if (m_workersCount > 0) { + if (m_workerThread->isRunning()) { // The worker thread will continue running. It could even be running // a method of m_worker at the moment, so we delete it using // deleteLater() to prevent a crash. @@ -79,38 +86,17 @@ KDirectoryContentsCounter::~KDirectoryContentsCounter() } } -void KDirectoryContentsCounter::addDirectory(const QString& path) +void KDirectoryContentsCounter::scanDirectory(const QString& path) { startWorker(path); } -int KDirectoryContentsCounter::countDirectoryContentsSynchronously(const QString& path) -{ - const QString resolvedPath = QFileInfo(path).canonicalFilePath(); - - if (!m_dirWatcher->contains(resolvedPath)) { - m_dirWatcher->addDir(resolvedPath); - m_watchedDirs.insert(resolvedPath); - } - - KDirectoryContentsCounterWorker::Options options; - - if (m_model->showHiddenFiles()) { - options |= KDirectoryContentsCounterWorker::CountHiddenFiles; - } - - if (m_model->showDirectoriesOnly()) { - options |= KDirectoryContentsCounterWorker::CountDirectoriesOnly; - } - - return KDirectoryContentsCounterWorker::subItemsCount(path, options); -} - -void KDirectoryContentsCounter::slotResult(const QString& path, int count) +void KDirectoryContentsCounter::slotResult(const QString& path, int count, long size) { m_workerIsBusy = false; - const QString resolvedPath = QFileInfo(path).canonicalFilePath(); + const QFileInfo info = QFileInfo(path); + const QString resolvedPath = info.canonicalFilePath(); if (!m_dirWatcher->contains(resolvedPath)) { m_dirWatcher->addDir(resolvedPath); @@ -121,7 +107,22 @@ void KDirectoryContentsCounter::slotResult(const QString& path, int count) startWorker(m_queue.dequeue()); } - emit result(path, count); + if (s_cache->contains(resolvedPath)) { + const auto pair = s_cache->value(resolvedPath); + if (pair.first == count && pair.second == size) { + // no change no need to send another result event + return; + } + } + + if (info.dir().path() == m_model->rootItem().url().path()) { + // update cache or overwrite value + // when path is a direct children of the current model root + s_cache->insert(resolvedPath, QPair<int, long>(count, size)); + } + + // sends the results + emit result(resolvedPath, count, size); } void KDirectoryContentsCounter::slotDirWatchDirty(const QString& path) @@ -146,7 +147,7 @@ void KDirectoryContentsCounter::slotItemsRemoved() if (!m_watchedDirs.isEmpty()) { // Don't let KDirWatch watch for removed items if (allItemsRemoved) { - foreach (const QString& path, m_watchedDirs) { + for (const QString& path : qAsConst(m_watchedDirs)) { m_dirWatcher->removeDir(path); } m_watchedDirs.clear(); @@ -166,6 +167,13 @@ void KDirectoryContentsCounter::slotItemsRemoved() void KDirectoryContentsCounter::startWorker(const QString& path) { + if (s_cache->contains(path)) { + // fast path when in cache + // will be updated later if result has changed + const auto pair = s_cache->value(path); + emit result(path, pair.first, pair.second); + } + if (m_workerIsBusy) { m_queue.enqueue(path); } else { @@ -185,4 +193,3 @@ void KDirectoryContentsCounter::startWorker(const QString& path) } QThread* KDirectoryContentsCounter::m_workerThread = nullptr; -int KDirectoryContentsCounter::m_workersCount = 0; |
