]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/private/kdirectorycontentscounterworker.cpp
2a683cdbc7c2ef8e9bf8fc8dcda14704bf8653f1
[dolphin.git] / src / kitemviews / private / kdirectorycontentscounterworker.cpp
1 /*
2 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
3 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "kdirectorycontentscounterworker.h"
9
10 // Required includes for subItemsCount():
11 #ifdef Q_OS_WIN
12 #include <QDir>
13 #else
14 #include <QFile>
15 #include <qplatformdefs.h>
16 #endif
17
18 #include "dolphin_detailsmodesettings.h"
19
20 KDirectoryContentsCounterWorker::KDirectoryContentsCounterWorker(QObject* parent) :
21 QObject(parent)
22 {
23 qRegisterMetaType<KDirectoryContentsCounterWorker::Options>();
24 }
25
26 #ifndef Q_OS_WIN
27 KDirectoryContentsCounterWorker::CountResult walkDir(const QString &dirPath,
28 const bool countHiddenFiles,
29 const bool countDirectoriesOnly,
30 const uint allowedRecursiveLevel)
31 {
32 int count = -1;
33 long size = -1;
34 auto dir = QT_OPENDIR(QFile::encodeName(dirPath));
35 if (dir) {
36 count = 0;
37 size = 0;
38 QT_DIRENT *dirEntry;
39 QT_STATBUF buf;
40
41 while ((dirEntry = QT_READDIR(dir))) {
42 if (dirEntry->d_name[0] == '.') {
43 if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) {
44 // Skip "." or hidden files
45 continue;
46 }
47 if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') {
48 // Skip ".."
49 continue;
50 }
51 }
52
53 // If only directories are counted, consider an unknown file type and links also
54 // as directory instead of trying to do an expensive stat()
55 // (see bugs 292642 and 299997).
56 const bool countEntry = !countDirectoriesOnly ||
57 dirEntry->d_type == DT_DIR ||
58 dirEntry->d_type == DT_LNK ||
59 dirEntry->d_type == DT_UNKNOWN;
60 if (countEntry) {
61 ++count;
62 }
63
64 if (allowedRecursiveLevel > 0) {
65 QString nameBuf = QStringLiteral("%1/%2").arg(dirPath, dirEntry->d_name);
66
67 if (dirEntry->d_type == DT_REG) {
68 if (QT_STAT(nameBuf.toLocal8Bit(), &buf) == 0) {
69 size += buf.st_size;
70 }
71 }
72 if (dirEntry->d_type == DT_DIR) {
73 // recursion for dirs
74 auto subdirResult = walkDir(nameBuf, countHiddenFiles, countDirectoriesOnly, allowedRecursiveLevel - 1);
75 if (subdirResult.size > 0) {
76 size += subdirResult.size;
77 }
78 }
79 }
80 }
81 QT_CLOSEDIR(dir);
82 }
83 return KDirectoryContentsCounterWorker::CountResult{count, size};
84 }
85 #endif
86
87 KDirectoryContentsCounterWorker::CountResult KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options options)
88 {
89 const bool countHiddenFiles = options & CountHiddenFiles;
90 const bool countDirectoriesOnly = options & CountDirectoriesOnly;
91
92 #ifdef Q_OS_WIN
93 QDir dir(path);
94 QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
95 if (countHiddenFiles) {
96 filters |= QDir::Hidden;
97 }
98 if (countDirectoriesOnly) {
99 filters |= QDir::Dirs;
100 } else {
101 filters |= QDir::AllEntries;
102 }
103 return {static_cast<int>(dir.entryList(filters).count()), 0};
104 #else
105
106 const uint maxRecursiveLevel = DetailsModeSettings::directorySizeCount() ? 1 : DetailsModeSettings::recursiveDirectorySizeLimit();
107
108 auto res = walkDir(path, countHiddenFiles, countDirectoriesOnly, maxRecursiveLevel);
109
110 return res;
111 #endif
112 }
113
114 void KDirectoryContentsCounterWorker::countDirectoryContents(const QString& path, Options options)
115 {
116 auto res = subItemsCount(path, options);
117 Q_EMIT result(path, res.count, res.size);
118 }