diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-11-20 15:30:20 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-01-09 12:01:17 +0000 |
commit | fcbaa8ec385e796c18cf317e8f364bd8e3c2538b (patch) | |
tree | 02f3dd099051e18e81e15e0050c90b6d56f9a391 | |
parent | d196036024697a75868c1f1626525710495ca428 (diff) |
QFileSystemModel/Windows: Make file name checking case-insensitive
Introduce a special hash modeled on the one used for QFileSystemWatcher
on Windows.
Task-number: QTBUG-31103
Task-number: QTBUG-64147
Change-Id: I69ebabe841716e4957ae3fb04fa5c43d233a3552
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r-- | src/widgets/dialogs/qfilesystemmodel.cpp | 9 | ||||
-rw-r--r-- | src/widgets/dialogs/qfilesystemmodel_p.h | 19 | ||||
-rw-r--r-- | tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp | 29 |
3 files changed, 49 insertions, 8 deletions
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 7458cfdd80..bf88aaa467 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -1100,8 +1100,8 @@ void QFileSystemModelPrivate::sortChildren(int column, const QModelIndex &parent return; QVector<QFileSystemModelPrivate::QFileSystemNode*> values; - QHash<QString, QFileSystemNode *>::const_iterator iterator; - for(iterator = indexNode->children.constBegin() ; iterator != indexNode->children.constEnd() ; ++iterator) { + + for (auto iterator = indexNode->children.constBegin(), cend = indexNode->children.constEnd(); iterator != cend; ++iterator) { if (filtersAcceptsNode(iterator.value())) { values.append(iterator.value()); } else { @@ -1661,13 +1661,10 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons QStringList toRemove; QStringList newFiles = files; std::sort(newFiles.begin(), newFiles.end()); - QHash<QString, QFileSystemNode*>::const_iterator i = parentNode->children.constBegin(); - while (i != parentNode->children.constEnd()) { + for (auto i = parentNode->children.constBegin(), cend = parentNode->children.constEnd(); i != cend; ++i) { QStringList::iterator iterator = std::lower_bound(newFiles.begin(), newFiles.end(), i.value()->fileName); if ((iterator == newFiles.end()) || (i.value()->fileName < *iterator)) toRemove.append(i.value()->fileName); - - ++i; } for (int i = 0 ; i < toRemove.count() ; ++i ) removeNode(parentNode, toRemove[i]); diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index 640225529b..e8bae4f659 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -72,6 +72,23 @@ class ExtendedInformation; class QFileSystemModelPrivate; class QFileIconProvider; +#if defined(Q_OS_WIN) +class QFileSystemModelNodePathKey : public QString +{ +public: + QFileSystemModelNodePathKey() {} + QFileSystemModelNodePathKey(const QString &other) : QString(other) {} + QFileSystemModelNodePathKey(const QFileSystemModelNodePathKey &other) : QString(other) {} + bool operator==(const QFileSystemModelNodePathKey &other) const { return !compare(other, Qt::CaseInsensitive); } +}; + +Q_DECLARE_TYPEINFO(QFileSystemModelNodePathKey, Q_MOVABLE_TYPE); + +inline uint qHash(const QFileSystemModelNodePathKey &key) { return qHash(key.toCaseFolded()); } +#else // Q_OS_WIN +typedef QString QFileSystemModelNodePathKey; +#endif + class Q_AUTOTEST_EXPORT QFileSystemModelPrivate : public QAbstractItemModelPrivate { Q_DECLARE_PUBLIC(QFileSystemModel) @@ -189,7 +206,7 @@ public: bool populatedChildren; bool isVisible; - QHash<QString,QFileSystemNode *> children; + QHash<QFileSystemModelNodePathKey, QFileSystemNode *> children; QList<QString> visibleChildren; int dirtyChildrenIndex; QFileSystemNode *parent; diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 979d5c632e..71efe1d59a 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -43,6 +43,7 @@ #if defined(Q_OS_WIN) # include <qt_windows.h> // for SetFileAttributes #endif +#include <private/qfilesystemengine_p.h> #include <algorithm> @@ -883,6 +884,18 @@ void tst_QFileSystemModel::deleteFile() QVERIFY(!newFile.exists()); } +static QString flipCase(QString s) +{ + for (int i = 0, size = s.size(); i < size; ++i) { + const QChar c = s.at(i); + if (c.isUpper()) + s[i] = c.toLower(); + else if (c.isLower()) + s[i] = c.toUpper(); + } + return s; +} + void tst_QFileSystemModel::caseSensitivity() { QString tmp = flatDirTestPath; @@ -890,9 +903,23 @@ void tst_QFileSystemModel::caseSensitivity() files << "a" << "c" << "C"; QVERIFY(createFiles(tmp, files)); QModelIndex root = model->index(tmp); + QStringList paths; + QModelIndexList indexes; QCOMPARE(model->rowCount(root), 0); for (int i = 0; i < files.count(); ++i) { - QVERIFY(model->index(tmp + '/' + files.at(i)).isValid()); + const QString path = tmp + '/' + files.at(i); + const QModelIndex index = model->index(path); + QVERIFY(index.isValid()); + paths.append(path); + indexes.append(index); + } + + if (!QFileSystemEngine::isCaseSensitive()) { + // QTBUG-31103, QTBUG-64147: Verify that files can be accessed by paths with fLipPeD case. + for (int i = 0; i < paths.count(); ++i) { + const QModelIndex flippedCaseIndex = model->index(flipCase(paths.at(i))); + QCOMPARE(indexes.at(i), flippedCaseIndex); + } } } |