// 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 "terminalhooks.h" #include "externalterminalprocessimpl.h" #include "filepath.h" #include "qtcprocess.h" #include "utilstr.h" #include namespace Utils::Terminal { Result defaultShellForDevice(const FilePath &deviceRoot) { if (deviceRoot.osType() == OsTypeWindows) return deviceRoot.withNewPath("cmd.exe").searchInPath(); const Result env = deviceRoot.deviceEnvironmentWithError(); if (!env) return ResultError(env.error()); FilePath shell = FilePath::fromUserInput(env->value_or("SHELL", "/bin/sh")); if (!shell.isAbsolutePath()) shell = env->searchInPath(shell.nativePath()); if (shell.isEmpty()) return ResultError(Tr::tr("Could not find any shell.")); return deviceRoot.withNewMappedPath(shell); } class HooksPrivate { public: HooksPrivate() { auto openTerminal = [](const OpenTerminalParameters ¶meters) { parameters.workingDirectory.value_or(FilePath{}) .openTerminal(parameters.environment.value_or(Environment{})); }; auto createProcessInterface = [] { return new ExternalTerminalProcessImpl; }; addCallbackSet("External", {openTerminal, createProcessInterface}); } void addCallbackSet(const QString &name, const Hooks::CallbackSet &callbackSet) { QMutexLocker lk(&m_mutex); m_callbackSets.push_back(qMakePair(name, callbackSet)); m_createTerminalProcessInterface = m_callbackSets.back().second.createTerminalProcessInterface; m_openTerminal = m_callbackSets.back().second.openTerminal; } void removeCallbackSet(const QString &name) { if (name == "External") return; QMutexLocker lk(&m_mutex); m_callbackSets.removeIf([name](const auto &pair) { return pair.first == name; }); m_createTerminalProcessInterface = m_callbackSets.back().second.createTerminalProcessInterface; m_openTerminal = m_callbackSets.back().second.openTerminal; } Hooks::CreateTerminalProcessInterface createTerminalProcessInterface() { QMutexLocker lk(&m_mutex); return m_createTerminalProcessInterface; } Hooks::OpenTerminal openTerminal() { QMutexLocker lk(&m_mutex); return m_openTerminal; } private: Hooks::OpenTerminal m_openTerminal; Hooks::CreateTerminalProcessInterface m_createTerminalProcessInterface; QMutex m_mutex; QList> m_callbackSets; }; Hooks &Hooks::instance() { static Hooks manager; return manager; } Hooks::Hooks() : d(new HooksPrivate()) {} Hooks::~Hooks() = default; void Hooks::openTerminal(const OpenTerminalParameters ¶meters) const { d->openTerminal()(parameters); } ProcessInterface *Hooks::createTerminalProcessInterface() const { return d->createTerminalProcessInterface()(); } void Hooks::addCallbackSet(const QString &name, const CallbackSet &callbackSet) { d->addCallbackSet(name, callbackSet); } void Hooks::removeCallbackSet(const QString &name) { d->removeCallbackSet(name); } } // namespace Utils::Terminal