Remove QFileInfo::type and related enum from 5.14

The API is problematic for several reasons:
- the mixing of flags and enum in a single enum type
- the name "type" as somewhat overloaded
- the ease of misuse when comparing the result rather than testing
  for a bit being set

In light of this, focus for 5.14 on the new isShortcut and
isSymbolicLink functions, thus migitating the problematic
isSymLink which conflates the two concepts.

Change-Id: I57e02321edd5061f69a775f04a0932ef89adf866
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
Volker Hilsheimer 2019-08-29 16:22:53 +02:00
parent f00bbd5eb7
commit ca3be92234
3 changed files with 136 additions and 165 deletions

View File

@ -310,19 +310,6 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
\sa QDir, QFile \sa QDir, QFile
*/ */
/*!
\enum QFileInfo::FileType
This enum is returned by type() to describe the type of the file system
entity described by the QFileInfo object.
\value Unknown The object refers to an unknown item.
\value Regular The object refers to a regular file.
\value Directory The object refers to a directory.
\value SymbolicLink The object refers to a symbolic link.
\value Shortcut The object refers to a shortcut.
*/
/*! /*!
\fn QFileInfo &QFileInfo::operator=(QFileInfo &&other) \fn QFileInfo &QFileInfo::operator=(QFileInfo &&other)
@ -1008,7 +995,11 @@ bool QFileInfo::isNativePath() const
*/ */
bool QFileInfo::isFile() const bool QFileInfo::isFile() const
{ {
return (type() & FileTypeMask) == Regular; Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::FileType,
[d]() { return d->metaData.isFile(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::FileType); });
} }
/*! /*!
@ -1019,7 +1010,11 @@ bool QFileInfo::isFile() const
*/ */
bool QFileInfo::isDir() const bool QFileInfo::isDir() const
{ {
return (type() & FileTypeMask) == Directory; Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::DirectoryType,
[d]() { return d->metaData.isDirectory(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::DirectoryType); });
} }
@ -1070,8 +1065,6 @@ bool QFileInfo::isSymLink() const
} }
/*! /*!
\fn bool QFileInfo::isSymbolicLink() const
Returns \c true if this object points to a symbolic link; Returns \c true if this object points to a symbolic link;
otherwise returns \c false. otherwise returns \c false.
@ -1091,9 +1084,16 @@ bool QFileInfo::isSymLink() const
\sa isFile(), isDir(), isShortcut(), symLinkTarget() \sa isFile(), isDir(), isShortcut(), symLinkTarget()
*/ */
/*! bool QFileInfo::isSymbolicLink() const
\fn bool QFileInfo::isShortcut() const {
Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::LegacyLinkType,
[d]() { return d->metaData.isLink(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); });
}
/*!
Returns \c true if this object points to a shortcut; Returns \c true if this object points to a shortcut;
otherwise returns \c false. otherwise returns \c false.
@ -1110,6 +1110,14 @@ bool QFileInfo::isSymLink() const
\sa isFile(), isDir(), isSymbolicLink(), symLinkTarget() \sa isFile(), isDir(), isSymbolicLink(), symLinkTarget()
*/ */
bool QFileInfo::isShortcut() const
{
Q_D(const QFileInfo);
return d->checkAttribute<bool>(
QFileSystemMetaData::LegacyLinkType,
[d]() { return d->metaData.isLnkFile(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); });
}
/*! /*!
Returns \c true if the object points to a directory or to a symbolic Returns \c true if the object points to a directory or to a symbolic
@ -1314,53 +1322,6 @@ qint64 QFileInfo::size() const
}); });
} }
/*!
Returns the QFileInfo::FileTypes.
QFileInfo::FileTypes combines with an indirection flag (link type) and a
base type it refers to.
For example, \c SymbolicLink combines with \c Regular meaning a symlink to
a regular file.
In addition, FileTypeMask and LinkTypeMask are used to extract the base
type and link type respectively.
\sa isFile(), isDir(), isShortcut(), isSymbolicLink()
*/
QFileInfo::FileTypes QFileInfo::type() const
{
Q_D(const QFileInfo);
QFileInfo::FileTypes type = QFileInfo::Unknown;
if (d->checkAttribute<bool>(
QFileSystemMetaData::LegacyLinkType,
[d]() { return d->metaData.isLnkFile(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); })) {
type = QFileInfo::Shortcut;
} else if (d->checkAttribute<bool>(
QFileSystemMetaData::LegacyLinkType,
[d]() { return d->metaData.isLink(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); })) {
type = QFileInfo::SymbolicLink;
}
if (d->checkAttribute<bool>(
QFileSystemMetaData::DirectoryType,
[d]() { return d->metaData.isDirectory(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::DirectoryType); })) {
return type | QFileInfo::Directory;
}
if (d->checkAttribute<bool>(
QFileSystemMetaData::FileType,
[d]() { return d->metaData.isFile(); },
[d]() { return d->getFileFlags(QAbstractFileEngine::FileType); })) {
return type | QFileInfo::Regular;
}
return type;
}
#if QT_DEPRECATED_SINCE(5, 10) #if QT_DEPRECATED_SINCE(5, 10)
/*! /*!
\deprecated \deprecated

View File

@ -66,20 +66,6 @@ public:
QFileInfo(const QFileInfo &fileinfo); QFileInfo(const QFileInfo &fileinfo);
~QFileInfo(); ~QFileInfo();
enum FileType {
Unknown,
// base type
Regular,
Directory,
// indirection flag
SymbolicLink = 0x10,
Shortcut = 0x20,
// mask
FileTypeMask = 0x0f,
LinkTypeMask = 0xf0
};
Q_DECLARE_FLAGS(FileTypes, FileType)
QFileInfo &operator=(const QFileInfo &fileinfo); QFileInfo &operator=(const QFileInfo &fileinfo);
QFileInfo &operator=(QFileInfo &&other) noexcept { swap(other); return *this; } QFileInfo &operator=(QFileInfo &&other) noexcept { swap(other); return *this; }
@ -125,8 +111,8 @@ public:
bool isFile() const; bool isFile() const;
bool isDir() const; bool isDir() const;
bool isSymLink() const; bool isSymLink() const;
inline bool isSymbolicLink() const { return type() & SymbolicLink; } bool isSymbolicLink() const;
inline bool isShortcut() const { return type() & Shortcut; } bool isShortcut() const;
bool isRoot() const; bool isRoot() const;
bool isBundle() const; bool isBundle() const;
@ -145,7 +131,6 @@ public:
QFile::Permissions permissions() const; QFile::Permissions permissions() const;
qint64 size() const; qint64 size() const;
FileTypes type() const;
// ### Qt6: inline these functions // ### Qt6: inline these functions
#if QT_DEPRECATED_SINCE(5, 10) #if QT_DEPRECATED_SINCE(5, 10)

View File

@ -236,6 +236,13 @@ private slots:
void isSymLink_data(); void isSymLink_data();
void isSymLink(); void isSymLink();
void isSymbolicLink_data();
void isSymbolicLink();
void isShortcut_data();
void isShortcut();
void link_data(); void link_data();
void link(); void link();
@ -279,9 +286,6 @@ private slots:
void invalidState(); void invalidState();
void nonExistingFile(); void nonExistingFile();
void type_data();
void type();
private: private:
const QString m_currentDir; const QString m_currentDir;
QString m_sourceFile; QString m_sourceFile;
@ -1342,7 +1346,92 @@ void tst_QFileInfo::isSymLink()
#endif #endif
} }
Q_DECLARE_METATYPE(QFileInfo::FileType) void tst_QFileInfo::isShortcut_data()
{
QFile::remove("link.lnk");
QFile::remove("symlink.lnk");
QFile::remove("link");
QFile::remove("symlink");
QFile::remove("directory.lnk");
QFile::remove("directory");
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("isShortcut");
QFile regularFile(m_sourceFile);
QTest::newRow("regular")
<< regularFile.fileName() << false;
QTest::newRow("directory")
<< QDir::currentPath() << false;
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// windows shortcuts
QVERIFY(regularFile.link("link.lnk"));
QTest::newRow("shortcut")
<< "link.lnk" << true;
QVERIFY(regularFile.link("link"));
QTest::newRow("invalid-shortcut")
<< "link" << false;
QVERIFY(QFile::link(QDir::currentPath(), "directory.lnk"));
QTest::newRow("directory-shortcut")
<< "directory.lnk" << true;
#endif
}
void tst_QFileInfo::isShortcut()
{
QFETCH(QString, path);
QFETCH(bool, isShortcut);
QFileInfo fi(path);
QCOMPARE(fi.isShortcut(), isShortcut);
}
void tst_QFileInfo::isSymbolicLink_data()
{
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("isSymbolicLink");
QFile regularFile(m_sourceFile);
QTest::newRow("regular")
<< regularFile.fileName() << false;
QTest::newRow("directory")
<< QDir::currentPath() << false;
#ifndef Q_NO_SYMLINKS
#if defined(Q_OS_WIN)
#if !defined(Q_OS_WINRT)
QString errorMessage;
const DWORD creationResult = createSymbolicLink("symlink", m_sourceFile, &errorMessage);
if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
QWARN(msgInsufficientPrivileges(errorMessage));
} else {
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
QTest::newRow("NTFS-symlink")
<< "symlink" << true;
}
#endif // !Q_OS_WINRT
#else // Unix:
QVERIFY(regularFile.link("symlink.lnk"));
QTest::newRow("symlink.lnk")
<< "symlink.lnk" << true;
QVERIFY(regularFile.link("symlink"));
QTest::newRow("symlink")
<< "symlink" << true;
QVERIFY(QFile::link(QDir::currentPath(), "directory"));
QTest::newRow("directory-symlink")
<< "directory" << true;
#endif
#endif // !Q_NO_SYMLINKS
}
void tst_QFileInfo::isSymbolicLink()
{
QFETCH(QString, path);
QFETCH(bool, isSymbolicLink);
QFileInfo fi(path);
QCOMPARE(fi.isSymbolicLink(), isSymbolicLink);
}
void tst_QFileInfo::link_data() void tst_QFileInfo::link_data()
{ {
@ -1354,23 +1443,24 @@ void tst_QFileInfo::link_data()
QFile::remove("relative/link"); QFile::remove("relative/link");
QTest::addColumn<QString>("path"); QTest::addColumn<QString>("path");
QTest::addColumn<QFileInfo::FileType>("linkType"); QTest::addColumn<bool>("isShortcut");
QTest::addColumn<bool>("isSymbolicLink");
QTest::addColumn<QString>("linkTarget"); QTest::addColumn<QString>("linkTarget");
QFile file1(m_sourceFile); QFile file1(m_sourceFile);
QFile file2("dummyfile"); QFile file2("dummyfile");
file2.open(QIODevice::WriteOnly); file2.open(QIODevice::WriteOnly);
QTest::newRow("existent file") << m_sourceFile << QFileInfo::Unknown << ""; QTest::newRow("existent file") << m_sourceFile << false << false << "";
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// windows shortcuts // windows shortcuts
QVERIFY(file1.link("link.lnk")); QVERIFY(file1.link("link.lnk"));
QTest::newRow("link.lnk") QTest::newRow("link.lnk")
<< "link.lnk" << QFileInfo::Shortcut << QFileInfo(m_sourceFile).absoluteFilePath(); << "link.lnk" << true << false << QFileInfo(m_sourceFile).absoluteFilePath();
QVERIFY(file2.link("brokenlink.lnk")); QVERIFY(file2.link("brokenlink.lnk"));
QTest::newRow("broken link.lnk") QTest::newRow("broken link.lnk")
<< "brokenlink.lnk" << QFileInfo::Shortcut << QFileInfo("dummyfile").absoluteFilePath(); << "brokenlink.lnk" << true << false << QFileInfo("dummyfile").absoluteFilePath();
#endif #endif
#ifndef Q_NO_SYMLINKS #ifndef Q_NO_SYMLINKS
@ -1383,7 +1473,7 @@ void tst_QFileInfo::link_data()
} else { } else {
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage)); QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
QTest::newRow("link") QTest::newRow("link")
<< "link" << QFileInfo::SymbolicLink << QFileInfo(m_sourceFile).absoluteFilePath(); << "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
} }
creationResult = createSymbolicLink("brokenlink", "dummyfile", &errorMessage); creationResult = createSymbolicLink("brokenlink", "dummyfile", &errorMessage);
@ -1392,22 +1482,22 @@ void tst_QFileInfo::link_data()
} else { } else {
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage)); QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
QTest::newRow("broken link") QTest::newRow("broken link")
<< "brokenlink" << QFileInfo::SymbolicLink << QFileInfo("dummyfile").absoluteFilePath(); << "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
} }
#endif // !Q_OS_WINRT #endif // !Q_OS_WINRT
#else // Unix: #else // Unix:
QVERIFY(file1.link("link")); QVERIFY(file1.link("link"));
QTest::newRow("link") QTest::newRow("link")
<< "link" << QFileInfo::SymbolicLink << QFileInfo(m_sourceFile).absoluteFilePath(); << "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
QVERIFY(file2.link("brokenlink")); QVERIFY(file2.link("brokenlink"));
QTest::newRow("broken link") QTest::newRow("broken link")
<< "brokenlink" << QFileInfo::SymbolicLink << QFileInfo("dummyfile").absoluteFilePath(); << "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
QDir::current().mkdir("relative"); QDir::current().mkdir("relative");
QFile::link("../dummyfile", "relative/link"); QFile::link("../dummyfile", "relative/link");
QTest::newRow("relative link") QTest::newRow("relative link")
<< "relative/link" << QFileInfo::SymbolicLink << QFileInfo("dummyfile").absoluteFilePath(); << "relative/link" << false << true << QFileInfo("dummyfile").absoluteFilePath();
#endif #endif
#endif // !Q_NO_SYMLINKS #endif // !Q_NO_SYMLINKS
file2.remove(); file2.remove();
@ -1416,11 +1506,13 @@ void tst_QFileInfo::link_data()
void tst_QFileInfo::link() void tst_QFileInfo::link()
{ {
QFETCH(QString, path); QFETCH(QString, path);
QFETCH(QFileInfo::FileType, linkType); QFETCH(bool, isShortcut);
QFETCH(bool, isSymbolicLink);
QFETCH(QString, linkTarget); QFETCH(QString, linkTarget);
QFileInfo fi(path); QFileInfo fi(path);
QCOMPARE(fi.type() & QFileInfo::LinkTypeMask, linkType); QCOMPARE(fi.isShortcut(), isShortcut);
QCOMPARE(fi.isSymbolicLink(), isSymbolicLink);
QCOMPARE(fi.symLinkTarget(), linkTarget); QCOMPARE(fi.symLinkTarget(), linkTarget);
} }
@ -2179,73 +2271,6 @@ void tst_QFileInfo::nonExistingFile()
stateCheck(info, dirname, filename); stateCheck(info, dirname, filename);
} }
Q_DECLARE_METATYPE(QFileInfo::FileTypes)
void tst_QFileInfo::type_data()
{
QFile::remove("link.lnk");
QFile::remove("symlink.lnk");
QFile::remove("link");
QFile::remove("symlink");
QFile::remove("directory.lnk");
QFile::remove("directory");
QTest::addColumn<QString>("path");
QTest::addColumn<QFileInfo::FileTypes>("type");
QFile regularFile(m_sourceFile);
QTest::newRow("regular")
<< regularFile.fileName() << QFileInfo::FileTypes(QFileInfo::Regular);
QTest::newRow("directory")
<< QDir::currentPath() << QFileInfo::FileTypes(QFileInfo::Directory);
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// windows shortcuts
QVERIFY(regularFile.link("link.lnk"));
QTest::newRow("shortcut")
<< "link.lnk" << QFileInfo::FileTypes(QFileInfo::Shortcut | QFileInfo::Regular);
QVERIFY(regularFile.link("link"));
QTest::newRow("invalid-shortcut")
<< "link" << QFileInfo::FileTypes(QFileInfo::Regular);
QVERIFY(QFile::link(QDir::currentPath(), "directory.lnk"));
QTest::newRow("directory-shortcut")
<< "directory.lnk" << QFileInfo::FileTypes(QFileInfo::Shortcut | QFileInfo::Directory);
#endif
#ifndef Q_NO_SYMLINKS
#if defined(Q_OS_WIN)
#if !defined(Q_OS_WINRT)
QString errorMessage;
const DWORD creationResult = createSymbolicLink("symlink", m_sourceFile, &errorMessage);
if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
QWARN(msgInsufficientPrivileges(errorMessage));
} else {
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
QTest::newRow("NTFS-symlink")
<< "symlink" << QFileInfo::FileTypes(QFileInfo::SymbolicLink | QFileInfo::Regular);
}
#endif // !Q_OS_WINRT
#else // Unix:
QVERIFY(regularFile.link("symlink.lnk"));
QTest::newRow("symlink.lnk")
<< "symlink.lnk" << QFileInfo::FileTypes(QFileInfo::SymbolicLink | QFileInfo::Regular);
QVERIFY(regularFile.link("symlink"));
QTest::newRow("symlink")
<< "symlink" << QFileInfo::FileTypes(QFileInfo::SymbolicLink | QFileInfo::Regular);
QVERIFY(QFile::link(QDir::currentPath(), "directory"));
QTest::newRow("directory-symlink")
<< "directory" << QFileInfo::FileTypes(QFileInfo::SymbolicLink | QFileInfo::Directory);
#endif
#endif // !Q_NO_SYMLINKS
}
void tst_QFileInfo::type()
{
QFETCH(QString, path);
QFETCH(QFileInfo::FileTypes, type);
QFileInfo info(path);
QCOMPARE(info.type(), type);
}
QTEST_MAIN(tst_QFileInfo) QTEST_MAIN(tst_QFileInfo)
#include "tst_qfileinfo.moc" #include "tst_qfileinfo.moc"