summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Samir <[email protected]>2024-06-21 00:59:45 +0300
committerAhmad Samir <[email protected]>2024-06-27 03:35:02 +0300
commite583c3d5163a5512abac85e32359652e28a053f7 (patch)
treea8cb9487210cc084614923d82a1c318d255a3291
parent05d4740623477eda83c1ce544aeadffba3014806 (diff)
QDirListing: add flags to handle entries filtering
By extending IteratorFlag so that it replaces both QDir::Filter and QDirIterator::IteratorFlag enums, but with better defaults (based on how QDir/Iterator is used in 15-20 years worth of code in Qt and KDE). Make the QDirListing(QDir ~~) ctor private, also change it to use QDirIterator::IteratatorFlags; it will be used to port existing code. If QDir is ported to use QDirListing::IteratorFlags, instead of QDir::Filters, a public QDirListing(QDir) constructor can then be added. Pick-to: 6.8 Fixes: QTBUG-125504 Task-number: QTBUG-125859 Change-Id: Ide4ff8279f554029ac30d0579b0e8373ed4337f7 Reviewed-by: Thiago Macieira <[email protected]>
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp4
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp3
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp3
-rw-r--r--src/corelib/io/qabstractfileengine.cpp34
-rw-r--r--src/corelib/io/qabstractfileengine_p.h10
-rw-r--r--src/corelib/io/qdir.cpp13
-rw-r--r--src/corelib/io/qdir.h2
-rw-r--r--src/corelib/io/qdiriterator.cpp48
-rw-r--r--src/corelib/io/qdirlisting.cpp314
-rw-r--r--src/corelib/io/qdirlisting.h59
-rw-r--r--src/corelib/io/qfilesystemiterator_p.h1
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp4
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp7
-rw-r--r--src/corelib/io/qfsfileengine.cpp6
-rw-r--r--src/corelib/io/qfsfileengine_iterator.cpp7
-rw-r--r--src/corelib/io/qfsfileengine_iterator_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_p.h2
-rw-r--r--src/corelib/io/qresource.cpp7
-rw-r--r--src/corelib/io/qresource_iterator.cpp8
-rw-r--r--src/corelib/io/qresource_iterator_p.h2
-rw-r--r--src/corelib/io/qresource_p.h2
-rw-r--r--src/corelib/io/qstorageinfo_linux.cpp4
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp2
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp13
-rw-r--r--src/gui/itemmodels/qfileinfogatherer.cpp4
-rw-r--r--src/network/access/qnetworkdiskcache.cpp4
-rw-r--r--src/network/ssl/qsslcertificate.cpp4
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.cpp4
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.h4
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp6
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h2
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm4
-rw-r--r--src/plugins/tls/openssl/qtlsbackend_openssl.cpp9
-rw-r--r--src/tools/androiddeployqt/main.cpp2
-rw-r--r--src/tools/rcc/rcc.cpp4
-rw-r--r--src/tools/windeployqt/qtmoduleinfo.cpp3
-rw-r--r--tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp6
-rw-r--r--tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp369
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp3
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp4
40 files changed, 637 insertions, 352 deletions
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index b5df6179272..4e43b4e6bd7 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -314,9 +314,9 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
const QStringList sourceFilesFilter = sourceFilesForImplicitRulesFilter();
QStringList fixifiedSourceDirs = fileFixify(QList<QString>(source_directories.constBegin(), source_directories.constEnd()), FileFixifyAbsolute);
fixifiedSourceDirs.removeDuplicates();
- constexpr auto filters = QDir::Files | QDir::NoDotAndDotDot;
+ using F = QDirListing::IteratorFlag;
for (const QString &sourceDir : std::as_const(fixifiedSourceDirs)) {
- for (const auto &dirEntry : QDirListing(sourceDir, sourceFilesFilter, filters)) {
+ for (const auto &dirEntry : QDirListing(sourceDir, sourceFilesFilter, F::FilesOnly)) {
QString &duplicate = fileNames[dirEntry.completeBaseName()];
if (duplicate.isNull()) {
duplicate = dirEntry.filePath();
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 21925358677..82d47f59811 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -1293,9 +1293,8 @@ void VcprojGenerator::initDeploymentTool()
}
int pathSize = searchPath.size();
- constexpr auto filters = QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks;
using F = QDirListing::IteratorFlag;
- QDirListing dirList(searchPath, QStringList{nameFilter}, filters, F::Recursive);
+ QDirListing dirList(searchPath, QStringList{nameFilter}, F::FilesOnly | F::Recursive);
// foreach dirIterator-entry in d
for (const auto &dirEntry : dirList) {
const QString absoluteItemPath = Option::fixPathToTargetOS(dirEntry.absolutePath());
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp
index 231bf48d26b..0694daa6cba 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdirlisting.cpp
@@ -35,7 +35,8 @@ for (const auto &dirEntry : dirList) {
{
//! [2]
-QDirListing audioFileIt(u"/home/johndoe/"_s, {"*.mp3", "*.wav"}, QDir::Files);
+QDirListing audioFileIt(u"/home/johndoe/"_s, QStringList{u"*.mp3"_s, u"*.wav"_s},
+ QDirListing::IteratorFlag::FilesOnly);
//! [2]
}
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index ea5ce13b5eb..70e68be21c1 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -597,6 +597,21 @@ QStringList QAbstractFileEngine::entryList(QDir::Filters filters, const QStringL
Q_UNUSED(filterNames);
Q_UNREACHABLE_RETURN(ret);
#else
+ for (const auto &dirEntry : QDirListing(fileName(), filterNames, filters.toInt()))
+ ret.emplace_back(dirEntry.fileName());
+ return ret;
+#endif
+}
+
+QStringList QAbstractFileEngine::entryList(QDirListing::IteratorFlags filters,
+ const QStringList &filterNames) const
+{
+ QStringList ret;
+#ifdef QT_BOOTSTRAPPED
+ Q_UNUSED(filters);
+ Q_UNUSED(filterNames);
+ Q_UNREACHABLE_RETURN(ret);
+#else
for (const auto &dirEntry : QDirListing(fileName(), filterNames, filters))
ret.emplace_back(dirEntry.fileName());
return ret;
@@ -902,6 +917,15 @@ QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path, QD
{
}
+QAbstractFileEngineIterator::QAbstractFileEngineIterator(const QString &path,
+ QDirListing::IteratorFlags filters,
+ const QStringList &nameFilters)
+ : m_listingFilters(filters),
+ m_nameFilters(nameFilters),
+ m_path(appendSlashIfNeeded(path))
+{
+}
+
/*!
Destroys the QAbstractFileEngineIterator.
@@ -1017,6 +1041,16 @@ QAbstractFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
return {};
}
+QAbstractFileEngine::IteratorUniquePtr
+QAbstractFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames)
+{
+ Q_UNUSED(path);
+ Q_UNUSED(filters);
+ Q_UNUSED(filterNames);
+ return {};
+}
+
/*!
Reads a number of characters from the file into \a data. At most
\a maxlen characters will be read.
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index b2e0b248da7..5e6232af71a 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -18,6 +18,7 @@
#include <QtCore/private/qglobal_p.h>
#include "QtCore/qfile.h"
#include "QtCore/qdir.h"
+#include "QtCore/qdirlisting.h"
#include <memory>
#include <optional>
@@ -106,6 +107,8 @@ public:
virtual bool caseSensitive() const;
virtual bool isRelativePath() const;
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
+ virtual QStringList entryList(QDirListing::IteratorFlags filters,
+ const QStringList &filterNames) const;
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const;
virtual bool setPermissions(uint perms);
virtual QByteArray id() const;
@@ -128,6 +131,10 @@ public:
beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames);
virtual IteratorUniquePtr endEntryList() { return {}; }
+ virtual IteratorUniquePtr
+ beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames);
+
virtual qint64 read(char *data, qint64 maxlen);
virtual qint64 readLine(char *data, qint64 maxlen);
virtual qint64 write(const char *data, qint64 len);
@@ -203,6 +210,8 @@ class Q_CORE_EXPORT QAbstractFileEngineIterator
public:
QAbstractFileEngineIterator(const QString &path, QDir::Filters filters,
const QStringList &nameFilters);
+ QAbstractFileEngineIterator(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &nameFilters);
virtual ~QAbstractFileEngineIterator();
virtual bool advance() = 0;
@@ -225,6 +234,7 @@ private:
friend class QDirListingPrivate;
QDir::Filters m_filters;
+ QDirListing::IteratorFlags m_listingFilters;
QStringList m_nameFilters;
QString m_path;
};
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 05947f33804..3e1c778e98b 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -347,8 +347,10 @@ inline void QDirPrivate::initFileLists(const QDir &dir) const
QMutexLocker locker(&fileCache.mutex);
if (!fileCache.fileListsInitialized) {
QFileInfoList l;
- for (const auto &dirEntry : QDirListing(dir))
+ for (const auto &dirEntry : QDirListing(dir.path(), dir.nameFilters(),
+ dir.filter().toInt())) {
l.emplace_back(dirEntry.fileInfo());
+ }
sortFileList(sort, l, &fileCache.files, &fileCache.fileInfos);
fileCache.fileListsInitialized = true;
@@ -1427,7 +1429,7 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
}
}
- QDirListing dirList(d->dirEntry.filePath(), nameFilters, filters);
+ QDirListing dirList(d->dirEntry.filePath(), nameFilters, filters.toInt());
QStringList ret;
if (needsSorting) {
QFileInfoList l;
@@ -1473,7 +1475,7 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter
}
QFileInfoList l;
- for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, filters))
+ for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, filters.toInt()))
l.emplace_back(dirEntry.fileInfo());
QFileInfoList ret;
d->sortFileList(sort, l, nullptr, &ret);
@@ -1645,8 +1647,7 @@ bool QDir::removeRecursively()
bool success = true;
const QString dirPath = path();
// not empty -- we must empty it first
- constexpr auto dirFilters = QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
- for (const auto &dirEntry : QDirListing(dirPath, dirFilters)) {
+ for (const auto &dirEntry : QDirListing(dirPath, QDirListing::IteratorFlag::IncludeHidden)) {
const QString &filePath = dirEntry.filePath();
bool ok;
if (dirEntry.isDir() && !dirEntry.isSymLink()) {
@@ -1969,7 +1970,7 @@ bool QDir::exists(const QString &name) const
bool QDir::isEmpty(Filters filters) const
{
Q_D(const QDir);
- QDirListing dirList(d->dirEntry.filePath(), d->nameFilters, filters);
+ QDirListing dirList(d->dirEntry.filePath(), d->nameFilters, filters.toInt());
return dirList.cbegin() == dirList.cend();
}
#endif // !QT_BOOTSTRAPPED
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index 53c0900f95c..9430149e1c1 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -6,6 +6,7 @@
#include <QtCore/qcompare.h>
#include <QtCore/qstring.h>
+#include <QtCore/qdirlisting.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qstringlist.h>
@@ -244,6 +245,7 @@ private:
Q_DECLARE_EQUALITY_COMPARABLE(QDir)
friend class QDirIterator;
friend class QDirListing;
+ friend class QDirListingPrivate;
// Q_DECLARE_PRIVATE equivalent for shared data pointers
QDirPrivate *d_func();
const QDirPrivate *d_func() const { return d_ptr.constData(); }
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index 3604e673e2f..f539fd3bfaf 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -86,44 +86,12 @@ using namespace Qt::StringLiterals;
class QDirIteratorPrivate
{
- static QDirListing::IteratorFlags toDirListingFlags(QDirIterator::IteratorFlags flags)
- {
- using F = QDirListing::IteratorFlag;
- QDirListing::IteratorFlags listerFlags;
-
- if (flags & QDirIterator::NoIteratorFlags)
- listerFlags.setFlag(F::NoFlag);
- if (flags & QDirIterator::FollowSymlinks)
- listerFlags.setFlag(F::FollowSymlinks);
- if (flags & QDirIterator::Subdirectories)
- listerFlags.setFlag(F::Recursive);
-
- return listerFlags;
- }
-
public:
- QDirIteratorPrivate(const QDir &dir, QDirIterator::IteratorFlags flags)
- : lister(dir, toDirListingFlags(flags))
- {
- init();
- }
- QDirIteratorPrivate(const QString &path, QDirIterator::IteratorFlags flags)
- : lister(path, toDirListingFlags(flags))
- {
- init();
- }
- QDirIteratorPrivate(const QString &path, QDir::Filters filters,
- QDirIterator::IteratorFlags flags)
- : lister(path, filters, toDirListingFlags(flags))
- {
- init();
- }
- QDirIteratorPrivate(const QString &path, const QStringList &nameFilters, QDir::Filters filters,
- QDirIterator::IteratorFlags flags)
- : lister(path, nameFilters, filters, toDirListingFlags(flags))
- {
- init();
- }
+ QDirIteratorPrivate(const QString &path, const QStringList &nameFilters = {},
+ QDir::Filters filters = QDir::NoFilter,
+ QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags)
+ : lister(path, nameFilters, filters.toInt(), flags.toInt())
+ { init(); }
void init()
{
@@ -162,7 +130,7 @@ public:
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
- : d(new QDirIteratorPrivate(dir, flags))
+ : d(new QDirIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags))
{
}
@@ -180,7 +148,7 @@ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
- : d(new QDirIteratorPrivate(path, filters, flags))
+ : d(new QDirIteratorPrivate(path, {}, filters, flags))
{
}
@@ -197,7 +165,7 @@ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorF
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
- : d(new QDirIteratorPrivate(path, flags))
+ : d(new QDirIteratorPrivate(path, {}, QDir::NoFilter, flags))
{
}
diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp
index 9bfd414a6a9..408cccaaf56 100644
--- a/src/corelib/io/qdirlisting.cpp
+++ b/src/corelib/io/qdirlisting.cpp
@@ -15,7 +15,7 @@
directory contents recursively, and following symbolic links. Unlike
QDir::entryList(), QDirListing does not support sorting.
- The QDirListing constructor takes a QDir or a directory path as
+ The QDirListing constructor takes a directory path string as
argument. Here's how to iterate over all entries recursively:
\snippet code/src_corelib_io_qdirlisting.cpp 0
@@ -45,24 +45,73 @@
/*! \enum QDirListing::IteratorFlag
- This enum class describes flags can be used to configure the behavior of
- QDirListing. These flags can be bitwise OR'ed together.
-
- \value NoFlag The default value, representing no flags. The iterator
- will return entries for the assigned path.
-
- \value FollowSymlinks When combined with Recursive, this flag enables
- iterating through all subdirectories of the assigned path, following
- all symbolic links. Symbolic link loops (e.g., link => . or link =>
- ..) are automatically detected and ignored.
-
- \value Recursive List entries inside all subdirectories as well.
+ This enum class describes flags that can be used to configure the behavior
+ of QDirListing. Values from this enumerator can be bitwise OR'ed together.
+
+ \value Default
+ List all files, directories and symbolic links, including broken
+ symlinks (where the target doesn't exist).
+ Hidden files and directories and the special entries \c{.} and \c{..}
+ aren't listed by default.
+
+ \value ExcludeFiles
+ Don't list regular files. When combined with ResolveSymlinks, symbolic
+ links to regular files will be excluded too.
+
+ \value ExcludeDirs
+ Don't list directories. When combined with ResolveSymlinks, symbolic
+ links to directories will be excluded too.
+
+ \value ExcludeSpecial
+ Don't list special system files:
+ \list
+ \li On Unix: an entry that is not a directory, regular file or
+ symbolic link (including broken symlinks). That is, FIFO,
+ socket, character device, or block device.
+ \li On Windows: \c {.lnk}.
+ \endlist
+
+ \value ResolveSymlinks
+ Filter symbolic links based on the type of the target of the link,
+ rather than the symbolic link itself. With this flag, broken symbolic
+ links (where the target doesn't exist) are excluded. This flag is
+ ignored on operating systems that don't support symbolic links.
+
+ \value FilesOnly
+ Only regular files will be listed. When combined with ResolveSymlinks,
+ symbolic links to files will also be listed.
+
+ \value DirsOnly
+ Only directories will be listed. When combined with ResolveSymlinks,
+ symbolic links to directories will also be listed.
+
+ \value IncludeHidden
+ List hidden entries. When combined with Recursive, the iteration will
+ recurse into hidden sub-directories as well.
+
+ \value IncludeDotAndDotDot
+ List the \c {.} and \c{..} special entries.
+
+ \value CaseSensitive
+ The file glob patterns in the name filters passed to the QDirListing
+ constructor, will be matched case sensitively (for details, see
+ QDir::setNameFilters()).
+
+ \value Recursive
+ List entries inside all sub-directories as well. When combined with
+ FollowDirSymlinks, symbolic links to directories will be iterated too.
+
+ \value FollowDirSymlinks
+ When combined with Recursive, symbolic links to directories will be
+ iterated too. Symbolic link loops (e.g., link => . or link => ..) are
+ automatically detected and ignored.
*/
#include "qdirlisting.h"
#include "qdirentryinfo_p.h"
#include "qdir_p.h"
+#include "qdiriterator.h"
#include "qabstractfileengine_p.h"
#include <QtCore/qset.h>
@@ -85,6 +134,21 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
+static QDirListing::IteratorFlags toDirListingFlags(QDirIterator::IteratorFlags flags)
+{
+ using F = QDirListing::IteratorFlag;
+ QDirListing::IteratorFlags listerFlags;
+
+ if (flags & QDirIterator::NoIteratorFlags)
+ listerFlags.setFlag(F::Default);
+ if (flags & QDirIterator::FollowSymlinks)
+ listerFlags.setFlag(F::FollowDirSymlinks);
+ if (flags & QDirIterator::Subdirectories)
+ listerFlags.setFlag(F::Recursive);
+
+ return listerFlags;
+}
+
class QDirListingPrivate
{
public:
@@ -100,15 +164,32 @@ public:
bool matchesFilters(QDirEntryInfo &data) const;
bool hasIterators() const;
+ bool matchesLegacyFilters(QDirEntryInfo &data) const;
+ void setLegacyFilters(QDir::Filters dirFilters, QDirIterator::IteratorFlags dirIteratorFlags)
+ {
+ useLegacyFilters = true;
+ legacyDirFilters = dirFilters;
+ iteratorFlags = toDirListingFlags(dirIteratorFlags);
+ }
+
std::unique_ptr<QAbstractFileEngine> engine;
QDirEntryInfo initialEntryInfo;
QStringList nameFilters;
- QDir::Filters filters;
QDirListing::IteratorFlags iteratorFlags;
QDirEntryInfo currentEntryInfo;
+ bool useLegacyFilters = false;
+ QDir::Filters legacyDirFilters;
+
#if QT_CONFIG(regularexpression)
QList<QRegularExpression> nameRegExps;
+ bool regexMatchesName(const QString &fileName) const
+ {
+ if (nameRegExps.isEmpty())
+ return true;
+ auto hasMatch = [&fileName](const auto &re) { return re.match(fileName).hasMatch(); };
+ return std::any_of(nameRegExps.cbegin(), nameRegExps.cend(), hasMatch);
+ }
#endif
using FEngineIteratorPtr = std::unique_ptr<QAbstractFileEngineIterator>;
@@ -127,13 +208,21 @@ void QDirListingPrivate::init(bool resolveEngine = true)
if (nameFilters.contains("*"_L1))
nameFilters.clear();
- if (filters == QDir::NoFilter)
- filters = QDir::AllEntries;
+ if (useLegacyFilters) {
+ if (legacyDirFilters == QDir::NoFilter)
+ legacyDirFilters = QDir::AllEntries;
+ }
#if QT_CONFIG(regularexpression)
nameRegExps.reserve(nameFilters.size());
- const auto cs = filters.testAnyFlags(QDir::CaseSensitive) ? Qt::CaseSensitive
- : Qt::CaseInsensitive;
+
+ const bool isCase = [this] {
+ if (useLegacyFilters)
+ return legacyDirFilters.testAnyFlags(QDir::CaseSensitive);
+ return iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::CaseSensitive);
+ }();
+
+ const auto cs = isCase ? Qt::CaseSensitive : Qt::CaseInsensitive;
for (const auto &filter : nameFilters)
nameRegExps.emplace_back(QRegularExpression::fromWildcard(filter, cs));
#endif
@@ -171,7 +260,7 @@ void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
}();
- if (iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::FollowSymlinks)) {
+ if (iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::FollowDirSymlinks)) {
// Stop link loops
if (visitedLinks.hasSeen(entryInfo.canonicalFilePath()))
return;
@@ -179,7 +268,7 @@ void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
if (engine) {
engine->setFileName(path);
- if (auto it = engine->beginEntryList(path, filters, nameFilters)) {
+ if (auto it = engine->beginEntryList(path, iteratorFlags, nameFilters)) {
fileEngineIterators.emplace_back(std::move(it));
} else {
// No iterator; no entry list.
@@ -191,7 +280,7 @@ void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
fentry = &entryInfo.fileInfoOpt->d_ptr->fileEntry;
else
fentry = &entryInfo.entry;
- nativeIterators.emplace_back(std::make_unique<QFileSystemIterator>(*fentry, filters));
+ nativeIterators.emplace_back(std::make_unique<QFileSystemIterator>(*fentry, iteratorFlags));
#else
qWarning("Qt was built with -no-feature-filesystemiterator: no files/plugins will be found!");
#endif
@@ -201,6 +290,8 @@ void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
bool QDirListingPrivate::entryMatches(QDirEntryInfo &entryInfo)
{
checkAndPushDirectory(entryInfo);
+ if (useLegacyFilters)
+ return matchesLegacyFilters(entryInfo);
return matchesFilters(entryInfo);
}
@@ -260,6 +351,11 @@ void QDirListingPrivate::advance()
}
}
+static bool isDotOrDotDot(QStringView fileName)
+{
+ return fileName == "."_L1 || fileName == ".."_L1;
+}
+
void QDirListingPrivate::checkAndPushDirectory(QDirEntryInfo &entryInfo)
{
using F = QDirListing::IteratorFlag;
@@ -272,16 +368,20 @@ void QDirListingPrivate::checkAndPushDirectory(QDirEntryInfo &entryInfo)
return;
// Follow symlinks only when asked
- if (!iteratorFlags.testAnyFlags(F::FollowSymlinks) && entryInfo.isSymLink())
+ if (!iteratorFlags.testAnyFlags(F::FollowDirSymlinks) && entryInfo.isSymLink())
return;
// Never follow . and ..
- const QString &fileName = entryInfo.fileName();
- if ("."_L1 == fileName || ".."_L1 == fileName)
+ if (isDotOrDotDot(entryInfo.fileName()))
return;
// No hidden directories unless requested
- if (!filters.testAnyFlags(QDir::AllDirs | QDir::Hidden) && entryInfo.isHidden())
+ const bool includeHidden = [this]() {
+ if (useLegacyFilters)
+ return legacyDirFilters.testAnyFlags(QDir::AllDirs | QDir::Hidden);
+ return iteratorFlags.testAnyFlags(QDirListing::IteratorFlag::IncludeHidden);
+ }();
+ if (!includeHidden && entryInfo.isHidden())
return;
pushDirectory(entryInfo);
@@ -290,21 +390,21 @@ void QDirListingPrivate::checkAndPushDirectory(QDirEntryInfo &entryInfo)
/*!
\internal
- This functions returns \c true if the current entry matches the filters
- (i.e., the current entry will be returned as part of the directory
- iteration); otherwise, \c false is returned.
+ Works the same as matchesFilters() but for the old QDir::Filters.
*/
-bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
+bool QDirListingPrivate::matchesLegacyFilters(QDirEntryInfo &entryInfo) const
{
+ Q_ASSERT(useLegacyFilters);
+
const QString &fileName = entryInfo.fileName();
if (fileName.isEmpty())
return false;
+ auto &filters = legacyDirFilters;
+
// filter . and ..?
+ const bool dotOrDotDot = isDotOrDotDot(fileName);
const qsizetype fileNameSize = fileName.size();
- const bool dotOrDotDot = fileName[0] == u'.'
- && ((fileNameSize == 1)
- ||(fileNameSize == 2 && fileName[1] == u'.'));
if ((filters & QDir::NoDot) && dotOrDotDot && fileNameSize == 1)
return false;
if ((filters & QDir::NoDotDot) && dotOrDotDot && fileNameSize == 2)
@@ -313,11 +413,8 @@ bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
// name filter
#if QT_CONFIG(regularexpression)
// Pass all entries through name filters, except dirs if AllDirs is set
- if (!nameRegExps.isEmpty() && !(filters.testAnyFlags(QDir::AllDirs) && entryInfo.isDir())) {
- auto regexMatchesName = [&fileName](const auto &re) {
- return re.match(fileName).hasMatch();
- };
- if (std::none_of(nameRegExps.cbegin(), nameRegExps.cend(), regexMatchesName))
+ if (!(filters.testAnyFlags(QDir::AllDirs) && entryInfo.isDir())) {
+ if (!regexMatchesName(fileName))
return false;
}
#endif
@@ -371,6 +468,59 @@ bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
return true;
}
+/*!
+ \internal
+
+ This function returns \c true if the current entry matches the filters
+ (i.e., the current entry will be returned as part of the directory
+ iteration); otherwise, \c false is returned.
+*/
+bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
+{
+ using F = QDirListing::IteratorFlag;
+
+ const QString &fileName = entryInfo.fileName();
+ if (fileName.isEmpty())
+ return false;
+
+ if (isDotOrDotDot(fileName)) // All done, other checks below don't matter in this case
+ return iteratorFlags.testAnyFlags(F::IncludeDotAndDotDot);
+
+ // name filter
+#if QT_CONFIG(regularexpression)
+ if (!regexMatchesName(fileName))
+ return false;
+#endif // QT_CONFIG(regularexpression)
+
+ if (!iteratorFlags.testAnyFlag(F::IncludeHidden) && entryInfo.isHidden())
+ return false;
+
+ if (entryInfo.isSymLink()) {
+ // With ResolveSymlinks, we look at the type of the link's target,
+ // and exclude broken symlinks (where the target doesn't exist).
+ if (iteratorFlags.testAnyFlag(F::ResolveSymlinks)) {
+ if (!entryInfo.exists())
+ return false;
+ } else if (iteratorFlags.testAnyFlags(F::FilesOnly)
+ || iteratorFlags.testAnyFlags(F::DirsOnly)) {
+ return false; // symlink is not a file or dir
+ }
+ }
+
+ if (iteratorFlags.testAnyFlag(F::ExcludeSpecial)
+ && !entryInfo.isFile() && !entryInfo.isDir() && !entryInfo.isSymLink()) {
+ return false;
+ }
+
+ if (iteratorFlags.testAnyFlags(F::ExcludeDirs) && entryInfo.isDir())
+ return false;
+
+ if (iteratorFlags.testAnyFlags(F::ExcludeFiles) && entryInfo.isFile())
+ return false;
+
+ return true;
+}
+
bool QDirListingPrivate::hasIterators() const
{
if (engine)
@@ -384,98 +534,67 @@ bool QDirListingPrivate::hasIterators() const
}
/*!
- Constructs a QDirListing that can iterate over \a dir's entries, using
- \a dir's name filters and the QDir::Filters set in \a dir. You can pass
- options via \a flags to decide how the directory should be iterated.
+ Constructs a QDirListing that can iterate over \a path.
- By default, \a flags is NoIteratorFlags, which provides the same behavior
- as in QDir::entryList().
+ You can pass options via \a flags to control how the directory should
+ be iterated.
- The sorting in \a dir is ignored.
-
- \note To list symlinks that point to non existing files, QDir::System
- must be set in \a dir's QDir::Filters.
+ By default, \a flags is IteratorFlag::Default.
\sa IteratorFlags
*/
-QDirListing::QDirListing(const QDir &dir, IteratorFlags flags)
+QDirListing::QDirListing(const QString &path, IteratorFlags flags)
: d(new QDirListingPrivate)
{
- const QDirPrivate *other = dir.d_ptr.constData();
- d->initialEntryInfo.entry = other->dirEntry;
- d->nameFilters = other->nameFilters;
- d->filters = other->filters;
+ d->initialEntryInfo.entry = QFileSystemEntry(path);
d->iteratorFlags = flags;
- const bool resolveEngine = other->fileEngine ? true : false;
- d->init(resolveEngine);
+ d->init();
}
/*!
- Constructs a QDirListing that can iterate over \a path. Entries are
- filtered according to \a filters. You can pass options via \a flags to
- decide how the directory should be iterated.
-
- By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags,
- which provides the same behavior as in QDir::entryList().
+ Constructs a QDirListing that can iterate over \a path.
- \note To list symlinks that point to non existing files, QDir::System
- must be set in \a filters.
+ You can pass options via \a flags to control how the directory should
+ be iterated. By default, \a flags is IteratorFlag::Default.
- \sa IteratorFlags
-*/
-QDirListing::QDirListing(const QString &path, QDir::Filters filters, IteratorFlags flags)
- : d(new QDirListingPrivate)
-{
- d->initialEntryInfo.entry = QFileSystemEntry(path);
- d->filters = filters;
- d->iteratorFlags = flags;
- d->init();
-}
+ The listed entries will be filtered according to the file glob patterns
+ in \a nameFilters (see QDir::setNameFilters() for more details).
-/*!
- Constructs a QDirListing that can iterate over \a path. You can pass
- options via \a flags to decide how the directory should be iterated.
+ For example, the following iterator could be used to iterate over audio
+ files:
- By default, \a flags is NoIteratorFlags, which provides the same behavior
- as in QDir::entryList().
+ \snippet code/src_corelib_io_qdirlisting.cpp 2
- \sa IteratorFlags
+ \sa IteratorFlags, QDir::setNameFilters()
*/
-QDirListing::QDirListing(const QString &path, IteratorFlags flags)
+QDirListing::QDirListing(const QString &path, const QStringList &nameFilters, IteratorFlags flags)
: d(new QDirListingPrivate)
{
d->initialEntryInfo.entry = QFileSystemEntry(path);
- d->filters = QDir::NoFilter;
+ d->nameFilters = nameFilters;
d->iteratorFlags = flags;
d->init();
}
/*!
- Constructs a QDirListing that can iterate over \a path, using \a
- nameFilters and \a filters. You can pass options via \a flags to decide
- how the directory should be iterated.
-
- By default, \a flags is NoIteratorFlags, which provides the same behavior
- as QDir::entryList().
-
- For example, the following iterator could be used to iterate over audio
- files:
-
- \snippet code/src_corelib_io_qdirlisting.cpp 2
+ \internal
- \note To list symlinks that point to non existing files, QDir::System
- must be set in \a flags.
+ Only used by classes that still have to use QDir::Filters; for example,
+ QDir, such usage may be deprecated at some point.
- \sa IteratorFlags, QDir::setNameFilters()
+ \a qdirFilters is converted to QDir::Filters and \a qdirIteratorFlags is
+ converted to QDirIterator::IteratorFlags (qdirlisting.h can't include
+ qdir.h or qdiriterator.h) and used to control the filtering of the
+ dir entries.
*/
-QDirListing::QDirListing(const QString &path, const QStringList &nameFilters, QDir::Filters filters,
- IteratorFlags flags)
+QDirListing::QDirListing(const QString &path, const QStringList &nameFilters, uint qdirFilters,
+ uint qdirIteratorFlags)
: d(new QDirListingPrivate)
{
d->initialEntryInfo.entry = QFileSystemEntry(path);
d->nameFilters = nameFilters;
- d->filters = filters;
- d->iteratorFlags = flags;
+ d->setLegacyFilters(QDir::Filters::fromInt(qdirFilters),
+ QDirIterator::IteratorFlags::fromInt(qdirIteratorFlags));
d->init();
}
@@ -497,6 +616,7 @@ QDirListing::QDirListing(QDirListing &&other) = default;
*/
QDirListing &QDirListing::operator=(QDirListing &&other) = default;
+
/*!
Destroys the QDirListing.
*/
diff --git a/src/corelib/io/qdirlisting.h b/src/corelib/io/qdirlisting.h
index 7b6ca470c48..3d462277811 100644
--- a/src/corelib/io/qdirlisting.h
+++ b/src/corelib/io/qdirlisting.h
@@ -5,7 +5,11 @@
#ifndef QDILISTING_H
#define QDILISTING_H
-#include <QtCore/qdir.h>
+#include <QtCore/qfiledevice.h>
+#include <QtCore/qflags.h>
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/qtcoreexports.h>
+#include <QtCore/qdatetime.h>
#include <iterator>
#include <memory>
@@ -13,24 +17,32 @@
QT_BEGIN_NAMESPACE
class QDirListingPrivate;
+class QFileInfo;
+class QDir;
+class QTimeZone;
class Q_CORE_EXPORT QDirListing
{
public:
enum class IteratorFlag {
- NoFlag = 0x0,
- FollowSymlinks = 0x1,
- Recursive = 0x2
+ Default = 0x000000,
+ ExcludeFiles = 0x000004,
+ ExcludeDirs = 0x000008,
+ ExcludeSpecial = 0x000010,
+ ResolveSymlinks = 0x000020,
+ FilesOnly = ExcludeDirs | ExcludeSpecial,
+ DirsOnly = ExcludeFiles | ExcludeSpecial,
+ IncludeHidden = 0x000040,
+ IncludeDotAndDotDot = 0x000080,
+ CaseSensitive = 0x000100,
+ Recursive = 0x000400,
+ FollowDirSymlinks = 0x000800,
};
Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag)
- QDirListing(const QDir &dir, IteratorFlags flags = IteratorFlag::NoFlag);
- QDirListing(const QString &path, IteratorFlags flags = IteratorFlag::NoFlag);
- QDirListing(const QString &path, QDir::Filters filter,
- IteratorFlags flags = IteratorFlag::NoFlag);
- QDirListing(const QString &path, const QStringList &nameFilters,
- QDir::Filters filters = QDir::NoFilter,
- IteratorFlags flags = IteratorFlag::NoFlag);
+ explicit QDirListing(const QString &path, IteratorFlags flags = IteratorFlag::Default);
+ explicit QDirListing(const QString &path, const QStringList &nameFilters,
+ IteratorFlags flags = IteratorFlag::Default);
QDirListing(QDirListing &&);
QDirListing &operator=(QDirListing &&);
@@ -65,11 +77,15 @@ public:
QString absolutePath() const;
qint64 size() const;
- QDateTime birthTime(const QTimeZone &tz) const { return fileTime(QFile::FileBirthTime, tz); }
- QDateTime metadataChangeTime(const QTimeZone &tz) const { return fileTime(QFile::FileMetadataChangeTime, tz); }
- QDateTime lastModified(const QTimeZone &tz) const { return fileTime(QFile::FileModificationTime, tz); }
- QDateTime lastRead(const QTimeZone &tz) const { return fileTime(QFile::FileAccessTime, tz); }
- QDateTime fileTime(QFile::FileTime type, const QTimeZone &tz) const;
+ QDateTime birthTime(const QTimeZone &tz) const
+ { return fileTime(QFileDevice::FileBirthTime, tz); }
+ QDateTime metadataChangeTime(const QTimeZone &tz) const
+ { return fileTime(QFileDevice::FileMetadataChangeTime, tz); }
+ QDateTime lastModified(const QTimeZone &tz) const
+ { return fileTime(QFileDevice::FileModificationTime, tz); }
+ QDateTime lastRead(const QTimeZone &tz) const
+ { return fileTime(QFileDevice::FileAccessTime, tz); }
+ QDateTime fileTime(QFileDevice::FileTime type, const QTimeZone &tz) const;
};
class const_iterator
@@ -111,8 +127,19 @@ public:
private:
Q_DISABLE_COPY(QDirListing)
+ // Private constructor that is used in deprecated code paths.
+ // `uint` instead of QDir::Filters and QDirIterator::IteratorFlags
+ // because qdir.h can't be included here; qdiriterator.h can't included
+ // either, because it includes qdir.h
+ QDirListing(const QString &path, const QStringList &nameFilters, uint dirFilters,
+ uint qdirIteratorFlags = 0); // QDirIterator::NoIteratorFlags == 0x0
+
std::unique_ptr<QDirListingPrivate> d;
friend class QDir;
+ friend class QDirPrivate;
+ friend class QDirIteratorPrivate;
+ friend class QAbstractFileEngine;
+ friend class QFileInfoGatherer;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDirListing::IteratorFlags)
diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h
index c55d5c6d317..59577f0a2a0 100644
--- a/src/corelib/io/qfilesystemiterator_p.h
+++ b/src/corelib/io/qfilesystemiterator_p.h
@@ -38,6 +38,7 @@ class QFileSystemIterator
public:
QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters);
QFileSystemIterator(const QFileSystemEntry &entry);
+ QFileSystemIterator(const QFileSystemEntry &entry, QDirListing::IteratorFlags filters);
~QFileSystemIterator();
bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData);
diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp
index f06ff253442..774cf72b6f8 100644
--- a/src/corelib/io/qfilesystemiterator_unix.cpp
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -32,6 +32,10 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry)
}
}
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDirListing::IteratorFlags)
+ : QFileSystemIterator(entry)
+{}
+
QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters)
: QFileSystemIterator(entry)
{
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index d2e3904af6d..1be8854d81a 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -42,6 +42,13 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi
onlyDirs = true;
}
+QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry,
+ QDirListing::IteratorFlags flags)
+ : QFileSystemIterator(entry)
+{
+ onlyDirs = flags.testAnyFlags(QDirListing::IteratorFlag::DirsOnly);
+}
+
QFileSystemIterator::~QFileSystemIterator()
{
if (findFileHandle != INVALID_HANDLE_VALUE)
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 3d3af7468b3..2f9087bf6a3 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -798,6 +798,12 @@ QFSFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
return std::make_unique<QFSFileEngineIterator>(path, filters, filterNames);
}
+QAbstractFileEngine::IteratorUniquePtr
+QFSFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames)
+{
+ return std::make_unique<QFSFileEngineIterator>(path, filters, filterNames);
+}
#endif // QT_NO_FILESYSTEMITERATOR
/*!
diff --git a/src/corelib/io/qfsfileengine_iterator.cpp b/src/corelib/io/qfsfileengine_iterator.cpp
index fb0332f7f33..bdb2ecdafe7 100644
--- a/src/corelib/io/qfsfileengine_iterator.cpp
+++ b/src/corelib/io/qfsfileengine_iterator.cpp
@@ -16,6 +16,13 @@ QFSFileEngineIterator::QFSFileEngineIterator(const QString &path, QDir::Filters
{
}
+QFSFileEngineIterator::QFSFileEngineIterator(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames)
+ : QAbstractFileEngineIterator(path, filters, filterNames),
+ nativeIterator(new QFileSystemIterator(QFileSystemEntry(path), filters))
+{
+}
+
QFSFileEngineIterator::~QFSFileEngineIterator()
{
}
diff --git a/src/corelib/io/qfsfileengine_iterator_p.h b/src/corelib/io/qfsfileengine_iterator_p.h
index b91c5d99734..22400abb7db 100644
--- a/src/corelib/io/qfsfileengine_iterator_p.h
+++ b/src/corelib/io/qfsfileengine_iterator_p.h
@@ -27,6 +27,8 @@ class QFSFileEngineIterator : public QAbstractFileEngineIterator
{
public:
QFSFileEngineIterator(const QString &path, QDir::Filters filters, const QStringList &filterNames);
+ QFSFileEngineIterator(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames);
~QFSFileEngineIterator();
bool advance() override;
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index ba1ed0aadfb..5e77804606a 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -88,6 +88,8 @@ public:
#ifndef QT_NO_FILESYSTEMITERATOR
IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters,
const QStringList &filterNames) override;
+ IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames) override;
#endif
qint64 read(char *data, qint64 maxlen) override;
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 581e1e75ef1..83df4e1aec1 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -1589,6 +1589,13 @@ QResourceFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
return std::make_unique<QResourceFileEngineIterator>(path, filters, filterNames);
}
+QAbstractFileEngine::IteratorUniquePtr
+QResourceFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames)
+{
+ return std::make_unique<QResourceFileEngineIterator>(path, filters, filterNames);
+}
+
bool QResourceFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
{
Q_D(QResourceFileEngine);
diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp
index abb61d3b462..fdd5942fe47 100644
--- a/src/corelib/io/qresource_iterator.cpp
+++ b/src/corelib/io/qresource_iterator.cpp
@@ -15,6 +15,14 @@ QResourceFileEngineIterator::QResourceFileEngineIterator(const QString &path, QD
{
}
+QResourceFileEngineIterator::QResourceFileEngineIterator(const QString &path,
+ QDirListing::IteratorFlags filters,
+ const QStringList &filterNames)
+ : QAbstractFileEngineIterator(path, filters, filterNames),
+ index(-1)
+{
+}
+
QResourceFileEngineIterator::~QResourceFileEngineIterator()
{
}
diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h
index bcbbc46b51c..c4fd9f278db 100644
--- a/src/corelib/io/qresource_iterator_p.h
+++ b/src/corelib/io/qresource_iterator_p.h
@@ -26,6 +26,8 @@ class QResourceFileEngineIterator : public QAbstractFileEngineIterator
public:
QResourceFileEngineIterator(const QString &path, QDir::Filters filters,
const QStringList &filterNames);
+ QResourceFileEngineIterator(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames);
~QResourceFileEngineIterator();
bool advance() override;
diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h
index 37fddd7a415..00b6bddf3ec 100644
--- a/src/corelib/io/qresource_p.h
+++ b/src/corelib/io/qresource_p.h
@@ -51,6 +51,8 @@ public:
IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters,
const QStringList &filterNames) override;
+ IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames) override;
bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr) override;
bool supportsExtension(Extension extension) const override;
diff --git a/src/corelib/io/qstorageinfo_linux.cpp b/src/corelib/io/qstorageinfo_linux.cpp
index f2381e87e0a..4c7a0c70c84 100644
--- a/src/corelib/io/qstorageinfo_linux.cpp
+++ b/src/corelib/io/qstorageinfo_linux.cpp
@@ -349,9 +349,7 @@ static inline quint64 retrieveDeviceId(const QByteArray &device, quint64 deviceI
static QDirListing devicesByLabel()
{
static const char pathDiskByLabel[] = "/dev/disk/by-label";
- static constexpr auto LabelFileFilter =
- QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot;
-
+ static constexpr auto LabelFileFilter = QDirListing::IteratorFlag::IncludeHidden;
return QDirListing(QLatin1StringView(pathDiskByLabel), LabelFileFilter);
}
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 40f3b0121c2..ed7e398ea2c 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -309,7 +309,7 @@ inline void QFactoryLoaderPrivate::updateSinglePath(const QString &path)
#elif defined(Q_OS_ANDROID)
QStringList("libplugins_%1_*.so"_L1.arg(suffix)),
#endif
- QDir::Files);
+ QDirListing::IteratorFlag::FilesOnly);
for (const auto &dirEntry : plugins) {
const QString &fileName = dirEntry.fileName();
diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
index 45a6867524e..4975e2a8e6e 100644
--- a/src/corelib/time/qtimezoneprivate_tz.cpp
+++ b/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -11,6 +11,7 @@
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
#include <QtCore/QDirListing>
+#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QCache>
#include <QtCore/QMap>
@@ -113,14 +114,16 @@ static QTzTimeZoneHash loadTzTimeZones()
}
}
- const QString path = tzif.fileName();
+ QString path = tzif.fileName();
const qsizetype cut = path.lastIndexOf(u'/');
Q_ASSERT(cut > 0);
- const QDir zoneDir = QDir(path.first(cut));
- for (const auto &info : QDirListing(zoneDir, QDirListing::IteratorFlag::Recursive)) {
+ path.truncate(cut + 1);
+ const qsizetype prefixLen = path.size();
+ for (const auto &info : QDirListing(path, QDirListing::IteratorFlag::Recursive)) {
if (!(info.isFile() || info.isSymLink()))
continue;
- const QString name = zoneDir.relativeFilePath(info.filePath());
+ const QString infoAbsolutePath = info.absoluteFilePath();
+ const QString name = infoAbsolutePath.sliced(prefixLen);
// Two sub-directories containing (more or less) copies of the zoneinfo tree.
if (info.isDir() ? name == "posix"_L1 || name == "right"_L1
: name.startsWith("posix/"_L1) || name.startsWith("right/"_L1)) {
@@ -130,7 +133,7 @@ static QTzTimeZoneHash loadTzTimeZones()
// isTzFile() check; in practice current (2023) zoneinfo/ contains only
// actual zone files and matches to that filter.
const QByteArray id = QFile::encodeName(name);
- if (!zonesHash.contains(id) && isTzFile(zoneDir.absoluteFilePath(name)))
+ if (!zonesHash.contains(id) && isTzFile(infoAbsolutePath))
zonesHash.insert(id, QTzTimeZone());
}
return zonesHash;
diff --git a/src/gui/itemmodels/qfileinfogatherer.cpp b/src/gui/itemmodels/qfileinfogatherer.cpp
index 41fb0a0db5e..a0192c99828 100644
--- a/src/gui/itemmodels/qfileinfogatherer.cpp
+++ b/src/gui/itemmodels/qfileinfogatherer.cpp
@@ -419,8 +419,10 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
QStringList allFiles;
if (files.isEmpty()) {
+ // Use QDirListing::IteratorFlags when QFileSystemModel is
+ // changed to use them too
constexpr auto dirFilters = QDir::AllEntries | QDir::System | QDir::Hidden;
- for (const auto &dirEntry : QDirListing(path, dirFilters)) {
+ for (const auto &dirEntry : QDirListing(path, {}, dirFilters.toInt())) {
if (isInterruptionRequested())
break;
fileInfo = dirEntry.fileInfo();
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index b39924025e8..69e35cea279 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -473,8 +473,6 @@ qint64 QNetworkDiskCache::expire()
// close file handle to prevent "in use" error when QFile::remove() is called
d->lastItem.reset();
- const QDir::Filters filters = QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot;
-
struct CacheItem
{
std::chrono::milliseconds msecs;
@@ -484,7 +482,7 @@ qint64 QNetworkDiskCache::expire()
std::vector<CacheItem> cacheItems;
qint64 totalSize = 0;
using F = QDirListing::IteratorFlag;
- for (const auto &dirEntry : QDirListing(cacheDirectory(), filters, F::Recursive)) {
+ for (const auto &dirEntry : QDirListing(cacheDirectory(), F::FilesOnly | F::Recursive)) {
if (!dirEntry.fileName().endsWith(CACHE_POSTFIX))
continue;
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 9878c603b6c..a424bfd1b94 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -681,8 +681,8 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
#endif
using F = QDirListing::IteratorFlag;
- constexpr auto iterFlags = F::FollowSymlinks | F::Recursive;
- for (const auto &dirEntry : QDirListing(pathPrefixString, QDir::Files, iterFlags)) {
+ constexpr auto iterFlags = F::FollowDirSymlinks | F::Recursive | F::FilesOnly;
+ for (const auto &dirEntry : QDirListing(pathPrefixString, iterFlags)) {
QString filePath = dirEntry.filePath();
if (startIndex > 0)
filePath.remove(0, startIndex);
diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp
index f4afb3789a0..b66bbf1e6eb 100644
--- a/src/plugins/platforms/android/androidcontentfileengine.cpp
+++ b/src/plugins/platforms/android/androidcontentfileengine.cpp
@@ -245,7 +245,7 @@ QString AndroidContentFileEngine::fileName(FileName f) const
}
QAbstractFileEngine::IteratorUniquePtr
-AndroidContentFileEngine::beginEntryList(const QString &path, QDir::Filters filters,
+AndroidContentFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
const QStringList &filterNames)
{
return std::make_unique<AndroidContentFileEngineIterator>(path, filters, filterNames);
@@ -265,7 +265,7 @@ AndroidContentFileEngineHandler::create(const QString &fileName) const
}
AndroidContentFileEngineIterator::AndroidContentFileEngineIterator(
- const QString &path, QDir::Filters filters, const QStringList &filterNames)
+ const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames)
: QAbstractFileEngineIterator(path, filters, filterNames)
{
}
diff --git a/src/plugins/platforms/android/androidcontentfileengine.h b/src/plugins/platforms/android/androidcontentfileengine.h
index a5dd1b30f33..a93ea3373a0 100644
--- a/src/plugins/platforms/android/androidcontentfileengine.h
+++ b/src/plugins/platforms/android/androidcontentfileengine.h
@@ -30,7 +30,7 @@ public:
QDateTime fileTime(QFile::FileTime time) const override;
FileFlags fileFlags(FileFlags type = FileInfoAll) const override;
QString fileName(FileName file = DefaultName) const override;
- IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters,
+ IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
const QStringList &filterNames) override;
private:
@@ -53,7 +53,7 @@ public:
class AndroidContentFileEngineIterator : public QAbstractFileEngineIterator
{
public:
- AndroidContentFileEngineIterator(const QString &path, QDir::Filters filters,
+ AndroidContentFileEngineIterator(const QString &path, QDirListing::IteratorFlags filters,
const QStringList &filterNames);
~AndroidContentFileEngineIterator();
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index 4ea6536cef2..1c7364cd229 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -164,7 +164,7 @@ Q_CONSTINIT QMutex FolderIterator::m_assetsCacheMutex;
class AndroidAbstractFileEngineIterator: public QAbstractFileEngineIterator
{
public:
- AndroidAbstractFileEngineIterator(QDir::Filters filters,
+ AndroidAbstractFileEngineIterator(QDirListing::IteratorFlags filters,
const QStringList &nameFilters,
const QString &path)
: QAbstractFileEngineIterator(path, filters, nameFilters)
@@ -351,8 +351,8 @@ public:
m_assetsInfoCache.insert(m_fileName, newAssetInfoPtr);
}
- IteratorUniquePtr
- beginEntryList(const QString &, QDir::Filters filters, const QStringList &filterNames) override
+ IteratorUniquePtr beginEntryList(const QString &, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames) override
{
// AndroidAbstractFileEngineIterator use `m_fileName` as the path
if (m_assetInfo && m_assetInfo->type == AssetItem::Type::Folder)
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h
index 0ad54a9e114..62d50db7662 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h
@@ -29,7 +29,7 @@ public:
void setFileName(const QString &file) override;
#ifndef QT_NO_FILESYSTEMITERATOR
- IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters,
+ IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
const QStringList &filterNames) override;
#endif
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
index f7e112ab81f..61780718a3f 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
@@ -258,7 +258,7 @@ public:
QIOSAssetEnumerator *m_enumerator;
QIOSFileEngineIteratorAssetsLibrary(
- const QString &path, QDir::Filters filters, const QStringList &nameFilters)
+ const QString &path, QDirListing::IteratorFlags filters, const QStringList &nameFilters)
: QAbstractFileEngineIterator(path, filters, nameFilters)
, m_enumerator(new QIOSAssetEnumerator([[[ALAssetsLibrary alloc] init] autorelease], ALAssetsGroupAll))
{
@@ -440,7 +440,7 @@ void QIOSFileEngineAssetsLibrary::setFileName(const QString &file)
QAbstractFileEngine::IteratorUniquePtr
QIOSFileEngineAssetsLibrary::beginEntryList(
- const QString &path, QDir::Filters filters, const QStringList &filterNames)
+ const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames)
{
return std::make_unique<QIOSFileEngineIteratorAssetsLibrary>(path, filters, filterNames);
}
diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
index d73515724bb..f9bebaa8121 100644
--- a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
+++ b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
@@ -207,7 +207,8 @@ void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const
const QStringList symLinkFilter{
u"[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"_s};
for (const auto &dir : dirs) {
- QDirListing dirList(QString::fromLatin1(dir), symLinkFilter, QDir::Files);
+ QDirListing dirList(QString::fromLatin1(dir), symLinkFilter,
+ QDirListing::IteratorFlag::FilesOnly);
if (dirList.cbegin() != dirList.cend()) { // Not empty
QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true);
break;
@@ -390,11 +391,9 @@ QList<QSslCertificate> systemCaCertificates()
QStringLiteral("/etc/pki/tls/certs/ca-bundle.crt"), // Fedora, Mandriva
QStringLiteral("/usr/local/share/certs/ca-root-nss.crt") // FreeBSD's ca_root_nss
};
- QDir currentDir;
- currentDir.setNameFilters(QStringList{QStringLiteral("*.pem"), QStringLiteral("*.crt")});
+ static const QStringList nameFilters = {u"*.pem"_s, u"*.crt"_s};
for (const auto &directory : directories) {
- currentDir.setPath(QLatin1StringView(directory));
- for (const auto &dirEntry : QDirListing(currentDir)) {
+ for (const auto &dirEntry : QDirListing(directory, nameFilters)) {
// use canonical path here to not load the same certificate twice if symlinked
certFiles.insert(dirEntry.canonicalFilePath());
}
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index f9a645aadb7..f4c96edc55d 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -2870,7 +2870,7 @@ void checkAndWarnGradleLongPaths(const QString &outputDirectory)
QStringList longFileNames;
using F = QDirListing::IteratorFlag;
for (const auto &dirEntry : QDirListing(outputDirectory, QStringList(u"*.java"_s),
- QDir::Files, F::Recursive)) {
+ F::FilesOnly | F::Recursive)) {
if (dirEntry.size() >= MAX_PATH)
longFileNames.append(dirEntry.filePath());
}
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 06f9ae1015c..563672243b3 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -688,13 +688,13 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
absFileName.prepend(currentPath);
QFileInfo file(absFileName);
if (file.isDir()) {
- QDir dir(file.filePath());
if (!alias.endsWith(slash))
alias += slash;
QStringList filePaths;
using F = QDirListing::IteratorFlag;
- for (const auto &entry : QDirListing(dir, F::FollowSymlinks | F::Recursive)) {
+ constexpr auto flags = F::FollowDirSymlinks | F::Recursive;
+ for (const auto &entry : QDirListing(file.filePath(), flags)) {
const QString &fileName = entry.fileName();
if (fileName == "."_L1 || fileName == ".."_L1)
continue;
diff --git a/src/tools/windeployqt/qtmoduleinfo.cpp b/src/tools/windeployqt/qtmoduleinfo.cpp
index b928a644784..e03da339401 100644
--- a/src/tools/windeployqt/qtmoduleinfo.cpp
+++ b/src/tools/windeployqt/qtmoduleinfo.cpp
@@ -133,8 +133,9 @@ bool QtModuleInfoStore::populate(const QString &modulesDir, const QString &trans
}
}
+ using F = QDirListing::IteratorFlag;
// Read modules, and assign a bit as ID.
- for (const auto &dirEntry : QDirListing(modulesDir, {u"*.json"_s}, QDir::Files)) {
+ for (const auto &dirEntry : QDirListing(modulesDir, {u"*.json"_s}, F::FilesOnly)) {
QtModule module = moduleFromJsonFile(dirEntry.filePath(), errorString);
if (!errorString->isEmpty())
return false;
diff --git a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
index cf00c1525c5..3a54e74981c 100644
--- a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
+++ b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
@@ -432,7 +432,7 @@ public:
class Iterator : public QAbstractFileEngineIterator
{
public:
- Iterator(const QString &path, QDir::Filters filters, const QStringList &filterNames)
+ Iterator(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames)
: QAbstractFileEngineIterator(path, filters, filterNames)
{
names.append("foo");
@@ -463,8 +463,8 @@ public:
{
}
- IteratorUniquePtr
- beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames) override
+ IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
+ const QStringList &filterNames) override
{
return std::make_unique<Iterator>(path, filters, filterNames);
}
diff --git a/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp b/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp
index e2ac1858dae..5b31d335f98 100644
--- a/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp
+++ b/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp
@@ -26,7 +26,6 @@
using namespace Qt::StringLiterals;
Q_DECLARE_METATYPE(QDirListing::IteratorFlags)
-Q_DECLARE_METATYPE(QDir::Filters)
using ItFlag = QDirListing::IteratorFlag;
@@ -187,183 +186,259 @@ void tst_QDirListing::iterateRelativeDirectory_data()
{
QTest::addColumn<QString>("dirName"); // relative from current path or abs
QTest::addColumn<QDirListing::IteratorFlags>("flags");
- QTest::addColumn<QDir::Filters>("filters");
QTest::addColumn<QStringList>("nameFilters");
QTest::addColumn<QStringList>("entries");
- QTest::newRow("no flags")
- << QString("entrylist") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::NoFilter) << QStringList("*")
- << QString(
- "entrylist/.,"
- "entrylist/..,"
- "entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
-#endif
- "entrylist/directory,"
-#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
- "entrylist/linktodirectory.lnk,"
-#endif
- "entrylist/writable").split(',');
-
- QTest::newRow("NoDot")
- << QString("entrylist") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::AllEntries | QDir::NoDot) << QStringList("*")
- << QString(
- "entrylist/..,"
- "entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
-#endif
- "entrylist/directory,"
-#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
- "entrylist/linktodirectory.lnk,"
-#endif
- "entrylist/writable").split(',');
-
- QTest::newRow("NoDotDot")
- << QString("entrylist") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::AllEntries | QDir::NoDotDot) << QStringList("*")
- << QString(
- "entrylist/.,"
- "entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
-#endif
- "entrylist/directory,"
-#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
- "entrylist/linktodirectory.lnk,"
+ const QStringList allSymlinks = {
+#if !defined(Q_NO_SYMLINKS)
+ "entrylist/linktofile.lnk"_L1,
+ "entrylist/brokenlink.lnk"_L1,
+# if !defined(Q_NO_SYMLINKS_TO_DIRS)
+ "entrylist/linktodirectory.lnk"_L1,
+# endif
#endif
- "entrylist/writable").split(',');
+ };
- QTest::newRow("NoDotAndDotDot")
- << QString("entrylist") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::AllEntries | QDir::NoDotAndDotDot) << QStringList("*")
- << QString(
- "entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
-#endif
- "entrylist/directory,"
-#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
- "entrylist/linktodirectory.lnk,"
-#endif
- "entrylist/writable").split(',');
-
- QTest::newRow("QDir::Subdirectories | QDir::FollowSymlinks")
- << QString("entrylist") << QDirListing::IteratorFlags(ItFlag::Recursive | ItFlag::FollowSymlinks)
- << QDir::Filters(QDir::NoFilter) << QStringList("*")
- << QString(
- "entrylist/.,"
- "entrylist/..,"
- "entrylist/directory/.,"
- "entrylist/directory/..,"
- "entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
-#endif
- "entrylist/directory,"
- "entrylist/directory/dummy,"
-#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
- "entrylist/linktodirectory.lnk,"
+ const QStringList nonBrokenSymlinks = {
+#if !defined(Q_NO_SYMLINKS)
+ "entrylist/linktofile.lnk"_L1,
+# if !defined(Q_NO_SYMLINKS_TO_DIRS)
+ "entrylist/linktodirectory.lnk"_L1,
+# endif
#endif
- "entrylist/writable").split(',');
+ };
- QTest::newRow("QDir::Subdirectories / QDir::Files")
- << QString("entrylist") << QDirListing::IteratorFlags(ItFlag::Recursive)
- << QDir::Filters(QDir::Files) << QStringList("*")
- << QString("entrylist/directory/dummy,"
- "entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
+ using F = QDirListing::IteratorFlag;
+ QTest::newRow("Default_Flag")
+ << QString("entrylist") << QDirListing::IteratorFlags{F::Default}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/writable"_L1,
+ } + allSymlinks;
+
+ QTest::newRow("IncludeDotAndDotDot")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags{F::IncludeDotAndDotDot}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/."_L1,
+ "entrylist/.."_L1,
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/writable"_L1,
+ } + allSymlinks;
+
+ QTest::newRow("Recursive-IncludeDotAndDotDot")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags{F::Recursive | F::IncludeDotAndDotDot}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/."_L1,
+ "entrylist/.."_L1,
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/directory/."_L1,
+ "entrylist/directory/.."_L1,
+ "entrylist/directory/dummy"_L1,
+ "entrylist/writable"_L1,
+ } + allSymlinks;
+
+ QTest::newRow("Recursive")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags(F::Recursive)
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/directory/dummy"_L1,
+ "entrylist/writable"_L1,
+ } + allSymlinks;
+
+ QTest::newRow("ResolveSymlinks")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags{F::ResolveSymlinks}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/writable"_L1,
+ } + nonBrokenSymlinks;
+
+ QTest::newRow("Recursive-ResolveSymlinks")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags(F::Recursive | F::ResolveSymlinks)
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/directory/dummy"_L1,
+ "entrylist/writable"_L1,
+ } + nonBrokenSymlinks;
+
+ QTest::newRow("Recursive-FilesOnly")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags(F::Recursive | F::FilesOnly)
+ << QStringList("*")
+ << QStringList{
+ "entrylist/directory/dummy"_L1,
+ "entrylist/file"_L1,
+ "entrylist/writable"_L1,
+ };
+
+ QTest::newRow("Recursive-FilesOnly-ResolveSymlinks")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags(F::Recursive | F::FilesOnly | F::ResolveSymlinks)
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory/dummy"_L1,
+ "entrylist/writable"_L1,
+#if !defined(Q_NO_SYMLINKS)
+ "entrylist/linktofile.lnk"_L1,
#endif
- "entrylist/writable").split(',');
-
- QTest::newRow("QDir::Subdirectories | QDir::FollowSymlinks / QDir::Files")
- << QString("entrylist") << QDirListing::IteratorFlags(ItFlag::Recursive | QDirListing::IteratorFlag::FollowSymlinks)
- << QDir::Filters(QDir::Files) << QStringList("*")
- << QString("entrylist/file,"
-#ifndef Q_NO_SYMLINKS
- "entrylist/linktofile.lnk,"
+ };
+
+ QTest::newRow("Recursive-DirsOnly")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags(F::Recursive | F::DirsOnly)
+ << QStringList("*")
+ << QStringList{ "entrylist/directory"_L1, };
+
+ QTest::newRow("Recursive-DirsOnly-ResolveSymlinks")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags(F::Recursive | F::DirsOnly | F::ResolveSymlinks)
+ << QStringList("*")
+ << QStringList{
+ "entrylist/directory"_L1,
+#if !defined(Q_NO_SYMLINKS)
+ "entrylist/linktodirectory.lnk"_L1,
#endif
- "entrylist/directory/dummy,"
- "entrylist/writable").split(',');
-
- QTest::newRow("empty, default")
- << QString("empty") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::NoFilter) << QStringList("*")
- << QString("empty/.,empty/..").split(',');
-
- QTest::newRow("empty, QDir::NoDotAndDotDot")
+ };
+
+ QTest::newRow("FollowDirSymlinks")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags{F::FollowDirSymlinks}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/writable"_L1,
+ } + allSymlinks;
+
+ QTest::newRow("FollowDirSymlinks-Recursive")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags{F::FollowDirSymlinks | F::Recursive}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/directory/dummy"_L1,
+ "entrylist/writable"_L1,
+ } + allSymlinks;
+
+ QTest::newRow("FollowDirSymlinks-Recursive-ResolveSymlinks")
+ << QString("entrylist")
+ << QDirListing::IteratorFlags{F::FollowDirSymlinks | F::Recursive | F::ResolveSymlinks}
+ << QStringList("*")
+ << QStringList{
+ "entrylist/file"_L1,
+ "entrylist/directory"_L1,
+ "entrylist/directory/dummy"_L1,
+ "entrylist/writable"_L1,
+ } + nonBrokenSymlinks;
+
+ QTest::newRow("empty-dir-IncludeDotAndDotDot")
+ << QString("empty")
+ << QDirListing::IteratorFlags{F::IncludeDotAndDotDot}
+ << QStringList("*")
+ << QStringList{
+ "empty/."_L1,
+ "empty/.."_L1
+ };
+
+ QTest::newRow("empty-dir-Default-Flag")
<< QString("empty") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::NoDotAndDotDot) << QStringList("*")
+ << QStringList("*")
<< QStringList();
+
+ QTest::newRow("Recursive-nameFilter")
+ << u"entrylist"_s
+ << QDirListing::IteratorFlags(F::Recursive)
+ << QStringList{"dummy"_L1}
+ << QStringList{"entrylist/directory/dummy"_L1};
}
void tst_QDirListing::iterateRelativeDirectory()
{
QFETCH(QString, dirName);
QFETCH(QDirListing::IteratorFlags, flags);
- QFETCH(QDir::Filters, filters);
QFETCH(QStringList, nameFilters);
QFETCH(const QStringList, entries);
+ // If canonicalFilePath is empty (e.g. for broken symlinks), use absoluteFilePath()
QStringList list;
- for (const auto &dirEntry : QDirListing(dirName, nameFilters, filters, flags)) {
- // Using canonical file paths for final comparison
- list << dirEntry.fileInfo().canonicalFilePath();
+ for (const auto &dirEntry : QDirListing(dirName, nameFilters, flags)) {
+ QString filePath = dirEntry.canonicalFilePath();
+ list.emplace_back(!filePath.isEmpty()? filePath : dirEntry.absoluteFilePath());
}
// The order of items returned by QDirListing is not guaranteed.
list.sort();
QStringList sortedEntries;
- for (const QString &item : entries)
- sortedEntries.append(QFileInfo(item).canonicalFilePath());
- sortedEntries.sort();
-
- if (sortedEntries != list) {
- qDebug() << "ACTUAL: " << list;
- qDebug() << "EXPECTED:" << sortedEntries;
+ for (const QString &item : entries) {
+ QFileInfo fi(item);
+ QString filePath = fi.canonicalFilePath();
+ sortedEntries.emplace_back(!filePath.isEmpty()? filePath : fi.absoluteFilePath());
}
+ sortedEntries.sort();
- QCOMPARE(list, sortedEntries);
+ QCOMPARE_EQ(list, sortedEntries);
}
void tst_QDirListing::iterateResource_data()
{
QTest::addColumn<QString>("dirName"); // relative from current path or abs
QTest::addColumn<QDirListing::IteratorFlags>("flags");
- QTest::addColumn<QDir::Filters>("filters");
QTest::addColumn<QStringList>("nameFilters");
QTest::addColumn<QStringList>("entries");
- QTest::newRow("invalid") << QString::fromLatin1(":/testdata/burpaburpa") << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
- << QStringList();
+ QTest::newRow("invalid") << QString::fromLatin1(":/testdata/burpaburpa")
+ << QDirListing::IteratorFlags{ItFlag::Default}
+ << QStringList{u"*"_s} << QStringList();
+
QTest::newRow("qrc:/testdata") << u":/testdata/"_s << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
- << QString::fromLatin1(":/testdata/entrylist").split(QLatin1String(","));
- QTest::newRow("qrc:/testdata/entrylist") << u":/testdata/entrylist"_s << QDirListing::IteratorFlags{}
- << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
- << QString::fromLatin1(":/testdata/entrylist/directory,:/testdata/entrylist/file").split(QLatin1String(","));
- QTest::newRow("qrc:/testdata recursive") << u":/testdata"_s
- << QDirListing::IteratorFlags(ItFlag::Recursive)
- << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
- << QString::fromLatin1(":/testdata/entrylist,:/testdata/entrylist/directory,:/testdata/entrylist/directory/dummy,:/testdata/entrylist/file").split(QLatin1String(","));
+ << QStringList(QLatin1String("*"))
+ << QStringList{u":/testdata/entrylist"_s};
+
+ QTest::newRow("qrc:/testdata/entrylist")
+ << u":/testdata/entrylist"_s
+ << QDirListing::IteratorFlags{}
+ << QStringList(QLatin1String("*"))
+ << QStringList{u":/testdata/entrylist/directory"_s,
+ u":/testdata/entrylist/file"_s};
+
+ QTest::newRow("qrc:/testdata recursive")
+ << u":/testdata"_s
+ << QDirListing::IteratorFlags(ItFlag::Recursive)
+ << QStringList(QLatin1String("*"))
+ << QStringList{u":/testdata/entrylist"_s,
+ u":/testdata/entrylist/directory"_s,
+ u":/testdata/entrylist/directory/dummy"_s,
+ u":/testdata/entrylist/file"_s};
}
void tst_QDirListing::iterateResource()
{
QFETCH(QString, dirName);
QFETCH(QDirListing::IteratorFlags, flags);
- QFETCH(QDir::Filters, filters);
QFETCH(QStringList, nameFilters);
QFETCH(QStringList, entries);
QStringList list;
- for (const auto &dirEntry : QDirListing(dirName, nameFilters, filters, flags)) {
+ for (const auto &dirEntry : QDirListing(dirName, nameFilters, flags)) {
QString dir = dirEntry.fileInfo().filePath();
if (!dir.startsWith(":/qt-project.org"))
list.emplace_back(std::move(dir));
@@ -404,7 +479,7 @@ void tst_QDirListing::stopLinkLoop()
createLink("..", "entrylist/directory/entrylist4.lnk");
#endif
- constexpr auto flags = ItFlag::Recursive | ItFlag::FollowSymlinks;
+ constexpr auto flags = ItFlag::Recursive | ItFlag::FollowDirSymlinks;
QDirListing dirIter(u"entrylist"_s, flags);
QStringList list;
int max = 200;
@@ -424,7 +499,8 @@ public:
: QFSFileEngine(fileName)
{ }
- IteratorUniquePtr beginEntryList(const QString &, QDir::Filters, const QStringList &) override
+ IteratorUniquePtr beginEntryList(const QString &, QDirListing::IteratorFlags,
+ const QStringList &) override
{ return nullptr; }
};
@@ -468,7 +544,6 @@ void tst_QDirListing::testQFsFileEngineIterator()
{
QFETCH(QString, dirName);
QFETCH(QStringList, nameFilters);
- QFETCH(QDir::Filters, filters);
QFETCH(QDirListing::IteratorFlags, flags);
if (dirName == u"empty")
@@ -476,7 +551,7 @@ void tst_QDirListing::testQFsFileEngineIterator()
CustomEngineHandler handler;
bool isEmpty = true;
- for (const auto &dirEntry : QDirListing(u"entrylist"_s, nameFilters, filters, flags)) {
+ for (const auto &dirEntry : QDirListing(u"entrylist"_s, nameFilters, flags)) {
if (dirEntry.filePath().contains(u"entrylist"))
isEmpty = false; // At least one entry in `entrylist` dir
}
@@ -486,7 +561,7 @@ void tst_QDirListing::testQFsFileEngineIterator()
void tst_QDirListing::absoluteFilePathsFromRelativeIteratorPath()
{
- for (const auto &dirEntry : QDirListing(u"entrylist/"_s, QDir::NoDotAndDotDot))
+ for (const auto &dirEntry : QDirListing(u"entrylist/"_s, QDirListing::IteratorFlag::Recursive))
QVERIFY(dirEntry.absoluteFilePath().contains("entrylist"));
}
@@ -497,12 +572,11 @@ void tst_QDirListing::recurseWithFilters() const
expectedEntries.insert(QString::fromLatin1("recursiveDirs/dir1/textFileB.txt"));
expectedEntries.insert(QString::fromLatin1("recursiveDirs/textFileA.txt"));
- for (const auto &dirEntry : QDirListing(u"recursiveDirs/"_s, QStringList{u"*.txt"_s},
- QDir::Files, ItFlag::Recursive)) {
+ constexpr auto flags = ItFlag::ExcludeDirs | ItFlag::ExcludeSpecial| ItFlag::Recursive;
+ for (const auto &dirEntry : QDirListing(u"recursiveDirs/"_s, QStringList{u"*.txt"_s}, flags))
actualEntries.insert(dirEntry.filePath());
- }
- QCOMPARE(actualEntries, expectedEntries);
+ QCOMPARE_EQ(actualEntries, expectedEntries);
}
void tst_QDirListing::longPath()
@@ -518,7 +592,8 @@ void tst_QDirListing::longPath()
dirName.append('x');
}
- QDirListing dirList(dir.absolutePath(), QDir::NoDotAndDotDot|QDir::Dirs, ItFlag::Recursive);
+ constexpr auto flags = ItFlag::ExcludeFiles | ItFlag::ExcludeSpecial| ItFlag::Recursive;
+ QDirListing dirList(dir.absolutePath(), flags);
qsizetype m = 0;
for (auto it = dirList.begin(); it != dirList.end(); ++it)
++m;
@@ -562,8 +637,7 @@ void tst_QDirListing::uncPaths_data()
void tst_QDirListing::uncPaths()
{
QFETCH(QString, dirName);
- constexpr auto dirFilters = QDir::AllEntries | QDir::NoDotAndDotDot;
- for (const auto &dirEntry : QDirListing(dirName, dirFilters, ItFlag::Recursive)) {
+ for (const auto &dirEntry : QDirListing(dirName, ItFlag::Recursive)) {
const QString &filePath = dirEntry.filePath();
QCOMPARE(filePath, QDir::cleanPath(filePath));
}
@@ -588,15 +662,13 @@ void tst_QDirListing::hiddenFiles()
};
expected.sort();
- constexpr auto filters = QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot;
+ constexpr auto flags = ItFlag::ExcludeDirs | ItFlag::IncludeHidden | ItFlag::Recursive;
QStringList list;
list.reserve(expected.size());
- for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, filters,
- ItFlag::Recursive)) {
+ for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, flags)) {
QVERIFY(dirEntry.isFile());
list.emplace_back(dirEntry.filePath());
}
-
list.sort();
QCOMPARE_EQ(list, expected);
@@ -614,11 +686,10 @@ void tst_QDirListing::hiddenDirs()
};
expected.sort();
- constexpr auto filters = QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot;
+ constexpr auto flags = ItFlag::ExcludeFiles | ItFlag::IncludeHidden | ItFlag::Recursive;
QStringList list;
list.reserve(expected.size());
- for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, filters,
- ItFlag::Recursive)) {
+ for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, flags)) {
QVERIFY(dirEntry.isDir());
list.emplace_back(dirEntry.filePath());
}
@@ -631,7 +702,7 @@ void tst_QDirListing::hiddenDirs()
void tst_QDirListing::withStdAlgorithms()
{
- QDirListing dirList(u"entrylist"_s, QDir::AllEntries | QDir::NoDotAndDotDot, ItFlag::Recursive);
+ QDirListing dirList(u"entrylist"_s, ItFlag::Recursive);
std::for_each(dirList.cbegin(), dirList.cend(), [](const auto &dirEntry) {
QVERIFY(dirEntry.absoluteFilePath().contains("entrylist"));
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 87736fdfc5a..2748df5e7ba 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2327,7 +2327,8 @@ public:
MyEngine(int n) { number = n; }
qint64 size() const override { return 123 + number; }
- QStringList entryList(QDir::Filters, const QStringList &) const override { return QStringList(); }
+ QStringList entryList(QDirListing::IteratorFlags, const QStringList &) const override
+ { return QStringList(); }
QString fileName(FileName) const override { return name; }
private:
diff --git a/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp
index 66448bf838f..aeb5d9a0df2 100644
--- a/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp
+++ b/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp
@@ -206,12 +206,14 @@ void tst_QDirIterator::dirlisting()
{
QFETCH(QByteArray, dirpath);
+ using F = QDirListing::IteratorFlag;
+
int count = 0;
QBENCHMARK {
int c = 0;
- QDirListing dir(dirpath, dirFilters, QDirListing::IteratorFlag::Recursive);
+ QDirListing dir(dirpath, F::Recursive | F::IncludeHidden);
for (const auto &dirEntry : dir) {
const auto path = dirEntry.filePath();