QFileSystemModel: Handle drive root paths properly on Windows

Fetching a node that was a drive root path (C:/) ended in a wrong result
on Windows. Instead of the drive root the QFileSystemModel returned the
current working directory. This was due to the fact that the code in
QFileSystemModelPrivate::node stripped the /s from the "path elements".
As "C:" (in contrast to "C:/") is seen as a relative path on Windows
that lead to wrong results.

Pick-to: 6.8 6.5
Fixes: QTBUG-133746
Change-Id: I642a67853f31ad9b6710e2b5f696f22b1f60ead3
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Miguel Costa <miguel.costa@qt.io>
(cherry picked from commit 73c5c15d68dabce918a42d424ed31607bc9a20cf)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Oliver Wolff 2025-05-07 12:58:47 +02:00 committed by Qt Cherry-pick Bot
parent 1abb43b755
commit 5cd1ab5f1c
2 changed files with 43 additions and 0 deletions

View File

@ -444,6 +444,14 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
QFileSystemModelPrivate::QFileSystemNode *node; QFileSystemModelPrivate::QFileSystemNode *node;
if (!alreadyExisted) { if (!alreadyExisted) {
#ifdef Q_OS_WIN
// Special case: elementPath is a drive root path (C:). If we do not have the trailing
// '/' it will be read as a relative path (QTBUG-133746)
if (elementPath.length() == 2 && elementPath.at(0).isLetter()
&& elementPath.at(1) == u':') {
elementPath.append(u'/');
}
#endif
// Someone might call ::index("file://cookie/monster/doesn't/like/veggies"), // Someone might call ::index("file://cookie/monster/doesn't/like/veggies"),
// a path that doesn't exists, I.E. don't blindly create directories. // a path that doesn't exists, I.E. don't blindly create directories.
QFileInfo info(elementPath); QFileInfo info(elementPath);

View File

@ -117,6 +117,10 @@ private slots:
void pathWithTrailingSpace_data(); void pathWithTrailingSpace_data();
void pathWithTrailingSpace(); void pathWithTrailingSpace();
#ifdef Q_OS_WIN
void correctFileInfoForDriveRootPath();
#endif
protected: protected:
bool createFiles(QFileSystemModel *model, const QString &test_path, bool createFiles(QFileSystemModel *model, const QString &test_path,
const QStringList &initial_files, int existingFileCount = 0, const QStringList &initial_files, int existingFileCount = 0,
@ -1373,6 +1377,37 @@ void tst_QFileSystemModel::pathWithTrailingSpace()
} }
} }
#ifdef Q_OS_WIN
void tst_QFileSystemModel::correctFileInfoForDriveRootPath()
{
const QString current = QDir::currentPath();
const qsizetype firstSlash = current.indexOf(u'/');
const QString drive = current.left(firstSlash);
QCOMPARE(drive.length(), 2);
// Obtaining the drive root path's file info must not result in the current directory's file
// info (QTBUG-133746)
const QString slashDrive = drive + u'/';
const QString backslashDrive = drive + u'\\';
QFileSystemModel model;
QFileInfo info = model.fileInfo(model.index(slashDrive, 0));
QCOMPARE(info.absoluteFilePath(), slashDrive);
QCOMPARE(info.absolutePath(), slashDrive);
info = model.fileInfo(model.index(backslashDrive, 0));
QCOMPARE(info.absoluteFilePath(), slashDrive);
QCOMPARE(info.absolutePath(), slashDrive);
const qsizetype secondSlash = current.indexOf(u'/', firstSlash + 1);
if (secondSlash == -1)
return;
const QString rootChild = current.left(secondSlash);
QModelIndex childIndex = model.index(rootChild, 0);
info = model.fileInfo(childIndex.parent());
QCOMPARE(info.absoluteFilePath(), slashDrive);
QCOMPARE(info.absolutePath(), slashDrive);
}
#endif
QTEST_MAIN(tst_QFileSystemModel) QTEST_MAIN(tst_QFileSystemModel)
#include "tst_qfilesystemmodel.moc" #include "tst_qfilesystemmodel.moc"