QFileSystemModel: create nodes with correct QFileInfos

Create parent nodes with the corresponding paths, not with
the absolute path of the child node. Otherwise we will get
incorrect QFileInfo at least in the following case:

    QFileSystemModel model;
    model.setRootPath("/usr/bin");
    QModelIndex idx = model.setRootPath("/usr");
    qDebug() << model.fileInfo(idx).absoluteFilePath();

Without the fix it prints "/usr/bin".

It's a regression triggered by 61cefb2f7a
(De-inline QFileSystemModel::fileInfo() and implement it efficiently).

Change-Id: I3b4e5f5b256711e27ad50824eaa8492dbc096808
Task-number: QTBUG-51586
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
This commit is contained in:
Alexander Volkov 2016-03-01 15:44:06 +03:00
parent ab3a8443fa
commit acf43c17b6
3 changed files with 52 additions and 6 deletions

View File

@ -351,6 +351,9 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
)
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
QModelIndex index = QModelIndex(); // start with "My Computer"
QString elementPath;
QChar separator = QLatin1Char('/');
QString trailingSeparator;
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path
QString host = QLatin1String("\\\\") + pathElements.first();
@ -358,6 +361,8 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
absolutePath.append(QLatin1Char('/'));
if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/')))
absolutePath.append(QLatin1Char('/'));
if (absolutePath.endsWith(QLatin1Char('/')))
trailingSeparator = QLatin1String("\\");
int r = 0;
QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
if (!root.children.contains(host.toLower())) {
@ -374,11 +379,10 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
r = translateVisibleLocation(rootNode, r);
index = q->index(r, 0, QModelIndex());
pathElements.pop_front();
} else
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
{
separator = QLatin1Char('\\');
elementPath = host;
elementPath.append(separator);
} else {
if (!pathElements.at(0).contains(QLatin1Char(':'))) {
QString rootPath = QDir(longPath).rootPath();
pathElements.prepend(rootPath);
@ -396,6 +400,11 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
for (int i = 0; i < pathElements.count(); ++i) {
QString element = pathElements.at(i);
if (i != 0)
elementPath.append(separator);
elementPath.append(element);
if (i == pathElements.count() - 1)
elementPath.append(trailingSeparator);
#ifdef Q_OS_WIN
// On Windows, "filename " and "filename" are equivalent and
// "filename . " and "filename" are equivalent
@ -427,7 +436,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
if (!alreadyExisted) {
// 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(absolutePath);
QFileInfo info(elementPath);
if (!info.exists())
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);

View File

@ -569,6 +569,22 @@ void tst_QFiledialog::completer()
if (expectedFile.startsWith(input, caseSensitivity))
++expected;
}
// The temporary dir may create a node in QFileSystemModel
// which will bypass filters. If the path to the temporary
// dir contains an element which should be a subdirectory
// of x dir, but which is not listed, then take it into
// accont.
if (!tempDir.isNull()) {
QString xPath = x.absolutePath();
if (!xPath.endsWith(QLatin1Char('/')))
xPath.append(QLatin1Char('/'));
QString tmpPath = tempDir->path();
if (tmpPath.startsWith(xPath)) {
QString bypassedDirName = tmpPath.mid(xPath.size()).section(QLatin1Char('/'), 0, 0);
if (!expectedFiles.contains(bypassedDirName))
++expected;
}
}
}
QTRY_COMPARE(cModel->rowCount(), expected);

View File

@ -126,6 +126,8 @@ private slots:
void doNotUnwatchOnFailedRmdir();
void specialFiles();
void fileInfo();
protected:
bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList());
@ -1146,6 +1148,25 @@ void tst_QFileSystemModel::specialFiles()
QTRY_VERIFY(!fileListUnderIndex(&model, rootIndex).contains(testFileName));
}
void tst_QFileSystemModel::fileInfo()
{
QFileSystemModel model;
QModelIndex idx;
QVERIFY(model.fileInfo(idx).filePath().isEmpty());
const QString dirPath = flatDirTestPath;
QDir dir(dirPath);
const QString subdir = QStringLiteral("subdir");
QVERIFY(dir.mkdir(subdir));
const QString subdirPath = dir.absoluteFilePath(subdir);
idx = model.setRootPath(subdirPath);
QCOMPARE(model.fileInfo(idx), QFileInfo(subdirPath));
idx = model.setRootPath(dirPath);
QCOMPARE(model.fileInfo(idx), QFileInfo(dirPath));
}
QTEST_MAIN(tst_QFileSystemModel)
#include "tst_qfilesystemmodel.moc"