]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/private/kdirectorycontentscounterworker.cpp
Merge branch 'release/20.08'
[dolphin.git] / src / kitemviews / private / kdirectorycontentscounterworker.cpp
index e649c20e142f3cbaa024b3242862c4afcea0c3d3..59ff471aeee5e804b6ae8fada4bf642d0b602f8b 100644 (file)
@@ -1,66 +1,43 @@
-/***************************************************************************
- *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
- *   Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com>    *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
+/*
+ * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
+ * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
 
 #include "kdirectorycontentscounterworker.h"
 
 // Required includes for subItemsCount():
-#ifdef Q_WS_WIN
-    #include <QDir>
+#ifdef Q_OS_WIN
+#include <QDir>
 #else
-    #include <dirent.h>
-    #include <QFile>
+#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)
+#ifndef Q_OS_WIN
+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_WS_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 kdelibs/kio/kio/kdirmodel.cpp
-    // Copyright (C) 2006 David Faure <faure@kde.org>
-
     int count = -1;
-    DIR* dir = ::opendir(QFile::encodeName(path));
-    if (dir) {  // krazy:exclude=syscalls
+    long size = -1;
+    auto dir = QT_OPENDIR(QFile::encodeName(dirPath));
+    if (dir) {
         count = 0;
-        struct dirent *dirEntry = 0;
-        while ((dirEntry = ::readdir(dir))) {
+        QT_STATBUF buf;
+
+        while ((dirEntry = QT_READDIR(dir))) {
             if (dirEntry->d_name[0] == '.') {
                 if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) {
                     // Skip "." or hidden files
@@ -76,20 +53,70 @@ 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;
+                }
+            }
         }
-        ::closedir(dir);
+        QT_CLOSEDIR(dir);
     }
-    return count;
+    return KDirectoryContentsCounterWorker::CountResult{count, size};
+}
+#endif
+
+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);
 }