summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2025-07-19 16:44:28 +0300
committerAhmad Samir <a.samirh78@gmail.com>2025-08-09 19:42:51 +0300
commitf180f89ce1de526e3462b0a7b4e4f13d006115ec (patch)
tree4fc0cdb8e2d4276c060b0b934ded51539fc3e511 /src
parent3cf10c70d9a8a48270777e8ce9b6352d2e454cc3 (diff)
QDirListing: port away from private QDirListing ctor, [1]: QDir
Convert the values of a QDir::Filters that can be represented by QDirListing::IteratorFlags, and check the rest of the filters separately in QDir. Change-Id: Ib3cc8b04a2903111cf863b07d239d5a02f8397ca Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qdir.cpp120
-rw-r--r--src/corelib/io/qdir_p.h8
-rw-r--r--src/corelib/io/qdirlisting.cpp10
-rw-r--r--src/corelib/io/qdirlisting.h3
4 files changed, 127 insertions, 14 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index caf8dac464b..577de7bfe1b 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -353,20 +353,113 @@ inline void QDirPrivate::sortFileList(QDir::SortFlags sort, const QFileInfoList
}
}
+#ifndef QT_BOOTSTRAPPED
+/*! \internal
+
+ Returns \c true if the permissions flags set in \a filters match the
+ permissions of \a fileInfo; otherwise returns \c false.
+
+ If there are no permissions set in \a filters this method returns \c true.
+*/
+static bool checkPermissions(const QDirListing::DirEntry &dirEntry, QDir::Filters filters)
+{
+ const auto perms = filters & QDir::PermissionMask;
+ const bool filterByPermissions = perms != 0 && perms != QDir::PermissionMask;
+ if (filterByPermissions) {
+ const QFileInfo fileInfo = dirEntry.fileInfo();
+ if (filters.testFlags(QDir::Readable) && !fileInfo.isReadable())
+ return false;
+ if (filters.testFlags(QDir::Writable) && !fileInfo.isWritable())
+ return false;
+ if (filters.testFlags(QDir::Executable) && !fileInfo.isExecutable())
+ return false;
+ }
+ return true;
+}
+
+static bool checkDotOrDotDot(const QDirListing::DirEntry &dirEntry, QDir::Filters filters)
+{
+ const QString fileName = dirEntry.fileName();
+ if ((filters & QDir::NoDot) && fileName == u".")
+ return false;
+ if ((filters & QDir::NoDotDot) && fileName == u"..")
+ return false;
+ return true;
+}
+
+bool QDirPrivate::checkNonDirListingFlags(const QDirListing::DirEntry &dirEntry,
+ QDir::Filters filters)
+{
+ return checkPermissions(dirEntry, filters) && checkDotOrDotDot(dirEntry, filters);
+}
+
+static void appendIfMatchesNonDirListingFlags(const QDirListing::DirEntry &dirEntry,
+ QDir::Filters filters, QFileInfoList &l)
+{
+ if (QDirPrivate::checkNonDirListingFlags(dirEntry, filters))
+ l.emplace_back(dirEntry.fileInfo());
+}
+
+/*! \internal
+
+ Returns a set of QDirListing::IteratorFlags representing the flags in \a filters
+ that can be represented by QDirListing::IteratorFlags.
+
+ Note that not all QDir::Filter values are supported, some flags have to be checked
+ separately (see checkNonDirListingFlags()).
+*/
+QDirListing::IteratorFlags QDirPrivate::toDirListingFlags(QDir::Filters filters)
+{
+ if (filters == QDir::NoFilter)
+ filters = QDir::AllEntries;
+
+ using F = QDirListing::IteratorFlag;
+ QDirListing::IteratorFlags flags;
+ if (!(filters & QDir::Dirs) && !(filters & QDir::AllDirs))
+ flags |= F::ExcludeDirs;
+ if (!(filters & QDir::Files))
+ flags |= F::ExcludeFiles;
+ if (!(filters & QDir::NoSymLinks))
+ flags |= F::ResolveSymlinks;
+ if (filters & QDir::Hidden)
+ flags |= F::IncludeHidden;
+
+ if (!(filters & QDir::System))
+ flags |= F::ExcludeOther;
+ else
+ flags |= F::IncludeBrokenSymlinks; // QDir::System lists broken symlinks...
+
+
+ if (filters & QDir::AllDirs)
+ flags |= F::NoNameFiltersForDirs;
+ if (filters & QDir::CaseSensitive)
+ flags |= F::CaseSensitive;
+
+ // QDir::Filter has NoDot and NoDotDot; QDirListing has only one,
+ // F::IncludeDotAndDotDot. If either of the QDir::Filter values are
+ // not set, list both and use checkDotOrDotDot() to filter it later.
+ if (!(filters & QDir::NoDot) || !(filters & QDir::NoDotDot)) {
+ if (!(flags & F::ExcludeDirs)) // treat '.' and '..' as dirs
+ flags |= F::IncludeDotAndDotDot;
+ }
+
+ return flags;
+}
+
inline void QDirPrivate::initFileLists(const QDir &dir) const
{
QMutexLocker locker(&fileCache.mutex);
if (!fileCache.fileListsInitialized) {
QFileInfoList l;
- for (const auto &dirEntry : QDirListing(dir.path(), dir.nameFilters(),
- dir.filter().toInt())) {
- l.emplace_back(dirEntry.fileInfo());
- }
+ QDirListing::IteratorFlags flags = toDirListingFlags(dir.filter());
+ for (const auto &dirEntry : QDirListing(dir.path(), dir.nameFilters(), flags))
+ appendIfMatchesNonDirListingFlags(dirEntry, dir.filter(), l);
sortFileList(sort, l, &fileCache.files, &fileCache.fileInfos);
fileCache.fileListsInitialized = true;
}
}
+#endif // !QT_BOOTSTRAPPED
inline void QDirPrivate::clearCache(MetaDataClearing mode)
{
@@ -1439,12 +1532,13 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
}
}
- QDirListing dirList(d->dirEntry.filePath(), nameFilters, filters.toInt());
+ QDirListing::IteratorFlags flags = QDirPrivate::toDirListingFlags(filters);
+ QDirListing dirList(d->dirEntry.filePath(), nameFilters, flags);
QStringList ret;
if (needsSorting) {
QFileInfoList l;
for (const auto &dirEntry : dirList)
- l.emplace_back(dirEntry.fileInfo());
+ appendIfMatchesNonDirListingFlags(dirEntry, filters, l);
d->sortFileList(sort, l, &ret, nullptr);
} else {
for (const auto &dirEntry : dirList)
@@ -1485,8 +1579,9 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter
}
QFileInfoList l;
- for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, filters.toInt()))
- l.emplace_back(dirEntry.fileInfo());
+ const QDirListing::IteratorFlags flags = QDirPrivate::toDirListingFlags(filters);
+ for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), nameFilters, flags))
+ appendIfMatchesNonDirListingFlags(dirEntry, filters, l);
QFileInfoList ret;
d->sortFileList(sort, l, nullptr, &ret);
return ret;
@@ -1989,8 +2084,13 @@ 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.toInt());
- return dirList.cbegin() == dirList.cend();
+
+ QDirListing::IteratorFlags flags = QDirPrivate::toDirListingFlags(filters);
+ for (const auto &dirEntry : QDirListing(d->dirEntry.filePath(), d->nameFilters, flags)) {
+ if (QDirPrivate::checkNonDirListingFlags(dirEntry, filters))
+ return false;
+ }
+ return true;
}
#endif // !QT_BOOTSTRAPPED
diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h
index ad2b9bf925c..dc0756d2ec3 100644
--- a/src/corelib/io/qdir_p.h
+++ b/src/corelib/io/qdir_p.h
@@ -16,6 +16,7 @@
// We mean it.
//
+#include "qdirlisting.h"
#include "qfilesystementry_p.h"
#include "qfilesystemmetadata_p.h"
@@ -44,7 +45,13 @@ public:
bool exists() const;
+#ifndef QT_BOOTSTRAPPED
+ static QDirListing::IteratorFlags toDirListingFlags(QDir::Filters filters);
+ static bool checkNonDirListingFlags(const QDirListing::DirEntry &dirEntry,
+ QDir::Filters filters);
+
void initFileLists(const QDir &dir) const;
+#endif // !QT_BOOTSTRAPPED
static void sortFileList(QDir::SortFlags, const QFileInfoList &, QStringList *, QFileInfoList *);
@@ -52,6 +59,7 @@ public:
static inline QStringList splitFilters(const QString &nameFilter, QChar sep = {});
+
void setPath(const QString &path);
enum MetaDataClearing { KeepMetaData, IncludingMetaData };
diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp
index 363f028cb62..95d8e1fab61 100644
--- a/src/corelib/io/qdirlisting.cpp
+++ b/src/corelib/io/qdirlisting.cpp
@@ -129,6 +129,8 @@
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.
+
+ \omitvalue NoNameFiltersForDirs
*/
#include "qdirlisting.h"
@@ -507,8 +509,12 @@ bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
// name filter
#if QT_CONFIG(regularexpression)
- if (!regexMatchesName(fileName))
- return false;
+ const bool skipNameFilters = iteratorFlags.testAnyFlags(F::NoNameFiltersForDirs)
+ && entryInfo.isDir();
+ if (!skipNameFilters) {
+ if (!regexMatchesName(fileName))
+ return false;
+ }
#endif // QT_CONFIG(regularexpression)
if (isDotOrDotDot(fileName))
diff --git a/src/corelib/io/qdirlisting.h b/src/corelib/io/qdirlisting.h
index acd240b81f7..5f807561ee3 100644
--- a/src/corelib/io/qdirlisting.h
+++ b/src/corelib/io/qdirlisting.h
@@ -43,6 +43,7 @@ public:
Recursive = 0x000400,
FollowDirSymlinks = 0x000800,
IncludeBrokenSymlinks = 0x001000,
+ NoNameFiltersForDirs = 0x040000, // used internally
};
Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag)
@@ -162,8 +163,6 @@ private:
uint qdirIteratorFlags = 0); // QDirIterator::NoIteratorFlags == 0x0
QDirListingPrivate *d;
- friend class QDir;
- friend class QDirPrivate;
friend class QDirIteratorPrivate;
friend class QAbstractFileEngine;
friend class QFileInfoGatherer;