┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews/private/kdirectorycontentscounterworker.cpp
diff options
context:
space:
mode:
authorMéven Car <[email protected]>2020-05-04 07:26:26 +0200
committerMéven Car <[email protected]>2020-05-04 07:26:59 +0200
commite6ea3ab4c41dcc115143a237aafd3a1152849433 (patch)
tree73c849d42ac69d2c0dc8412228c6203963ffa6f9 /src/kitemviews/private/kdirectorycontentscounterworker.cpp
parentd34559d1c12a152afa235af8ba6eeb536aa31a9e (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/kdirectorycontentscounterworker.cpp')
-rw-r--r--src/kitemviews/private/kdirectorycontentscounterworker.cpp98
1 files changed, 68 insertions, 30 deletions
diff --git a/src/kitemviews/private/kdirectorycontentscounterworker.cpp b/src/kitemviews/private/kdirectorycontentscounterworker.cpp
index e9c954ed9..3117d07aa 100644
--- a/src/kitemviews/private/kdirectorycontentscounterworker.cpp
+++ b/src/kitemviews/private/kdirectorycontentscounterworker.cpp
@@ -22,44 +22,33 @@
// Required includes for subItemsCount():
#ifdef Q_OS_WIN
- #include <QDir>
+#include <QDir>
#else
- #include <QFile>
- #include <qplatformdefs.h>
+#include <QFile>
+#include <qplatformdefs.h>
#endif
+#include "dolphin_detailsmodesettings.h"
+
KDirectoryContentsCounterWorker::KDirectoryContentsCounterWorker(QObject* parent) :
QObject(parent)
{
qRegisterMetaType<KDirectoryContentsCounterWorker::Options>();
}
-int KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options options)
+KDirectoryContentsCounterWorker::CountResult walkDir(const QString &dirPath,
+ const bool countHiddenFiles,
+ const bool countDirectoriesOnly,
+ QT_DIRENT *dirEntry,
+ const uint allowedRecursiveLevel)
{
- const bool countHiddenFiles = options & CountHiddenFiles;
- const bool countDirectoriesOnly = options & CountDirectoriesOnly;
-
-#ifdef Q_OS_WIN
- QDir dir(path);
- QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
- if (countHiddenFiles) {
- filters |= QDir::Hidden;
- }
- if (countDirectoriesOnly) {
- filters |= QDir::Dirs;
- } else {
- filters |= QDir::AllEntries;
- }
- return dir.entryList(filters).count();
-#else
- // Taken from kio/src/widgets/kdirmodel.cpp
- // Copyright (C) 2006 David Faure <[email protected]>
-
int count = -1;
- auto dir = QT_OPENDIR(QFile::encodeName(path));
+ long size = -1;
+ auto dir = QT_OPENDIR(QFile::encodeName(dirPath));
if (dir) {
count = 0;
- QT_DIRENT *dirEntry = nullptr;
+ QT_STATBUF buf;
+
while ((dirEntry = QT_READDIR(dir))) {
if (dirEntry->d_name[0] == '.') {
if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) {
@@ -76,20 +65,69 @@ int KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options
// as directory instead of trying to do an expensive stat()
// (see bugs 292642 and 299997).
const bool countEntry = !countDirectoriesOnly ||
- dirEntry->d_type == DT_DIR ||
- dirEntry->d_type == DT_LNK ||
- dirEntry->d_type == DT_UNKNOWN;
+ dirEntry->d_type == DT_DIR ||
+ dirEntry->d_type == DT_LNK ||
+ dirEntry->d_type == DT_UNKNOWN;
if (countEntry) {
++count;
}
+
+ if (allowedRecursiveLevel > 0) {
+
+ bool linkFound = false;
+ QString nameBuf = QStringLiteral("%1/%2").arg(dirPath, dirEntry->d_name);
+
+ if (dirEntry->d_type == DT_REG || dirEntry->d_type == DT_LNK) {
+ if (QT_STAT(nameBuf.toLocal8Bit(), &buf) == 0) {
+ if (S_ISDIR(buf.st_mode)) {
+ // was a dir link, recurse
+ linkFound = true;
+ }
+ size += buf.st_size;
+ }
+ }
+ if (dirEntry->d_type == DT_DIR || linkFound) {
+ // recursion for dirs and dir links
+ size += walkDir(nameBuf, countHiddenFiles, countDirectoriesOnly, dirEntry, allowedRecursiveLevel - 1).size;
+ }
+ }
}
QT_CLOSEDIR(dir);
}
- return count;
+ return KDirectoryContentsCounterWorker::CountResult{count, size};
+}
+
+KDirectoryContentsCounterWorker::CountResult KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options options)
+{
+ const bool countHiddenFiles = options & CountHiddenFiles;
+ const bool countDirectoriesOnly = options & CountDirectoriesOnly;
+
+#ifdef Q_OS_WIN
+ QDir dir(path);
+ QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
+ if (countHiddenFiles) {
+ filters |= QDir::Hidden;
+ }
+ if (countDirectoriesOnly) {
+ filters |= QDir::Dirs;
+ } else {
+ filters |= QDir::AllEntries;
+ }
+ return {dir.entryList(filters).count(), 0};
+#else
+
+ const uint maxRecursiveLevel = DetailsModeSettings::directorySizeCount() ? 1 : DetailsModeSettings::recursiveDirectorySizeLimit();
+
+ QT_DIRENT *dirEntry = nullptr;
+
+ auto res = walkDir(QFile::encodeName(path), countHiddenFiles, countDirectoriesOnly, dirEntry, maxRecursiveLevel);
+
+ return res;
#endif
}
void KDirectoryContentsCounterWorker::countDirectoryContents(const QString& path, Options options)
{
- emit result(path, subItemsCount(path, options));
+ auto res = subItemsCount(path, options);
+ emit result(path, res.count, res.size);
}