From 5cd1ab5f1c707b50c2e8bc5a18aa7e08e6d7137a Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 7 May 2025 12:58:47 +0200 Subject: [PATCH] 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 Reviewed-by: Miguel Costa (cherry picked from commit 73c5c15d68dabce918a42d424ed31607bc9a20cf) Reviewed-by: Qt Cherry-pick Bot --- src/gui/itemmodels/qfilesystemmodel.cpp | 8 +++++ .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/gui/itemmodels/qfilesystemmodel.cpp b/src/gui/itemmodels/qfilesystemmodel.cpp index d950fd193a0..3d1ed4fb961 100644 --- a/src/gui/itemmodels/qfilesystemmodel.cpp +++ b/src/gui/itemmodels/qfilesystemmodel.cpp @@ -444,6 +444,14 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS QFileSystemModelPrivate::QFileSystemNode *node; 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"), // a path that doesn't exists, I.E. don't blindly create directories. QFileInfo info(elementPath); diff --git a/tests/auto/gui/itemmodels/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/gui/itemmodels/qfilesystemmodel/tst_qfilesystemmodel.cpp index 57e19ef07a3..3a668233bf9 100644 --- a/tests/auto/gui/itemmodels/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/gui/itemmodels/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -117,6 +117,10 @@ private slots: void pathWithTrailingSpace_data(); void pathWithTrailingSpace(); +#ifdef Q_OS_WIN + void correctFileInfoForDriveRootPath(); +#endif + protected: bool createFiles(QFileSystemModel *model, const QString &test_path, 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) #include "tst_qfilesystemmodel.moc"