From e9c079a648721ea53d58e63bc61b61f9a5da867f Mon Sep 17 00:00:00 2001 From: Daniel Teske <daniel.teske@nokia.com> Date: Fri, 25 Nov 2011 13:17:52 +0100 Subject: [PATCH] Add FileName isChildOf/relativePath and endsWith and appendPath Needed by qtversionmanager Change-Id: I4d455298e809b744ae3663493914db6e31f372a6 Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com> Reviewed-by: Daniel Teske <daniel.teske@nokia.com> --- src/libs/utils/fileutils.cpp | 70 ++++++++++++++++++---- src/libs/utils/fileutils.h | 19 ++++-- src/plugins/qt4projectmanager/qt4nodes.cpp | 11 ++-- 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 65e3fbbad67..4a306ef79b5 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -407,6 +407,14 @@ TempFileSaver::~TempFileSaver() QFile::remove(m_fileName); } +/*! \class Utils::FileName + + \brief A light-weight convenience class for filenames + + On windows filenames are compared case insensitively. +*/ + + #ifdef Q_OS_WIN Qt::CaseSensitivity FileName::cs = Qt::CaseInsensitive; #else @@ -419,31 +427,62 @@ FileName::FileName() } +/// Constructs a FileName from \a info FileName::FileName(const QFileInfo &info) : QString(info.absoluteFilePath()) { } +/// \returns a QFileInfo +QFileInfo FileName::toFileInfo() const +{ + return QFileInfo(*this); +} + +/// \returns a QString for passing on to QString based APIs QString FileName::toString() const { return QString(*this); } +/// \returns a QString to display to the user +/// Converts the separators to the native format +QString FileName::toUserOutput() const +{ + return QDir::toNativeSeparators(toString()); +} + +/// Constructs a FileName from \a fileName +/// \a fileName is not checked for validity. FileName FileName::fromString(const QString &filename) { return FileName(filename); } +/// Constructs a FileName from \a fileName +/// \a fileName is only passed through QDir::cleanPath +/// and QDir::fromNativeSeparators +FileName FileName::fromUserInput(const QString &filename) +{ + return FileName(QDir::cleanPath(QDir::fromNativeSeparators(filename))); +} + FileName::FileName(const QString &string) : QString(string) { } + bool FileName::operator==(const FileName &other) const { return QString::compare(*this, other, cs) == 0; } +bool FileName::operator!=(const FileName &other) const +{ + return !(*this == other); +} + bool FileName::operator<(const FileName &other) const { return QString::compare(*this, other, cs) < 0; @@ -464,29 +503,38 @@ bool FileName::operator>=(const FileName &other) const return other <= *this; } -bool FileName::startsWith(const QString &s) const +/// \returns whether FileName is a child of \a s +bool FileName::isChildOf(const FileName &s) const { - return QString::startsWith(s, cs); + if (!QString::startsWith(s, cs)) + return false; + if (size() <= s.size()) + return false; + return at(s.size()) == '/'; } +/// \returns whether FileName endsWith \a s bool FileName::endsWith(const QString &s) const { return QString::endsWith(s, cs); } -FileName FileName::left(int n) const -{ - return FileName(QString::left(n)); -} - -FileName FileName::mid(int position, int n) const +/// \returns the relativeChildPath of FileName to parent if FileName is a child of parent +/// \note returns a empty FileName if FileName is not a child of parent +/// That is, this never returns a path starting with "../" +FileName FileName::relativeChildPath(const FileName &parent) const { - return FileName(QString::mid(position, n)); + if (!isChildOf(parent)) + return Utils::FileName(); + return FileName(QString::mid(parent.size() + 1, -1)); } -FileName FileName::right(int n) const +/// Appends \a s, ensuring a / between the parts +void FileName::appendPath(const QString &s) { - return FileName(QString::right(n)); + if (QString::endsWith(QLatin1Char('/'))) + append(QLatin1Char('/')); + append(s); } } // namespace Utils diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index 90c8f47dfa9..308d9199cc2 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -39,6 +39,7 @@ #include <QtCore/QIODevice> #include <QtCore/QXmlStreamWriter> // Mac. #include <QtCore/QFileInfo> +#include <QtCore/QMetaType> QT_BEGIN_NAMESPACE class QFile; @@ -145,26 +146,32 @@ class QTCREATOR_UTILS_EXPORT FileName : private QString public: FileName(); explicit FileName(const QFileInfo &info); - QString toString() const; + QFileInfo toFileInfo() const; static FileName fromString(const QString &filename); + static FileName fromUserInput(const QString &filename); + QString toString() const; + QString toUserOutput() const; bool operator==(const FileName &other) const; + bool operator!=(const FileName &other) const; bool operator<(const FileName &other) const; bool operator<=(const FileName &other) const; bool operator>(const FileName &other) const; bool operator>=(const FileName &other) const; - bool startsWith(const QString &s) const; + bool isChildOf(const FileName &s) const; bool endsWith(const QString &s) const; - FileName left(int n) const Q_REQUIRED_RESULT; - FileName mid(int position, int n = -1) const Q_REQUIRED_RESULT; - FileName right(int n) const Q_REQUIRED_RESULT; + Utils::FileName relativeChildPath(const FileName &parent) const; + void appendPath(const QString &s); using QString::size; using QString::count; using QString::length; using QString::isEmpty; + using QString::isNull; + using QString::clear; + using QString::append; private: static Qt::CaseSensitivity cs; FileName(const QString &string); @@ -176,4 +183,6 @@ QT_BEGIN_NAMESPACE QTCREATOR_UTILS_EXPORT uint qHash(const Utils::FileName &a); QT_END_NAMESPACE +Q_DECLARE_METATYPE(Utils::FileName) + #endif // FILEUTILS_H diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index fe0c3b8207d..1819417d907 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -309,14 +309,13 @@ struct InternalNode void create(const QString &projectDir, const QSet<Utils::FileName> &newFilePaths, ProjectExplorer::FileType type) { static const QChar separator = QChar('/'); - const QString projectDirWithSeparator = projectDir + separator; - int projectDirWithSeparatorLength = projectDirWithSeparator.length(); + const Utils::FileName projectDirFileName = Utils::FileName::fromString(projectDir); foreach (const Utils::FileName &file, newFilePaths) { Utils::FileName fileWithoutPrefix; bool isRelative; - if (file.startsWith(projectDirWithSeparator)) { + if (file.isChildOf(projectDirFileName)) { isRelative = true; - fileWithoutPrefix = file.mid(projectDirWithSeparatorLength); + fileWithoutPrefix = file.relativeChildPath(projectDirFileName); } else { isRelative = false; fileWithoutPrefix = file; @@ -328,7 +327,7 @@ struct InternalNode #endif QStringListIterator it(parts); InternalNode *currentNode = this; - QString path = (isRelative ? projectDirWithSeparator : ""); + QString path = (isRelative ? (projectDirFileName.toString() + '/') : QString("")); while (it.hasNext()) { const QString &key = it.next(); if (it.hasNext()) { // key is directory @@ -683,7 +682,7 @@ void Qt4PriFileNode::folderChanged(const QString &folder) newFiles += recursiveEnumerate(changedFolder); foreach (const Utils::FileName &file, m_recursiveEnumerateFiles) { - if (!file.startsWith(changedFolder)) + if (!file.isChildOf(Utils::FileName::fromString(changedFolder))) newFiles.insert(file); } -- GitLab