Fix "open terminal with environment" functionality

... for RemoteLinux. We now open a *remote* terminal, as we should.

Change-Id: I84f73bbfcb6132717a30f5ef7c8d9d56d854a609
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2019-05-21 18:15:29 +02:00
parent 0a555018d1
commit 6fa474ead8
7 changed files with 76 additions and 29 deletions

View File

@@ -53,6 +53,7 @@ public:
explicit EnvironmentAspectWidget(EnvironmentAspect *aspect, QWidget *additionalWidget = nullptr);
virtual EnvironmentAspect *aspect() const;
EnvironmentWidget *envWidget() const { return m_environmentWidget; }
QWidget *additionalWidget() const;

View File

@@ -127,6 +127,7 @@ public:
Utils::EnvironmentModel *m_model;
QString m_baseEnvironmentText;
EnvironmentWidget::OpenTerminalFunc m_openTerminalFunc;
Utils::DetailsWidget *m_detailsContainer;
QTreeView *m_environmentView;
QPushButton *m_editButton;
@@ -227,6 +228,7 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
d->m_terminalButton = new QPushButton(this);
d->m_terminalButton->setText(tr("Open &Terminal"));
d->m_terminalButton->setToolTip(tr("Open a terminal with this environment set up."));
d->m_terminalButton->setEnabled(type == TypeLocal);
buttonLayout->addWidget(d->m_terminalButton);
buttonLayout->addStretch();
@@ -251,7 +253,14 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi
connect(d->m_environmentView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &EnvironmentWidget::environmentCurrentIndexChanged);
connect(d->m_terminalButton, &QAbstractButton::clicked,
this, &EnvironmentWidget::openTerminal);
this, [this] {
Utils::Environment env = d->m_model->baseEnvironment();
env.modify(d->m_model->userChanges());
if (d->m_openTerminalFunc)
d->m_openTerminalFunc(env);
else
Core::FileUtils::openTerminal(QDir::currentPath(), env);
});
connect(d->m_detailsContainer, &Utils::DetailsWidget::linkActivated,
this, &EnvironmentWidget::linkActivated);
@@ -303,6 +312,12 @@ void EnvironmentWidget::setUserChanges(const QList<Utils::EnvironmentItem> &list
updateSummaryText();
}
void EnvironmentWidget::setOpenTerminalFunc(const EnvironmentWidget::OpenTerminalFunc &func)
{
d->m_openTerminalFunc = func;
d->m_terminalButton->setEnabled(bool(func));
}
void EnvironmentWidget::updateSummaryText()
{
QList<Utils::EnvironmentItem> list = d->m_model->userChanges();
@@ -450,13 +465,6 @@ void EnvironmentWidget::batchEditEnvironmentButtonClicked()
d->m_model->setUserChanges(newChanges);
}
void EnvironmentWidget::openTerminal()
{
Utils::Environment env = d->m_model->baseEnvironment();
env.modify(d->m_model->userChanges());
Core::FileUtils::openTerminal(QDir::currentPath(), env);
}
void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &current)
{
if (current.isValid()) {

View File

@@ -59,6 +59,9 @@ public:
QList<Utils::EnvironmentItem> userChanges() const;
void setUserChanges(const QList<Utils::EnvironmentItem> &list);
using OpenTerminalFunc = std::function<void(const Utils::Environment &env)>;
void setOpenTerminalFunc(const OpenTerminalFunc &func);
signals:
void userChangesChanged();
void detailsVisibleChanged(bool visible);
@@ -71,7 +74,6 @@ private:
void appendPathButtonClicked();
void prependPathButtonClicked();
void batchEditEnvironmentButtonClicked();
void openTerminal();
void environmentCurrentIndexChanged(const QModelIndex &current);
void invalidateCurrentIndex();
void updateSummaryText();

View File

@@ -44,6 +44,7 @@
#include <ssh/sshremoteprocessrunner.h>
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/port.h>
#include <utils/qtcassert.h>
@@ -197,24 +198,7 @@ LinuxDevice::LinuxDevice()
if (Utils::HostOsInfo::isAnyUnixHost()) {
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
DeviceProcess * const proc = device->createProcess(nullptr);
QObject::connect(proc, &DeviceProcess::finished, [proc] {
if (!proc->errorString().isEmpty()) {
Core::MessageManager::write(tr("Error running remote shell: %1")
.arg(proc->errorString()),
Core::MessageManager::ModeSwitch);
}
proc->deleteLater();
});
QObject::connect(proc, &DeviceProcess::error, [proc] {
Core::MessageManager::write(tr("Error starting remote shell."),
Core::MessageManager::ModeSwitch);
proc->deleteLater();
});
Runnable runnable;
runnable.device = device;
proc->setRunInTerminal(true);
proc->start(runnable);
device.staticCast<LinuxDevice>()->startRemoteShell(Utils::Environment());
}});
}
}
@@ -284,6 +268,35 @@ bool LinuxDevice::supportsRSync() const
return extraData("RemoteLinux.SupportsRSync").toBool();
}
void LinuxDevice::startRemoteShell(const Utils::Environment &env) const
{
DeviceProcess * const proc = createProcess(nullptr);
QObject::connect(proc, &DeviceProcess::finished, [proc] {
if (!proc->errorString().isEmpty()) {
Core::MessageManager::write(tr("Error running remote shell: %1")
.arg(proc->errorString()),
Core::MessageManager::ModeSwitch);
}
proc->deleteLater();
});
QObject::connect(proc, &DeviceProcess::error, [proc] {
Core::MessageManager::write(tr("Error starting remote shell."),
Core::MessageManager::ModeSwitch);
proc->deleteLater();
});
Runnable runnable;
runnable.device = sharedFromThis();
runnable.environment = env;
// It seems we cannot pass an environment to OpenSSH dynamically
// without specifying an executable.
if (env.size() > 0)
runnable.executable = "/bin/sh";
proc->setRunInTerminal(true);
proc->start(runnable);
}
namespace Internal {

View File

@@ -32,6 +32,8 @@
#include <QCoreApplication>
namespace Utils { class Environment; }
namespace RemoteLinux {
class REMOTELINUX_EXPORT LinuxDevice : public ProjectExplorer::IDevice
@@ -62,6 +64,8 @@ public:
void setSupportsRsync(bool supportsRsync);
bool supportsRSync() const;
void startRemoteShell(const Utils::Environment &env) const;
protected:
LinuxDevice();
};

View File

@@ -99,7 +99,8 @@ QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const
if (!envString.isEmpty())
fullCommandLine.append(envString);
if (!runInTerminal())
fullCommandLine.append(" exec ");
fullCommandLine.append(" exec");
fullCommandLine.append(' ');
fullCommandLine.append(quote(runnable.executable));
if (!runnable.commandLineArguments.isEmpty()) {
fullCommandLine.append(QLatin1Char(' '));

View File

@@ -25,11 +25,15 @@
#include "remotelinuxenvironmentaspectwidget.h"
#include "linuxdevice.h"
#include "remotelinuxrunconfiguration.h"
#include "remotelinuxenvironmentreader.h"
#include <projectexplorer/target.h>
#include <coreplugin/icore.h>
#include <projectexplorer/environmentwidget.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
#include <QMessageBox>
@@ -63,6 +67,20 @@ RemoteLinuxEnvironmentAspectWidget::RemoteLinuxEnvironmentAspectWidget
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentFinished);
connect(deviceEnvReader, &RemoteLinuxEnvironmentReader::error,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentError);
const EnvironmentWidget::OpenTerminalFunc openTerminalFunc
= [target](const Utils::Environment &env) {
IDevice::ConstPtr device = DeviceKitAspect::device(target->kit());
if (!device) {
QMessageBox::critical(Core::ICore::mainWindow(), tr("Cannot open terminal"),
tr("Cannot open remote terminal: Current kit has no device."));
return;
}
const auto linuxDevice = device.dynamicCast<const LinuxDevice>();
QTC_ASSERT(linuxDevice, return);
linuxDevice->startRemoteShell(env);
};
envWidget()->setOpenTerminalFunc(openTerminalFunc);
}
RemoteLinuxEnvironmentAspect *RemoteLinuxEnvironmentAspectWidget::aspect() const