diff options
Diffstat (limited to 'src/plugins/terminal/shellmodel.cpp')
-rw-r--r-- | src/plugins/terminal/shellmodel.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/plugins/terminal/shellmodel.cpp b/src/plugins/terminal/shellmodel.cpp new file mode 100644 index 00000000000..b4cf53a1e99 --- /dev/null +++ b/src/plugins/terminal/shellmodel.cpp @@ -0,0 +1,110 @@ +// Copyright (C) 2022 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 "shellmodel.h" + +#include <utils/algorithm.h> +#include <utils/environment.h> +#include <utils/filepath.h> + +#include <QFileIconProvider> +#include <QStandardPaths> + +namespace Terminal::Internal { + +using namespace Utils; + +FilePaths availableShells() +{ + if (Utils::HostOsInfo::isWindowsHost()) { + FilePaths shells; + + FilePath comspec = FilePath::fromUserInput(qtcEnvironmentVariable("COMSPEC")); + shells << comspec; + + if (comspec.fileName() != "cmd.exe") { + FilePath cmd = FilePath::fromUserInput(QStandardPaths::findExecutable("cmd.exe")); + shells << cmd; + } + + FilePath powershell = FilePath::fromUserInput( + QStandardPaths::findExecutable("powershell.exe")); + if (powershell.exists()) + shells << powershell; + + FilePath bash = FilePath::fromUserInput(QStandardPaths::findExecutable("bash.exe")); + if (bash.exists()) + shells << bash; + + FilePath git_bash = FilePath::fromUserInput(QStandardPaths::findExecutable("git.exe")); + if (git_bash.exists()) + shells << git_bash.parentDir().parentDir().pathAppended("usr/bin/bash.exe"); + + FilePath msys2_bash = FilePath::fromUserInput(QStandardPaths::findExecutable("msys2.exe")); + if (msys2_bash.exists()) + shells << msys2_bash.parentDir().pathAppended("usr/bin/bash.exe"); + + return shells; + } else { + FilePath shellsFile = FilePath::fromString("/etc/shells"); + const auto shellFileContent = shellsFile.fileContents(); + QTC_ASSERT_EXPECTED(shellFileContent, return {}); + + QString shellFileContentString = QString::fromUtf8(*shellFileContent); + + // Filter out comments ... + const QStringList lines + = Utils::filtered(shellFileContentString.split('\n', Qt::SkipEmptyParts), + [](const QString &line) { return !line.trimmed().startsWith('#'); }); + + // Convert lines to file paths ... + const FilePaths shells = Utils::transform(lines, [](const QString &line) { + return FilePath::fromUserInput(line.trimmed()); + }); + + // ... and filter out non-existing shells. + return Utils::filtered(shells, [](const FilePath &shell) { return shell.exists(); }); + } +} + +struct ShellModelPrivate +{ + QList<ShellModelItem> localShells; +}; + +ShellModel::ShellModel(QObject *parent) + : QObject(parent) + , d(new ShellModelPrivate()) +{ + QFileIconProvider iconProvider; + + const FilePaths shells = availableShells(); + for (const FilePath &shell : shells) { + ShellModelItem item; + item.icon = iconProvider.icon(shell.toFileInfo()); + item.name = shell.toUserOutput(); + item.openParameters.shellCommand = {shell, {}}; + d->localShells << item; + } +} + +ShellModel::~ShellModel() = default; + +QList<ShellModelItem> ShellModel::local() const +{ + return d->localShells; +} + +QList<ShellModelItem> ShellModel::remote() const +{ + const auto deviceCmds = Utils::Terminal::Hooks::instance().getTerminalCommandsForDevicesHook()(); + + const QList<ShellModelItem> deviceItems = Utils::transform( + deviceCmds, [](const Utils::Terminal::NameAndCommandLine &item) -> ShellModelItem { + return ShellModelItem{item.name, {}, {item.commandLine, std::nullopt, std::nullopt}}; + }); + + return deviceItems; +} + +} // namespace Terminal::Internal |