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.

Fixes: QTBUG-125504
Task-number: QTBUG-125859
Change-Id: Ide4ff8279f554029ac30d0579b0e8373ed4337f7
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit e583c3d5163a5512abac85e32359652e28a053f7)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ahmad Samir 2024-06-21 00:59:45 +03:00 committed by Qt Cherry-pick Bot
parent 0cbf579ca1
commit 7c663d04d7
40 changed files with 632 additions and 347 deletions

View File

@ -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();

View File

@ -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());

View File

@ -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]
}

View File

@ -590,6 +590,21 @@ bool QAbstractFileEngine::isRelativePath() const
\sa setFileName()
*/
QStringList QAbstractFileEngine::entryList(QDir::Filters 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.toInt()))
ret.emplace_back(dirEntry.fileName());
return ret;
#endif
}
QStringList QAbstractFileEngine::entryList(QDirListing::IteratorFlags filters,
const QStringList &filterNames) const
{
QStringList ret;
#ifdef QT_BOOTSTRAPPED
@ -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.

View File

@ -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;
};

View File

@ -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

View File

@ -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(); }

View File

@ -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))
{
}

View File

@ -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.
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 NoFlag The default value, representing no flags. The iterator
will return entries for the assigned path.
\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 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 ExcludeFiles
Don't list regular files. When combined with ResolveSymlinks, symbolic
links to regular files will be excluded too.
\value Recursive List entries inside all subdirectories as well.
\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,60 +534,12 @@ 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.
\sa IteratorFlags
*/
QDirListing::QDirListing(const QDir &dir, 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->iteratorFlags = flags;
const bool resolveEngine = other->fileEngine ? true : false;
d->init(resolveEngine);
}
/*!
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().
\note To list symlinks that point to non existing files, QDir::System
must be set in \a filters.
\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();
}
/*!
Constructs a QDirListing that can iterate over \a path. 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 in QDir::entryList().
By default, \a flags is IteratorFlag::Default.
\sa IteratorFlags
*/
@ -445,40 +547,57 @@ QDirListing::QDirListing(const QString &path, IteratorFlags flags)
: d(new QDirListingPrivate)
{
d->initialEntryInfo.entry = QFileSystemEntry(path);
d->filters = QDir::NoFilter;
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.
Constructs a QDirListing that can iterate over \a path.
By default, \a flags is NoIteratorFlags, which provides the same behavior
as QDir::entryList().
You can pass options via \a flags to control how the directory should
be iterated. By default, \a flags is IteratorFlag::Default.
The listed entries will be filtered according to the file glob patterns
in \a nameFilters (see QDir::setNameFilters() for more details).
For example, the following iterator could be used to iterate over audio
files:
\snippet code/src_corelib_io_qdirlisting.cpp 2
\note To list symlinks that point to non existing files, QDir::System
must be set in \a flags.
\sa IteratorFlags, QDir::setNameFilters()
*/
QDirListing::QDirListing(const QString &path, const QStringList &nameFilters, QDir::Filters filters,
IteratorFlags flags)
QDirListing::QDirListing(const QString &path, const QStringList &nameFilters, IteratorFlags flags)
: d(new QDirListingPrivate)
{
d->initialEntryInfo.entry = QFileSystemEntry(path);
d->nameFilters = nameFilters;
d->filters = filters;
d->iteratorFlags = flags;
d->init();
}
/*!
\internal
Only used by classes that still have to use QDir::Filters; for example,
QDir, such usage may be deprecated at some point.
\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, uint qdirFilters,
uint qdirIteratorFlags)
: d(new QDirListingPrivate)
{
d->initialEntryInfo.entry = QFileSystemEntry(path);
d->nameFilters = nameFilters;
d->setLegacyFilters(QDir::Filters::fromInt(qdirFilters),
QDirIterator::IteratorFlags::fromInt(qdirIteratorFlags));
d->init();
}
/*!
Move constructor. Moves \a other into this QDirListing.
@ -497,6 +616,7 @@ QDirListing::QDirListing(QDirListing &&other) = default;
*/
QDirListing &QDirListing::operator=(QDirListing &&other) = default;
/*!
Destroys the QDirListing.
*/

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -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)

View File

@ -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
/*!

View File

@ -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()
{
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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()
{
}

View File

@ -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;

View File

@ -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;

View File

@ -140,9 +140,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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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)
{
}

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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());
}

View File

@ -635,13 +635,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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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,"
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
"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,"
const QStringList nonBrokenSymlinks = {
#if !defined(Q_NO_SYMLINKS)
"entrylist/linktofile.lnk"_L1,
# if !defined(Q_NO_SYMLINKS_TO_DIRS)
"entrylist/linktodirectory.lnk"_L1,
# 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,"
#endif
"entrylist/writable").split(',');
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("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("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("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,"
#endif
"entrylist/writable").split(',');
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("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,"
#endif
"entrylist/writable").split(',');
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("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,"
#endif
"entrylist/directory/dummy,"
"entrylist/writable").split(',');
QTest::newRow("ResolveSymlinks")
<< QString("entrylist")
<< QDirListing::IteratorFlags{F::ResolveSymlinks}
<< QStringList("*")
<< QStringList{
"entrylist/file"_L1,
"entrylist/directory"_L1,
"entrylist/writable"_L1,
} + nonBrokenSymlinks;
QTest::newRow("empty, default")
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
};
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
};
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::NoFilter) << QStringList("*")
<< QString("empty/.,empty/..").split(',');
QTest::newRow("empty, QDir::NoDotAndDotDot")
<< 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());
for (const QString &item : entries) {
QFileInfo fi(item);
QString filePath = fi.canonicalFilePath();
sortedEntries.emplace_back(!filePath.isEmpty()? filePath : fi.absoluteFilePath());
}
sortedEntries.sort();
if (sortedEntries != list) {
qDebug() << "ACTUAL: " << list;
qDebug() << "EXPECTED:" << sortedEntries;
}
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
<< 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)
<< 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,
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"));

View File

@ -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:

View File

@ -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();