2 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
3 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
5 * SPDX-License-Identifier: GPL-2.0-or-later
8 #include "kdirectorycontentscounterworker.h"
10 // Required includes for subItemsCount():
15 #include <qplatformdefs.h>
18 #include "dolphin_detailsmodesettings.h"
20 KDirectoryContentsCounterWorker::KDirectoryContentsCounterWorker(QObject
* parent
) :
23 qRegisterMetaType
<KDirectoryContentsCounterWorker::Options
>();
27 KDirectoryContentsCounterWorker::CountResult
walkDir(const QString
&dirPath
,
28 const bool countHiddenFiles
,
29 const bool countDirectoriesOnly
,
31 const uint allowedRecursiveLevel
)
35 auto dir
= QT_OPENDIR(QFile::encodeName(dirPath
));
40 while ((dirEntry
= QT_READDIR(dir
))) {
41 if (dirEntry
->d_name
[0] == '.') {
42 if (dirEntry
->d_name
[1] == '\0' || !countHiddenFiles
) {
43 // Skip "." or hidden files
46 if (dirEntry
->d_name
[1] == '.' && dirEntry
->d_name
[2] == '\0') {
52 // If only directories are counted, consider an unknown file type and links also
53 // as directory instead of trying to do an expensive stat()
54 // (see bugs 292642 and 299997).
55 const bool countEntry
= !countDirectoriesOnly
||
56 dirEntry
->d_type
== DT_DIR
||
57 dirEntry
->d_type
== DT_LNK
||
58 dirEntry
->d_type
== DT_UNKNOWN
;
63 if (allowedRecursiveLevel
> 0) {
65 bool linkFound
= false;
66 QString nameBuf
= QStringLiteral("%1/%2").arg(dirPath
, dirEntry
->d_name
);
68 if (dirEntry
->d_type
== DT_REG
|| dirEntry
->d_type
== DT_LNK
) {
69 if (QT_STAT(nameBuf
.toLocal8Bit(), &buf
) == 0) {
70 if (S_ISDIR(buf
.st_mode
)) {
71 // was a dir link, recurse
77 if (dirEntry
->d_type
== DT_DIR
|| linkFound
) {
78 // recursion for dirs and dir links
79 size
+= walkDir(nameBuf
, countHiddenFiles
, countDirectoriesOnly
, dirEntry
, allowedRecursiveLevel
- 1).size
;
85 return KDirectoryContentsCounterWorker::CountResult
{count
, size
};
89 KDirectoryContentsCounterWorker::CountResult
KDirectoryContentsCounterWorker::subItemsCount(const QString
& path
, Options options
)
91 const bool countHiddenFiles
= options
& CountHiddenFiles
;
92 const bool countDirectoriesOnly
= options
& CountDirectoriesOnly
;
96 QDir::Filters filters
= QDir::NoDotAndDotDot
| QDir::System
;
97 if (countHiddenFiles
) {
98 filters
|= QDir::Hidden
;
100 if (countDirectoriesOnly
) {
101 filters
|= QDir::Dirs
;
103 filters
|= QDir::AllEntries
;
105 return {dir
.entryList(filters
).count(), 0};
108 const uint maxRecursiveLevel
= DetailsModeSettings::directorySizeCount() ? 1 : DetailsModeSettings::recursiveDirectorySizeLimit();
110 QT_DIRENT
*dirEntry
= nullptr;
112 auto res
= walkDir(QFile::encodeName(path
), countHiddenFiles
, countDirectoriesOnly
, dirEntry
, maxRecursiveLevel
);
118 void KDirectoryContentsCounterWorker::countDirectoryContents(const QString
& path
, Options options
)
120 auto res
= subItemsCount(path
, options
);
121 emit
result(path
, res
.count
, res
.size
);