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); explicit EnvironmentAspectWidget(EnvironmentAspect *aspect, QWidget *additionalWidget = nullptr);
virtual EnvironmentAspect *aspect() const; virtual EnvironmentAspect *aspect() const;
EnvironmentWidget *envWidget() const { return m_environmentWidget; }
QWidget *additionalWidget() const; QWidget *additionalWidget() const;

View File

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

View File

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

View File

@@ -44,6 +44,7 @@
#include <ssh/sshremoteprocessrunner.h> #include <ssh/sshremoteprocessrunner.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/port.h> #include <utils/port.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -197,24 +198,7 @@ LinuxDevice::LinuxDevice()
if (Utils::HostOsInfo::isAnyUnixHost()) { if (Utils::HostOsInfo::isAnyUnixHost()) {
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) { addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
DeviceProcess * const proc = device->createProcess(nullptr); device.staticCast<LinuxDevice>()->startRemoteShell(Utils::Environment());
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);
}}); }});
} }
} }
@@ -284,6 +268,35 @@ bool LinuxDevice::supportsRSync() const
return extraData("RemoteLinux.SupportsRSync").toBool(); 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 { namespace Internal {

View File

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

View File

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

View File

@@ -25,11 +25,15 @@
#include "remotelinuxenvironmentaspectwidget.h" #include "remotelinuxenvironmentaspectwidget.h"
#include "linuxdevice.h"
#include "remotelinuxrunconfiguration.h" #include "remotelinuxrunconfiguration.h"
#include "remotelinuxenvironmentreader.h" #include "remotelinuxenvironmentreader.h"
#include <projectexplorer/target.h> #include <coreplugin/icore.h>
#include <projectexplorer/environmentwidget.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QMessageBox> #include <QMessageBox>
@@ -63,6 +67,20 @@ RemoteLinuxEnvironmentAspectWidget::RemoteLinuxEnvironmentAspectWidget
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentFinished); this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentFinished);
connect(deviceEnvReader, &RemoteLinuxEnvironmentReader::error, connect(deviceEnvReader, &RemoteLinuxEnvironmentReader::error,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentError); 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 RemoteLinuxEnvironmentAspect *RemoteLinuxEnvironmentAspectWidget::aspect() const