diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index ba7faea5df1..68917d2af90 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -1720,6 +1720,28 @@ FilePath FilePath::cleanPath() const return withNewPath(doCleanPath(path())); } +/*! + On Linux/Mac replace user's home path with ~ in the \c toString() + result for this path after cleaning. + + If path is not sub of home path, or when running on Windows, returns the input +*/ +QString FilePath::withTildeHomePath() const +{ + if (osType() == OsTypeWindows) + return toString(); + + if (needsDevice()) + return toString(); + + static const QString homePath = QDir::homePath(); + + QString outPath = cleanPath().absoluteFilePath().path(); + if (outPath.startsWith(homePath)) + outPath = '~' + outPath.mid(homePath.size()); + return outPath; +} + QTextStream &operator<<(QTextStream &s, const FilePath &fn) { return s << fn.toString(); diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index ef8762a15c5..77cdd7204fe 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -195,6 +195,8 @@ public: QString displayName(const QString &args = {}) const; QString nativePath() const; QString shortNativePath() const; + QString withTildeHomePath() const; + bool startsWithDriveLetter() const; static QString formatFilePaths(const FilePaths &files, const QString &separator); diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp index e59f784560d..fcbd3d55a2a 100644 --- a/src/libs/utils/stringutils.cpp +++ b/src/libs/utils/stringutils.cpp @@ -73,25 +73,6 @@ QTCREATOR_UTILS_EXPORT QString commonPrefix(const QStringList &strings) return strings.at(0).left(commonLength); } -QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path) -{ - if (HostOsInfo::isWindowsHost()) - return path; - - if (FilePath::fromString(path).needsDevice()) - return path; - - static const QString homePath = QDir::homePath(); - - QFileInfo fi(QDir::cleanPath(path)); - QString outPath = fi.absoluteFilePath(); - if (outPath.startsWith(homePath)) - outPath = '~' + outPath.mid(homePath.size()); - else - outPath = path; - return outPath; -} - static bool validateVarName(const QString &varName) { return !varName.startsWith("JS:"); diff --git a/src/libs/utils/stringutils.h b/src/libs/utils/stringutils.h index 76ebee5c0d7..6583a830a13 100644 --- a/src/libs/utils/stringutils.h +++ b/src/libs/utils/stringutils.h @@ -26,11 +26,6 @@ QTCREATOR_UTILS_EXPORT QString settingsKey(const QString &category); // "C:\foo\bar1" "C:\foo\bar2" -> "C:\foo\bar" QTCREATOR_UTILS_EXPORT QString commonPrefix(const QStringList &strings); -// On Linux/Mac replace user's home path with ~ -// Uses cleaned path and tries to use absolute path of "path" if possible -// If path is not sub of home path, or when running on Windows, returns the input -QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path); - // Removes first unescaped ampersand in text QTCREATOR_UTILS_EXPORT QString stripAccelerator(const QString &text); // Quotes all ampersands diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index bd51c11e165..3acf08591c8 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3476,7 +3476,7 @@ void ProjectExplorerPluginPrivate::updateRecentProjectMenu() continue; const QString actionText = ActionManager::withNumberAccelerator( - Utils::withTildeHomePath(filePath.toUserOutput()), acceleratorKey); + filePath.withTildeHomePath(), acceleratorKey); QAction *action = menu->addAction(actionText); connect(action, &QAction::triggered, this, [this, filePath] { openRecentProject(filePath); diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index 7d948b52675..9b07748fc2e 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -73,7 +73,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const case FilePathRole: return data.first.toVariant(); case PrettyFilePathRole: - return Utils::withTildeHomePath(data.first.toUserOutput()); // FIXME: FilePath::displayName() ? + return data.first.withTildeHomePath(); // FIXME: FilePath::displayName() ? case ShortcutRole: { const Id projectBase = PROJECT_BASE_ID; if (Command *cmd = ActionManager::command(projectBase.withSuffix(index.row() + 1))) @@ -334,7 +334,7 @@ public: yy += 18; // Project path. - QString pathWithTilde = Utils::withTildeHomePath(projectPath.toUserOutput()); + QString pathWithTilde = projectPath.withTildeHomePath(); painter->setPen(foregroundPrimaryColor); painter->drawText(x1, yy, fm.elidedText(pathWithTilde, Qt::ElideMiddle, textSpace)); yy += 22; @@ -485,7 +485,7 @@ public: painter->setPen(themeColor(Theme::Welcome_ForegroundPrimaryColor)); painter->setFont(sizedFont(13, option.widget)); - QString pathWithTilde = Utils::withTildeHomePath(projectPath.toUserOutput()); + QString pathWithTilde = projectPath.withTildeHomePath(); const QString pathWithTildeElided = painter->fontMetrics().elidedText(pathWithTilde, Qt::ElideMiddle, textSpace); painter->drawText(x + TEXT_OFFSET_HORIZONTAL, secondBase, pathWithTildeElided); diff --git a/src/plugins/projectexplorer/sessionmodel.cpp b/src/plugins/projectexplorer/sessionmodel.cpp index 9a28c309bd7..771d8a44785 100644 --- a/src/plugins/projectexplorer/sessionmodel.cpp +++ b/src/plugins/projectexplorer/sessionmodel.cpp @@ -84,7 +84,7 @@ QStringList pathsToBaseNames(const QStringList &paths) QStringList pathsWithTildeHomePath(const QStringList &paths) { return Utils::transform(paths, [](const QString &path) { - return Utils::withTildeHomePath(QDir::toNativeSeparators(path)); + return FilePath::fromString(path).withTildeHomePath(); }); } diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 7ceedd631fd..6f9c8893751 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -396,7 +396,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const case FilePathRole: return data.first.toVariant(); case PrettyFilePathRole: - return Utils::withTildeHomePath(data.first.absolutePath().toUserOutput()); + return data.first.absolutePath().withTildeHomePath(); case PreviewUrl: return QVariant(QStringLiteral("image://project_preview/") + QmlProjectManager::ProjectFileContentTools::appQmlFile( diff --git a/tests/auto/utils/stringutils/tst_stringutils.cpp b/tests/auto/utils/stringutils/tst_stringutils.cpp index 14aba489364..be01c2f1ea6 100644 --- a/tests/auto/utils/stringutils/tst_stringutils.cpp +++ b/tests/auto/utils/stringutils/tst_stringutils.cpp @@ -1,12 +1,15 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +#include #include #include //TESTED_COMPONENT=src/libs/utils +using namespace Utils; + class TestMacroExpander : public Utils::AbstractMacroExpander { public: @@ -77,32 +80,30 @@ private: void tst_StringUtils::testWithTildeHomePath() { + const QString home = QDir::homePath(); + const FilePath homePath = FilePath::fromString(home); + #ifndef Q_OS_WIN // home path itself - QCOMPARE(Utils::withTildeHomePath(QDir::homePath()), QString::fromLatin1("~")); - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QLatin1Char('/')), - QString::fromLatin1("~")); - QCOMPARE(Utils::withTildeHomePath(QString::fromLatin1("/unclean/..") + QDir::homePath()), - QString::fromLatin1("~")); + QCOMPARE(homePath.withTildeHomePath(), QString("~")); + QCOMPARE(homePath.pathAppended("/").withTildeHomePath(), QString("~")); + QCOMPARE(FilePath::fromString("/unclean/../" + home).withTildeHomePath(), QString("~")); // sub of home path - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/foo")), - QString::fromLatin1("~/foo")); - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/foo/")), - QString::fromLatin1("~/foo")); - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/some/path/file.txt")), - QString::fromLatin1("~/some/path/file.txt")); - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/some/unclean/../path/file.txt")), - QString::fromLatin1("~/some/path/file.txt")); + QCOMPARE(homePath.pathAppended("/foo").withTildeHomePath(), QString("~/foo")); + QCOMPARE(homePath.pathAppended("/foo/").withTildeHomePath(), QString("~/foo")); + QCOMPARE(homePath.pathAppended("/some/path/file.txt").withTildeHomePath(), + QString("~/some/path/file.txt")); + QCOMPARE(homePath.pathAppended("/some/unclean/../path/file.txt").withTildeHomePath(), + QString("~/some/path/file.txt")); // not sub of home path - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/../foo")), - QString(QDir::homePath() + QString::fromLatin1("/../foo"))); + QCOMPARE(homePath.pathAppended("/../foo").withTildeHomePath(), + QString(home + "/../foo")); #else // windows: should return same as input - QCOMPARE(Utils::withTildeHomePath(QDir::homePath()), QDir::homePath()); - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/foo")), - QDir::homePath() + QString::fromLatin1("/foo")); - QCOMPARE(Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/../foo")), - Utils::withTildeHomePath(QDir::homePath() + QString::fromLatin1("/../foo"))); + QCOMPARE(homePath.withTildeHomePath(), home); + QCOMPARE(homePath.pathAppended("/foo").withTildeHomePath(), home + QString("/foo")); + QCOMPARE(homePath.pathAppended("/../foo").withTildeHomePath(), + homePath.pathAppended("/../foo").withTildeHomePath()); #endif }