diff options
-rw-r--r-- | src/corelib/io/qdir.cpp | 65 | ||||
-rw-r--r-- | src/corelib/io/qdir.h | 44 | ||||
-rw-r--r-- | src/corelib/io/qfile.cpp | 50 | ||||
-rw-r--r-- | src/corelib/io/qfile.h | 107 | ||||
-rw-r--r-- | src/corelib/io/qfileinfo.cpp | 81 | ||||
-rw-r--r-- | src/corelib/io/qfileinfo.h | 38 | ||||
-rw-r--r-- | tests/auto/corelib/io/qdir/qdir.pro | 2 | ||||
-rw-r--r-- | tests/auto/corelib/io/qdir/tst_qdir.cpp | 41 | ||||
-rw-r--r-- | tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro | 1 | ||||
-rw-r--r-- | tests/auto/corelib/io/qfile/test.pro | 2 | ||||
-rw-r--r-- | tests/auto/corelib/io/qfile/tst_qfile.cpp | 51 | ||||
-rw-r--r-- | tests/auto/corelib/io/qfileinfo/qfileinfo.pro | 3 | ||||
-rw-r--r-- | tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp | 93 |
13 files changed, 573 insertions, 5 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 5ce3fbcca8..20af40f973 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -585,8 +585,8 @@ QDir::QDir(const QString &path) : d_ptr(new QDirPrivate(path)) also sorts the names using \a sort. The default \a nameFilter is an empty string, which excludes - nothing; the default \a filters is \l AllEntries, which also means - exclude nothing. The default \a sort is \l Name | \l IgnoreCase, + nothing; the default \a filters is \l AllEntries, which also + excludes nothing. The default \a sort is \l Name | \l IgnoreCase, i.e. sort by name case-insensitively. If \a path is an empty string, QDir uses "." (the current @@ -2551,4 +2551,65 @@ QDebug operator<<(QDebug debug, const QDir &dir) } #endif // QT_NO_DEBUG_STREAM +/*! + \fn QDir::QDir(const std::filesystem::path &path) + \since 6.0 + Constructs a QDir pointing to the given directory \a path. If path + is empty the program's working directory, ("."), is used. + + \sa currentPath() +*/ +/*! + \fn QDir::QDir(const std::filesystem::path &path, + const QString &nameFilter, + SortFlags sort, + Filters filters) + \since 6.0 + + Constructs a QDir with path \a path, that filters its entries by + name using \a nameFilter and by attributes using \a filters. It + also sorts the names using \a sort. + + The default \a nameFilter is an empty string, which excludes + nothing; the default \a filters is \l AllEntries, which also + excludes nothing. The default \a sort is \l Name | \l IgnoreCase, + i.e. sort by name case-insensitively. + + If \a path is empty, QDir uses "." (the current + directory). If \a nameFilter is an empty string, QDir uses the + name filter "*" (all files). + + Note that \a path need not exist. + + \sa exists(), setPath(), setNameFilters(), setFilter(), setSorting() +*/ +/*! + \fn void QDir::setPath(const std::filesystem::path &path) + \since 6.0 + \overload +*/ +/*! + \fn void QDir::addSearchPath(const QString &prefix, const std::filesystem::path &path) + \since 6.0 + \overload +*/ +/*! + \fn std::filesystem::path QDir::filesystemPath() const + \since 6.0 + Returns path() as \c{std::filesystem::path}. + \sa path() +*/ +/*! + \fn std::filesystem::path QDir::filesystemAbsolutePath() const + \since 6.0 + Returns absolutePath() as \c{std::filesystem::path}. + \sa absolutePath() +*/ +/*! + \fn std::filesystem::path QDir::filesystemCanonicalPath() const + \since 6.0 + Returns canonicalPath() as \c{std::filesystem::path}. + \sa canonicalPath() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 45a40995f8..f0dda73ebb 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -41,13 +41,13 @@ #define QDIR_H #include <QtCore/qstring.h> +#include <QtCore/qfile.h> #include <QtCore/qfileinfo.h> #include <QtCore/qstringlist.h> #include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE - class QDirIterator; class QDirPrivate; @@ -102,6 +102,22 @@ public: QDir(const QString &path = QString()); QDir(const QString &path, const QString &nameFilter, SortFlags sort = SortFlags(Name | IgnoreCase), Filters filter = AllEntries); +#ifdef Q_CLANG_QDOC + QDir(const std::filesystem::path &path); + QDir(const std::filesystem::path &path, const QString &nameFilter, + SortFlags sort = SortFlags(Name | IgnoreCase), Filters filter = AllEntries); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + QDir(const T &path) : QDir(QtPrivate::fromFilesystemPath(path)) + { + } + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + QDir(const T &path, const QString &nameFilter, + SortFlags sort = SortFlags(Name | IgnoreCase), Filters filter = AllEntries) + : QDir(QtPrivate::fromFilesystemPath(path), nameFilter, sort, filter) + { + } +#endif // QT_CONFIG(cxx17_filesystem) ~QDir(); QDir &operator=(const QDir &); @@ -115,9 +131,26 @@ public: { qSwap(d_ptr, other.d_ptr); } void setPath(const QString &path); +#ifdef Q_CLANG_QDOC + void setPath(const std::filesystem::path &path); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + void setPath(const T &path) + { + setPath(QtPrivate::fromFilesystemPath(path)); + } +#endif // QT_CONFIG(cxx17_filesystem) QString path() const; QString absolutePath() const; QString canonicalPath() const; +#if QT_CONFIG(cxx17_filesystem) + std::filesystem::path filesystemPath() const + { return QtPrivate::toFilesystemPath(path()); } + std::filesystem::path filesystemAbsolutePath() const + { return QtPrivate::toFilesystemPath(absolutePath()); } + std::filesystem::path filesystemCanonicalPath() const + { return QtPrivate::toFilesystemPath(canonicalPath()); } +#endif // QT_CONFIG(cxx17_filesystem) #if QT_DEPRECATED_SINCE(5, 13) QT_DEPRECATED_X("Use QDir::addSearchPath() instead") @@ -126,6 +159,15 @@ public: static void setSearchPaths(const QString &prefix, const QStringList &searchPaths); static void addSearchPath(const QString &prefix, const QString &path); +#ifdef Q_CLANG_QDOC + static void addSearchPath(const QString &prefix, const std::filesystem::path &path); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + static void addSearchPath(const QString &prefix, const T &path) + { + addSearchPath(prefix, QtPrivate::fromFilesystemPath(path)); + } +#endif // QT_CONFIG(cxx17_filesystem) static QStringList searchPaths(const QString &prefix); QString dirName() const; diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 0cdc5bd6d3..2a9c24bbd5 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1210,6 +1210,56 @@ qint64 QFile::size() const return QFileDevice::size(); // for now } +/*! + \fn QFile::QFile(const std::filesystem::path &name) + \since 6.0 + + Constructs a new file object to represent the file with the given \a name. +*/ +/*! + \fn QFile::QFile(const std::filesystem::path &name, QObject *parent) + \since 6.0 + + Constructs a new file object with the given \a parent to represent the + file with the specified \a name. +*/ +/*! + \fn std::filesystem::path QFile::filesystemFileName() const + \since 6.0 + Returns fileName() as \c{std::filesystem::path}. +*/ +/*! + \fn void QFile::setFileName(const std::filesystem::path &name) + \since 6.0 + \overload +*/ +/*! + \fn bool QFile::rename(const std::filesystem::path &newName) + \since 6.0 + \overload +*/ +/*! + \fn bool QFile::link(const std::filesystem::path &newName) + \since 6.0 + \overload +*/ +/*! + \fn bool QFile::copy(const std::filesystem::path &newName) + \since 6.0 + \overload +*/ +/*! + \fn QFile::Permissions QFile::permissions(const std::filesystem::path &filename) + \since 6.0 + \overload +*/ +/*! + \fn bool QFile::setPermissions(const std::filesystem::path &filename, Permissions permissionSpec) + \since 6.0 + \overload +*/ + + QT_END_NAMESPACE #ifndef QT_NO_QOBJECT diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h index 917fec4e1a..dab20b85a1 100644 --- a/src/corelib/io/qfile.h +++ b/src/corelib/io/qfile.h @@ -45,12 +45,44 @@ #include <QtCore/qstring.h> #include <stdio.h> +#if QT_CONFIG(cxx17_filesystem) +#include <filesystem> +#endif + #ifdef open #error qfile.h must be included before any header file that defines open #endif QT_BEGIN_NAMESPACE +#if QT_CONFIG(cxx17_filesystem) +namespace QtPrivate { +inline QString fromFilesystemPath(const std::filesystem::path &path) +{ +#ifdef Q_OS_WIN + return QString::fromStdWString(path.native()); +#else + return QString::fromStdString(path.native()); +#endif +} + +inline std::filesystem::path toFilesystemPath(const QString &path) +{ +#ifdef Q_OS_WIN + return std::filesystem::path(path.toStdU16String()); +#else + return std::filesystem::path(path.toStdString()); +#endif +} + +// Both std::filesystem::path and QString (without QT_NO_CAST_FROM_ASCII) can be implicitly +// constructed from string literals so we force the std::fs::path parameter to only +// accept std::fs::path with no implicit conversions. +template<typename T> +using ForceFilesystemPath = typename std::enable_if_t<std::is_same_v<std::filesystem::path, T>, int>; +} +#endif // QT_CONFIG(cxx17_filesystem) + class QTemporaryFile; class QFilePrivate; @@ -64,14 +96,45 @@ class Q_CORE_EXPORT QFile : public QFileDevice public: QFile(); QFile(const QString &name); +#ifdef Q_CLANG_QDOC + QFile(const std::filesystem::path &name); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + QFile(const T &name) : QFile(QtPrivate::fromFilesystemPath(name)) + { + } +#endif // QT_CONFIG(cxx17_filesystem) + #ifndef QT_NO_QOBJECT explicit QFile(QObject *parent); QFile(const QString &name, QObject *parent); -#endif + +#ifdef Q_CLANG_QDOC + QFile(const std::filesystem::path &path, QObject *parent); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + QFile(const T &path, QObject *parent) : QFile(QtPrivate::fromFilesystemPath(path), parent) + { + } +#endif // QT_CONFIG(cxx17_filesystem) +#endif // !QT_NO_QOBJECT ~QFile(); QString fileName() const override; +#if QT_CONFIG(cxx17_filesystem) + std::filesystem::path filesystemFileName() const + { return QtPrivate::toFilesystemPath(fileName()); } +#endif void setFileName(const QString &name); +#ifdef Q_CLANG_QDOC + void setFileName(const std::filesystem::path &name); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + void setFileName(const T &name) + { + setFileName(QtPrivate::fromFilesystemPath(name)); + } +#endif // QT_CONFIG(cxx17_filesystem) #if defined(Q_OS_DARWIN) // Mac always expects filenames in UTF-8... and decomposed... @@ -129,12 +192,39 @@ public: static bool moveToTrash(const QString &fileName, QString *pathInTrash = nullptr); bool rename(const QString &newName); +#ifdef Q_CLANG_QDOC + bool rename(const std::filesystem::path &newName); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + bool rename(const T &newName) + { + return rename(QtPrivate::fromFilesystemPath(newName)); + } +#endif // QT_CONFIG(cxx17_filesystem) static bool rename(const QString &oldName, const QString &newName); bool link(const QString &newName); +#ifdef Q_CLANG_QDOC + bool link(const std::filesystem::path &newName); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + bool link(const T &newName) + { + return link(QtPrivate::fromFilesystemPath(newName)); + } +#endif // QT_CONFIG(cxx17_filesystem) static bool link(const QString &oldname, const QString &newName); bool copy(const QString &newName); +#ifdef Q_CLANG_QDOC + bool copy(const std::filesystem::path &newName); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + bool copy(const T &newName) + { + return copy(QtPrivate::fromFilesystemPath(newName)); + } +#endif // QT_CONFIG(cxx17_filesystem) static bool copy(const QString &fileName, const QString &newName); bool open(OpenMode flags) override; @@ -150,6 +240,21 @@ public: static Permissions permissions(const QString &filename); bool setPermissions(Permissions permissionSpec) override; static bool setPermissions(const QString &filename, Permissions permissionSpec); +#ifdef Q_CLANG_QDOC + static Permissions permissions(const std::filesystem::path &filename); + static bool setPermissions(const std::filesystem::path &filename, Permissions permissionSpec); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + static Permissions permissions(const T &filename) + { + return permissions(QtPrivate::fromFilesystemPath(filename)); + } + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + static bool setPermissions(const T &filename, Permissions permissionSpec) + { + return setPermissions(QtPrivate::fromFilesystemPath(filename), permissionSpec); + } +#endif // QT_CONFIG(cxx17_filesystem) protected: #ifdef QT_NO_QOBJECT diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 64b1557231..479532fc36 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -363,7 +363,7 @@ QFileInfo::QFileInfo(const QFile &file) : d_ptr(new QFileInfoPrivate(file.fileNa /*! Constructs a new QFileInfo that gives information about the given - \a file in the directory \a dir. + \a file relative to the directory \a dir. If \a dir has a relative path, the QFileInfo will also have a relative path. @@ -1576,4 +1576,83 @@ QDebug operator<<(QDebug dbg, const QFileInfo &fi) } #endif +/*! + \fn QFileInfo::QFileInfo(const std::filesystem::path &file) + \since 6.0 + + Constructs a new QFileInfo that gives information about the given + \a file. + + \sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath() +*/ +/*! + \fn QFileInfo::QFileInfo(const QDir &dir, const std::filesystem::path &file) + \since 6.0 + + Constructs a new QFileInfo that gives information about the given + \a file relative to the directory \a dir. + + If \a dir has a relative path, the QFileInfo will also have a + relative path. + + If \a file is an absolute path, then the directory specified + by \a dir will be disregarded. +*/ +/*! + \fn void QFileInfo::setFile(const std::filesystem::path &file) + \since 6.0 + + Sets the file that the QFileInfo provides information about to \a + file. +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemFilePath() const + \since 6.0 + + Returns filePath() as a \c{std::filesystem::path}. + \sa filePath() +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemAbsoluteFilePath() const + \since 6.0 + + Returns absoluteFilePath() as a \c{std::filesystem::path}. + \sa absoluteFilePath() +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemCanonicalFilePath() const + \since 6.0 + + Returns canonicalFilePath() as a \c{std::filesystem::path}. + \sa canonicalFilePath() +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemPath() const + \since 6.0 + + Returns path() as a \c{std::filesystem::path}. + \sa path() +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemAbsolutePath() const + \since 6.0 + + Returns absolutePath() as a \c{std::filesystem::path}. + \sa absolutePath() +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemCanonicalPath() const + \since 6.0 + + Returns canonicalPath() as a \c{std::filesystem::path}. + \sa canonicalPath() +*/ +/*! + \fn std::filesystem::path QFileInfo::filesystemSymLinkTarget() const + \since 6.0 + + Returns symLinkTarget() as a \c{std::filesystem::path}. + \sa symLinkTarget() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index 7c7ff56ae4..2bed64eb1a 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -64,6 +64,18 @@ public: QFileInfo(const QFile &file); QFileInfo(const QDir &dir, const QString &file); QFileInfo(const QFileInfo &fileinfo); +#ifdef Q_CLANG_QDOC + QFileInfo(const std::filesystem::path &file); + QFileInfo(const QDir &dir, const std::filesystem::path &file); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + QFileInfo(const T &file) : QFileInfo(QtPrivate::fromFilesystemPath(file)) { } + + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + QFileInfo(const QDir &dir, const T &file) : QFileInfo(dir, QtPrivate::fromFilesystemPath(file)) + { + } +#endif // QT_CONFIG(cxx17_filesystem) ~QFileInfo(); QFileInfo &operator=(const QFileInfo &fileinfo); @@ -78,6 +90,13 @@ public: void setFile(const QString &file); void setFile(const QFile &file); void setFile(const QDir &dir, const QString &file); +#ifdef Q_CLANG_QDOC + void setFile(const std::filesystem::path &file); +#elif QT_CONFIG(cxx17_filesystem) + template<typename T, QtPrivate::ForceFilesystemPath<T> = 0> + void setFile(const T &file) { setFile(QtPrivate::fromFilesystemPath(file)); } +#endif // QT_CONFIG(cxx17_filesystem) + bool exists() const; static bool exists(const QString &file); void refresh(); @@ -85,6 +104,14 @@ public: QString filePath() const; QString absoluteFilePath() const; QString canonicalFilePath() const; +#if QT_CONFIG(cxx17_filesystem) + std::filesystem::path filesystemFilePath() const + { return QtPrivate::toFilesystemPath(filePath()); } + std::filesystem::path filesystemAbsoluteFilePath() const + { return QtPrivate::toFilesystemPath(absoluteFilePath()); } + std::filesystem::path filesystemCanonicalFilePath() const + { return QtPrivate::toFilesystemPath(canonicalFilePath()); } +#endif // QT_CONFIG(cxx17_filesystem) QString fileName() const; QString baseName() const; QString completeBaseName() const; @@ -95,6 +122,13 @@ public: QString path() const; QString absolutePath() const; QString canonicalPath() const; +#if QT_CONFIG(cxx17_filesystem) + std::filesystem::path filesystemPath() const { return QtPrivate::toFilesystemPath(path()); } + std::filesystem::path filesystemAbsolutePath() const + { return QtPrivate::toFilesystemPath(absolutePath()); } + std::filesystem::path filesystemCanonicalPath() const + { return QtPrivate::toFilesystemPath(canonicalPath()); } +#endif // QT_CONFIG(cxx17_filesystem) QDir dir() const; QDir absoluteDir() const; @@ -122,6 +156,10 @@ public: QString readLink() const; #endif QString symLinkTarget() const; +#if QT_CONFIG(cxx17_filesystem) + std::filesystem::path filesystemSymLinkTarget() const + { return QtPrivate::toFilesystemPath(symLinkTarget()); } +#endif // QT_CONFIG(cxx17_filesystem) QString owner() const; uint ownerId() const; diff --git a/tests/auto/corelib/io/qdir/qdir.pro b/tests/auto/corelib/io/qdir/qdir.pro index a8b106e250..f6ff0d0421 100644 --- a/tests/auto/corelib/io/qdir/qdir.pro +++ b/tests/auto/corelib/io/qdir/qdir.pro @@ -12,3 +12,5 @@ contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA android:!android-embedded { RESOURCES += android_testdata.qrc } + +qtConfig(c++17): CONFIG += c++17 diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 1162fb31e4..5462a63fab 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -216,6 +216,8 @@ private slots: void emptyDir(); void nonEmptyDir(); + void stdfilesystem(); + private: #ifdef BUILTIN_TESTDATA QString m_dataPath; @@ -2403,6 +2405,45 @@ void tst_QDir::nonEmptyDir() QVERIFY(!dir.isEmpty()); } +void tst_QDir::stdfilesystem() +{ +#if QT_CONFIG(cxx17_filesystem) + namespace fs = std::filesystem; + fs::path path("."); + QDir dir(path); + QCOMPARE(dir, QDir(QStringLiteral("."))); + + path = path / "testdir" / "dir"; + dir.setPath(path); + + QCOMPARE(dir, QDir(QStringLiteral("./testdir/dir"))); + + auto fsPath = dir.filesystemPath(); + QCOMPARE(QString::fromStdU16String(fsPath.u16string()), dir.path()); + fsPath = dir.filesystemAbsolutePath(); + QCOMPARE(QString::fromStdU16String(fsPath.u16string()), dir.absolutePath()); + fsPath = dir.filesystemCanonicalPath(); + QCOMPARE(QString::fromStdU16String(fsPath.u16string()), dir.canonicalPath()); + + QDir emptyPath(fs::path{}); + QCOMPARE(emptyPath, QDir(QStringLiteral("."))); + + { + // Test QDir ctor with filter and sorting reversed + QDir filteredDir(fs::path{"."} / "searchdir", "subdir*", + QDir::SortFlag::Reversed, QDir::Filter::Dirs); + QStringList entries = filteredDir.entryList(); + QCOMPARE(entries, QStringList() << "subdir2" << "subdir1"); + QCOMPARE(filteredDir.sorting(), QDir::SortFlag::Reversed); + QCOMPARE(filteredDir.filter(), QDir::Filter::Dirs); + QCOMPARE(filteredDir.nameFilters().length(), 1); + QCOMPARE(filteredDir.nameFilters().first(), "subdir*"); + } +#else + QSKIP("Not supported"); +#endif +} + QTEST_MAIN(tst_QDir) #include "tst_qdir.moc" diff --git a/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro b/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro index 512da8939b..bc48a9fb39 100644 --- a/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro +++ b/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro @@ -2,3 +2,4 @@ SOURCES += main.cpp QT = core load(qt_test_helper) +CONFIG += c++17 diff --git a/tests/auto/corelib/io/qfile/test.pro b/tests/auto/corelib/io/qfile/test.pro index 7a2767bf3c..47b778bc33 100644 --- a/tests/auto/corelib/io/qfile/test.pro +++ b/tests/auto/corelib/io/qfile/test.pro @@ -24,3 +24,5 @@ TESTDATA += \ resources/file1.ext1 win32:!winrt: QMAKE_USE += ole32 uuid + +CONFIG += c++17 diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 350bff0652..b8f0d29078 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -282,6 +282,8 @@ private slots: void moveToTrash_data(); void moveToTrash(); + void stdfilesystem(); + private: #ifdef BUILTIN_TESTDATA QSharedPointer<QTemporaryDir> m_dataDir; @@ -3812,5 +3814,54 @@ void tst_QFile::moveToTrash() } } +void tst_QFile::stdfilesystem() +{ +#if QT_CONFIG(cxx17_filesystem) + namespace fs = std::filesystem; + auto toFSPath = [](const QFile &file) { return fs::path(file.fileName().toStdU16String()); }; + fs::path path { "./path" }; + QFile file(path); + QCOMPARE(toFSPath(file), path); + + QCOMPARE(path, file.filesystemFileName()); + + { + QFile parentedFile(path, this); + QCOMPARE(file.fileName(), parentedFile.fileName()); + QCOMPARE(parentedFile.parent(), this); + } + + path = path / "filename"; + file.setFileName(path); + QCOMPARE(toFSPath(file), path); + + path = "test-file"; + file.setFileName(path); + QVERIFY(file.open(QIODevice::WriteOnly)); + file.close(); + + path = "tile-fest"; + QVERIFY(file.rename(path)); + QVERIFY(fs::exists(path)); + fs::path linkfile { "test-link" }; + QVERIFY(file.link(linkfile)); + QVERIFY(fs::exists(linkfile)); + + fs::path copyfile { "copy-file" }; + QVERIFY(file.copy(copyfile)); + QVERIFY(fs::exists(copyfile)); + + QFileDevice::Permissions p = QFile::permissions(path); + QVERIFY(p.testFlag(QFile::WriteUser) || p.testFlag(QFile::WriteOwner)); // some we know for sure + if (p.testFlag(QFile::ReadUser)) + p.setFlag(QFile::ReadUser, false); + else if (p.testFlag(QFile::ReadOwner)) + p.setFlag(QFile::ReadOwner, false); + QVERIFY(QFile::setPermissions(path, p)); +#else + QSKIP("Not supported"); +#endif +} + QTEST_MAIN(tst_QFile) #include "tst_qfile.moc" diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro index d181d16a3e..af764f3679 100644 --- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro @@ -6,3 +6,6 @@ RESOURCES += qfileinfo.qrc \ testdata.qrc win32:!winrt: QMAKE_USE += advapi32 netapi32 + +# for std::filesystem tests +qtConfig(c++17): CONFIG += c++17 diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index ebb9a0a44c..a1f9ca0b87 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -287,6 +287,8 @@ private slots: void invalidState(); void nonExistingFile(); + void stdfilesystem(); + private: const QString m_currentDir; QString m_sourceFile; @@ -2269,6 +2271,97 @@ void tst_QFileInfo::nonExistingFile() stateCheck(info, dirname, filename); } +void tst_QFileInfo::stdfilesystem() +{ +#if QT_CONFIG(cxx17_filesystem) + + namespace fs = std::filesystem; + + // Verify constructing with fs::path leads to valid objects + { + // We compare using absoluteFilePath since QFileInfo::operator== ends up using + // canonicalFilePath which evaluates to empty-string for non-existent paths causing + // these tests to always succeed. +#define COMPARE_CONSTRUCTION(filepath) \ + QCOMPARE(QFileInfo(fs::path(filepath)).absoluteFilePath(), \ + QFileInfo(QString::fromLocal8Bit(filepath)).absoluteFilePath()); \ + QCOMPARE(QFileInfo(base, fs::path(filepath)).absoluteFilePath(), \ + QFileInfo(base, QString::fromLocal8Bit(filepath)).absoluteFilePath()) + + QDir base{ "../" }; // Used for the QFileInfo(QDir, <path>) ctor + + COMPARE_CONSTRUCTION("./file"); + +#ifdef Q_OS_WIN32 + COMPARE_CONSTRUCTION("C:\\path\\to\\file.txt"); + COMPARE_CONSTRUCTION("x:\\path/to\\file.txt"); + COMPARE_CONSTRUCTION("D:/path/TO/file.txt"); + COMPARE_CONSTRUCTION("//sharename/folder/file.txt"); +#endif + COMPARE_CONSTRUCTION("/path/TO/file.txt"); + COMPARE_CONSTRUCTION("./path/TO/file.txt"); + COMPARE_CONSTRUCTION("../file.txt"); + COMPARE_CONSTRUCTION("./filæ.txt"); + +#undef COMPARE_CONSTRUCTION + { + // One proper comparison with operator== for each ctor + QFile file(QStringLiteral("./filesystem_test_file.txt")); + if (!file.open(QFile::NewOnly)) + QVERIFY(file.exists()); + file.close(); + + QFileInfo pinfo{ fs::path{ "./filesystem_test_file.txt" } }; + QFileInfo info{ QStringLiteral("./filesystem_test_file.txt") }; + QCOMPARE(pinfo, info); + } + + { + // And once more for QFileInfo(QDir, <path>) + const QString &subdir = QStringLiteral("./filesystem_test_dir/"); + base = QDir(QStringLiteral(".")); + if (!base.exists(subdir)) + QVERIFY(base.mkdir(subdir)); + base.cd(subdir); + QFile file{ base.filePath(QStringLiteral("./filesystem_test_file.txt")) }; + if (!file.open(QFile::NewOnly)) + QVERIFY(file.exists()); + file.close(); + QFileInfo pinfo{ base, fs::path{ "filesystem_test_file.txt" } }; + QFileInfo info{ base, QStringLiteral("filesystem_test_file.txt") }; + QCOMPARE(pinfo, info); + } + } + + // Verify that functions returning path all point to the same place + { +#define COMPARE_PATHS(actual, expected) \ + QCOMPARE(QString::fromStdU16String(actual.u16string()), expected) + + QFile file(QStringLiteral("./orig")); + if (!file.open(QFile::NewOnly)) + QVERIFY(file.exists()); + file.close(); + + QFileInfo info{ QStringLiteral("./orig") }; + COMPARE_PATHS(info.filesystemPath(), info.path()); + COMPARE_PATHS(info.filesystemAbsolutePath(), info.absolutePath()); + COMPARE_PATHS(info.filesystemCanonicalPath(), info.canonicalPath()); + COMPARE_PATHS(info.filesystemFilePath(), info.filePath()); + COMPARE_PATHS(info.filesystemAbsoluteFilePath(), info.absoluteFilePath()); + COMPARE_PATHS(info.filesystemCanonicalFilePath(), info.canonicalFilePath()); + + QVERIFY(file.link(QStringLiteral("./filesystem_test_symlink.lnk"))); + info = QFileInfo{ "./filesystem_test_symlink.lnk" }; + + COMPARE_PATHS(info.filesystemSymLinkTarget(), info.symLinkTarget()); +#undef COMPARE_PATHS + } + +#else + QSKIP("Not supported"); +#endif +} QTEST_MAIN(tst_QFileInfo) #include "tst_qfileinfo.moc" |