Terminal: Lazily open remote terminals

Move the burden of finding the shell of a device from the shell menu
to the TerminalWidget, so that opening the shell menu does not block
the ui.

Change-Id: I7f2e5a891f20faa53a1e3eec879866219f9bee0b
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-08-10 06:44:27 +02:00
parent d611fe6821
commit 92355bf40d
7 changed files with 60 additions and 38 deletions

View File

@@ -3,6 +3,9 @@
#include "shellmodel.h"
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/filepath.h>
@@ -138,11 +141,10 @@ ShellModelPrivate::ShellModelPrivate()
});
// ... and filter out non-existing shells.
localShells = Utils::transform(
Utils::filtered(shells, [](const FilePath &shell) {return shell.exists(); }),
[&iconProvider](const FilePath &shell) {
return ShellItemBuilder(iconProvider, shell).item();
});
localShells = Utils::transform(Utils::filtered(shells, &FilePath::exists),
[&iconProvider](const FilePath &shell) {
return ShellItemBuilder(iconProvider, shell).item();
});
}
}
@@ -161,14 +163,15 @@ QList<ShellModelItem> ShellModel::local() const
QList<ShellModelItem> ShellModel::remote() const
{
const auto deviceCmds = Utils::Terminal::Hooks::instance().getTerminalCommandsForDevicesHook()();
QList<ShellModelItem> result;
const QList<ShellModelItem> deviceItems = Utils::transform(
deviceCmds, [](const Utils::Terminal::NameAndCommandLine &item) -> ShellModelItem {
return ShellModelItem{item.name, {item.commandLine}};
ProjectExplorer::DeviceManager::instance()->forEachDevice(
[&result](const QSharedPointer<const ProjectExplorer::IDevice> &device) {
if (device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
result << ShellModelItem{device->displayName(), {{device->rootPath(), {}}}};
});
return deviceItems;
return result;
}
} // namespace Terminal::Internal

View File

@@ -16,6 +16,7 @@
#include <coreplugin/messagemanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
@@ -82,6 +83,33 @@ void TerminalWidget::setupPty()
CommandLine shellCommand = m_openParameters.shellCommand.value_or(
CommandLine{settings().shell(), settings().shellArguments(), CommandLine::Raw});
if (shellCommand.executable().isRootPath()) {
writeToTerminal(Tr::tr("Connecting ...\r\n").toUtf8(), true);
// We still have to find the shell to start ...
m_findShellWatcher.reset(new QFutureWatcher<FilePath>());
connect(m_findShellWatcher.get(), &QFutureWatcher<FilePath>::finished, this, [this] {
const FilePath result = m_findShellWatcher->result();
if (!result.isEmpty()) {
m_openParameters.shellCommand->setExecutable(m_findShellWatcher->result());
restart(m_openParameters);
return;
}
writeToTerminal(
("\r\n\033[31m" + Tr::tr("Could not find shell to start.") + "\r\n").toUtf8(), true);
});
m_findShellWatcher->setFuture(Utils::asyncRun([shellCommand] {
const FilePath result = Utils::Terminal::defaultShellForDevice(
shellCommand.executable());
if (result.isExecutableFile())
return result;
return FilePath{};
}));
return;
}
Environment env = m_openParameters.environment.value_or(Environment{})
.appliedToEnvironment(shellCommand.executable().deviceEnvironment());

View File

@@ -16,6 +16,10 @@
#include <utils/process.h>
#include <utils/terminalhooks.h>
#include <QFutureWatcher>
#include <memory>
namespace Terminal {
using RegisteredAction = std::unique_ptr<QAction, std::function<void(QAction *)>>;
@@ -105,6 +109,8 @@ private:
RegisteredAction m_close;
Internal::ShortcutMap m_shortcutMap;
std::unique_ptr<QFutureWatcher<Utils::FilePath>> m_findShellWatcher;
};
} // namespace Terminal