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:
parent
0cbf579ca1
commit
7c663d04d7
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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]
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
/*!
|
||||
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user