diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 1583316832b..04276a610b9 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -732,7 +732,7 @@ public: if (m_setup.m_ptyData) return new PtyProcessImpl; if (m_setup.m_terminalMode != TerminalMode::Off) - return Terminal::Hooks::instance().createTerminalProcessInterfaceHook()(); + return Terminal::Hooks::instance().createTerminalProcessInterface(); const ProcessImpl impl = m_setup.m_processImpl == ProcessImpl::Default ? defaultProcessImpl() : m_setup.m_processImpl; diff --git a/src/libs/utils/terminalhooks.cpp b/src/libs/utils/terminalhooks.cpp index 6ee46b33616..6922f5c4304 100644 --- a/src/libs/utils/terminalhooks.cpp +++ b/src/libs/utils/terminalhooks.cpp @@ -8,6 +8,7 @@ #include "terminalcommand.h" #include "terminalinterface.h" +#include #include namespace Utils::Terminal { @@ -88,21 +89,65 @@ public: ExternalTerminalProcessImpl() { setStubCreator(new ProcessStubCreator(this)); } }; -struct HooksPrivate +class HooksPrivate { +public: HooksPrivate() - : m_openTerminalHook([](const OpenTerminalParameters ¶meters) { + : m_getTerminalCommandsForDevicesHook([] { return QList{}; }) + { + auto openTerminal = [](const OpenTerminalParameters ¶meters) { DeviceFileHooks::instance().openTerminal(parameters.workingDirectory.value_or( FilePath{}), parameters.environment.value_or(Environment{})); - }) - , m_createTerminalProcessInterfaceHook([] { return new ExternalTerminalProcessImpl(); }) - , m_getTerminalCommandsForDevicesHook([] { return QList{}; }) - {} + }; + 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; + } - Hooks::OpenTerminalHook m_openTerminalHook; - Hooks::CreateTerminalProcessInterfaceHook m_createTerminalProcessInterfaceHook; Hooks::GetTerminalCommandsForDevicesHook m_getTerminalCommandsForDevicesHook; + +private: + Hooks::OpenTerminal m_openTerminal; + Hooks::CreateTerminalProcessInterface m_createTerminalProcessInterface; + + QMutex m_mutex; + QList> m_callbackSets; }; Hooks &Hooks::instance() @@ -117,14 +162,14 @@ Hooks::Hooks() Hooks::~Hooks() = default; -Hooks::OpenTerminalHook &Hooks::openTerminalHook() +void Hooks::openTerminal(const OpenTerminalParameters ¶meters) const { - return d->m_openTerminalHook; + d->openTerminal()(parameters); } -Hooks::CreateTerminalProcessInterfaceHook &Hooks::createTerminalProcessInterfaceHook() +ProcessInterface *Hooks::createTerminalProcessInterface() const { - return d->m_createTerminalProcessInterfaceHook; + return d->createTerminalProcessInterface()(); } Hooks::GetTerminalCommandsForDevicesHook &Hooks::getTerminalCommandsForDevicesHook() @@ -132,4 +177,14 @@ Hooks::GetTerminalCommandsForDevicesHook &Hooks::getTerminalCommandsForDevicesHo return d->m_getTerminalCommandsForDevicesHook; } +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 diff --git a/src/libs/utils/terminalhooks.h b/src/libs/utils/terminalhooks.h index 2da470d1711..5a614400f4f 100644 --- a/src/libs/utils/terminalhooks.h +++ b/src/libs/utils/terminalhooks.h @@ -37,7 +37,7 @@ private: }; namespace Terminal { -struct HooksPrivate; +class HooksPrivate; enum class ExitBehavior { Close, Restart, Keep }; @@ -61,18 +61,29 @@ QTCREATOR_UTILS_EXPORT FilePath defaultShellForDevice(const FilePath &deviceRoot class QTCREATOR_UTILS_EXPORT Hooks { public: - using OpenTerminalHook = Hook; - using CreateTerminalProcessInterfaceHook = Hook; + using OpenTerminal = std::function; + using CreateTerminalProcessInterface = std::function; + + struct CallbackSet + { + OpenTerminal openTerminal; + CreateTerminalProcessInterface createTerminalProcessInterface; + }; + using GetTerminalCommandsForDevicesHook = Hook>; public: static Hooks &instance(); ~Hooks(); - OpenTerminalHook &openTerminalHook(); - CreateTerminalProcessInterfaceHook &createTerminalProcessInterfaceHook(); GetTerminalCommandsForDevicesHook &getTerminalCommandsForDevicesHook(); + void openTerminal(const OpenTerminalParameters ¶meters) const; + ProcessInterface *createTerminalProcessInterface() const; + + void addCallbackSet(const QString &name, const CallbackSet &callbackSet); + void removeCallbackSet(const QString &name); + private: Hooks(); std::unique_ptr d; diff --git a/src/plugins/coreplugin/fileutils.cpp b/src/plugins/coreplugin/fileutils.cpp index 929ebfe61d3..a48cd34da70 100644 --- a/src/plugins/coreplugin/fileutils.cpp +++ b/src/plugins/coreplugin/fileutils.cpp @@ -106,7 +106,7 @@ void FileUtils::showInFileSystemView(const FilePath &path) void FileUtils::openTerminal(const FilePath &path, const Environment &env) { - Terminal::Hooks::instance().openTerminalHook()({std::nullopt, path, env}); + Terminal::Hooks::instance().openTerminal({std::nullopt, path, env}); } QString FileUtils::msgFindInDirectory() diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 25aae3385c2..6956d7862a3 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3818,7 +3818,7 @@ void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env BuildConfiguration *bc = activeBuildConfiguration(ProjectTree::projectForNode(currentNode)); if (!bc) { - Terminal::Hooks::instance().openTerminalHook()({{}, currentNode->directory(), environment}); + Terminal::Hooks::instance().openTerminal({{}, currentNode->directory(), environment}); return; } @@ -3835,10 +3835,9 @@ void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env const FilePath shell = Terminal::defaultShellForDevice(buildDevice->rootPath()); if (!shell.isEmpty() && buildDevice->rootPath().needsDevice()) { - Terminal::Hooks::instance().openTerminalHook()( - {CommandLine{shell, {}}, workingDir, environment}); + Terminal::Hooks::instance().openTerminal({CommandLine{shell, {}}, workingDir, environment}); } else { - Terminal::Hooks::instance().openTerminalHook()({std::nullopt, workingDir, environment}); + Terminal::Hooks::instance().openTerminal({std::nullopt, workingDir, environment}); } } @@ -3870,11 +3869,10 @@ void ProjectExplorerPluginPrivate::openTerminalHereWithRunEnv() const FilePath shell = Terminal::defaultShellForDevice(device->rootPath()); if (!shell.isEmpty() && device->rootPath().needsDevice()) { - Terminal::Hooks::instance().openTerminalHook()( + Terminal::Hooks::instance().openTerminal( {CommandLine{shell, {}}, workingDir, runnable.environment}); } else { - Terminal::Hooks::instance().openTerminalHook()( - {std::nullopt, workingDir, runnable.environment}); + Terminal::Hooks::instance().openTerminal({std::nullopt, workingDir, runnable.environment}); } } diff --git a/src/plugins/terminal/terminalplugin.cpp b/src/plugins/terminal/terminalplugin.cpp index a3258fcaf0e..409030acd12 100644 --- a/src/plugins/terminal/terminalplugin.cpp +++ b/src/plugins/terminal/terminalplugin.cpp @@ -43,13 +43,34 @@ void TerminalPlugin::extensionsInitialized() m_terminalPane = new TerminalPane(); ExtensionSystem::PluginManager::instance()->addObject(m_terminalPane); - Utils::Terminal::Hooks::instance().openTerminalHook().set( - [this](const Utils::Terminal::OpenTerminalParameters &p) { - m_terminalPane->openTerminal(p); - }); + auto enable = [this] { + Utils::Terminal::Hooks::instance() + .addCallbackSet("Internal", + {[this](const Utils::Terminal::OpenTerminalParameters &p) { + m_terminalPane->openTerminal(p); + }, + [this] { return new TerminalProcessImpl(m_terminalPane); }}); + }; - Utils::Terminal::Hooks::instance().createTerminalProcessInterfaceHook().set( - [this] { return new TerminalProcessImpl(m_terminalPane); }); + auto disable = [] { Utils::Terminal::Hooks::instance().removeCallbackSet("Internal"); }; + + static bool isEnabled = false; + auto settingsChanged = [enable, disable] { + if (isEnabled != TerminalSettings::instance().enableTerminal.value()) { + isEnabled = TerminalSettings::instance().enableTerminal.value(); + if (isEnabled) + enable(); + else + disable(); + } + }; + + QObject::connect(&TerminalSettings::instance(), + &Utils::AspectContainer::applied, + this, + settingsChanged); + + settingsChanged(); } } // namespace Internal diff --git a/src/plugins/terminal/terminalsettings.cpp b/src/plugins/terminal/terminalsettings.cpp index 32d1ff5097e..b43d964320b 100644 --- a/src/plugins/terminal/terminalsettings.cpp +++ b/src/plugins/terminal/terminalsettings.cpp @@ -64,6 +64,13 @@ TerminalSettings::TerminalSettings() setAutoApply(false); setSettingsGroup("Terminal"); + enableTerminal.setSettingsKey("EnableTerminal"); + enableTerminal.setLabelText(Tr::tr("Use internal Terminal")); + enableTerminal.setToolTip( + Tr::tr("If enabled, use the internal terminal when \"Run In Terminal\" is " + "enabled and for \"Open Terminal here\".")); + enableTerminal.setDefaultValue(true); + font.setSettingsKey("FontFamily"); font.setLabelText(Tr::tr("Family:")); font.setHistoryCompleter("Terminal.Fonts.History"); @@ -121,6 +128,7 @@ TerminalSettings::TerminalSettings() registerAspect(&fontSize); registerAspect(&shell); registerAspect(&allowBlinkingCursor); + registerAspect(&enableTerminal); } } // namespace Terminal diff --git a/src/plugins/terminal/terminalsettings.h b/src/plugins/terminal/terminalsettings.h index de5f0a32428..c793bd123a3 100644 --- a/src/plugins/terminal/terminalsettings.h +++ b/src/plugins/terminal/terminalsettings.h @@ -13,13 +13,14 @@ public: static TerminalSettings &instance(); + Utils::BoolAspect enableTerminal; + Utils::StringAspect font; Utils::IntegerAspect fontSize; Utils::StringAspect shell; Utils::ColorAspect foregroundColor; Utils::ColorAspect backgroundColor; - Utils::ColorAspect selectionColor; Utils::ColorAspect colors[16]; diff --git a/src/plugins/terminal/terminalsettingspage.cpp b/src/plugins/terminal/terminalsettingspage.cpp index bf73cddd0f4..9f0544bea37 100644 --- a/src/plugins/terminal/terminalsettingspage.cpp +++ b/src/plugins/terminal/terminalsettingspage.cpp @@ -47,6 +47,9 @@ QWidget *TerminalSettingsPage::widget() // clang-format off Column { + Row { + settings.enableTerminal, st, + }, Group { title(Tr::tr("Font")), Row {