forked from qt-creator/qt-creator
Utils: Integrate ptyqt into qtcprocess
Integrating PtyQt directly into QtcProcess allows us to start Pseudo terminal processes using the existing QtcProcess functionality such as starting remote process on e.g. docker or remote linux devices. This is needed for the new Terminal plugin. Change-Id: Iaeed5ff9b341ba4646d955b2ed9577a18cd7100f Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
@@ -15,11 +15,11 @@
|
||||
#include <utils/processinterface.h>
|
||||
#include <utils/stringutils.h>
|
||||
|
||||
#include <ptyqt.h>
|
||||
#include <vterm.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QElapsedTimer>
|
||||
#include <QGlyphRun>
|
||||
#include <QLoggingCategory>
|
||||
#include <QPaintEvent>
|
||||
@@ -69,7 +69,7 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op
|
||||
m_readDelayTimer.setSingleShot(true);
|
||||
m_readDelayTimer.setInterval(10);
|
||||
|
||||
connect(&m_readDelayTimer, &QTimer::timeout, this, [this]() {
|
||||
connect(&m_readDelayTimer, &QTimer::timeout, this, [this] {
|
||||
m_readDelayRestarts = 0;
|
||||
onReadyRead();
|
||||
});
|
||||
@@ -80,7 +80,7 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op
|
||||
connect(&m_zoomInAction, &QAction::triggered, this, &TerminalWidget::zoomIn);
|
||||
connect(&m_zoomOutAction, &QAction::triggered, this, &TerminalWidget::zoomOut);
|
||||
|
||||
connect(&TerminalSettings::instance(), &AspectContainer::applied, this, [this]() {
|
||||
connect(&TerminalSettings::instance(), &AspectContainer::applied, this, [this] {
|
||||
m_layoutVersion++;
|
||||
// Setup colors first, as setupFont will redraw the screen.
|
||||
setupColors();
|
||||
@@ -90,7 +90,7 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op
|
||||
|
||||
void TerminalWidget::setupPty()
|
||||
{
|
||||
m_ptyProcess.reset(PtyQt::createPtyProcess(IPtyProcess::PtyType::AutoPty));
|
||||
m_process = std::make_unique<QtcProcess>();
|
||||
|
||||
Environment env = m_openParameters.environment.value_or(Environment::systemEnvironment());
|
||||
|
||||
@@ -99,29 +99,17 @@ void TerminalWidget::setupPty()
|
||||
|
||||
// For git bash on Windows
|
||||
env.prependOrSetPath(shellCommand.executable().parentDir());
|
||||
if (env.hasKey("CLINK_NOAUTORUN"))
|
||||
env.unset("CLINK_NOAUTORUN");
|
||||
|
||||
QStringList envList = filtered(env.toStringList(), [](const QString &envPair) {
|
||||
return envPair != "CLINK_NOAUTORUN=1";
|
||||
});
|
||||
m_process->setProcessMode(ProcessMode::Writer);
|
||||
m_process->setTerminalMode(TerminalMode::Pty);
|
||||
m_process->setCommand(shellCommand);
|
||||
m_process->setWorkingDirectory(
|
||||
m_openParameters.workingDirectory.value_or(FilePath::fromString(QDir::homePath())));
|
||||
m_process->setEnvironment(env);
|
||||
|
||||
m_ptyProcess->startProcess(shellCommand.executable().nativePath(),
|
||||
shellCommand.splitArguments(),
|
||||
m_openParameters.workingDirectory
|
||||
.value_or(FilePath::fromString(QDir::homePath()))
|
||||
.nativePath(),
|
||||
envList,
|
||||
m_vtermSize.width(),
|
||||
m_vtermSize.height());
|
||||
|
||||
emit started(m_ptyProcess->pid());
|
||||
|
||||
if (!m_ptyProcess->lastError().isEmpty()) {
|
||||
qCWarning(terminalLog) << m_ptyProcess->lastError();
|
||||
m_ptyProcess.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(m_ptyProcess->notifier(), &QIODevice::readyRead, this, [this]() {
|
||||
connect(m_process.get(), &QtcProcess::readyReadStandardOutput, this, [this] {
|
||||
if (m_readDelayTimer.isActive())
|
||||
m_readDelayRestarts++;
|
||||
|
||||
@@ -131,16 +119,19 @@ void TerminalWidget::setupPty()
|
||||
m_readDelayTimer.start();
|
||||
});
|
||||
|
||||
connect(m_ptyProcess->notifier(), &QIODevice::aboutToClose, this, [this]() {
|
||||
connect(m_process.get(), &QtcProcess::done, this, [this] {
|
||||
m_cursor.visible = false;
|
||||
if (m_ptyProcess) {
|
||||
if (m_process) {
|
||||
onReadyRead();
|
||||
|
||||
if (m_ptyProcess->exitCode() != 0) {
|
||||
if (m_process->exitCode() != 0) {
|
||||
QByteArray msg = QString("\r\n\033[31mProcess exited with code: %1")
|
||||
.arg(m_ptyProcess->exitCode())
|
||||
.arg(m_process->exitCode())
|
||||
.toUtf8();
|
||||
|
||||
if (!m_process->errorString().isEmpty())
|
||||
msg += QString(" (%1)").arg(m_process->errorString()).toUtf8();
|
||||
|
||||
vterm_input_write(m_vterm.get(), msg.constData(), msg.size());
|
||||
vterm_screen_flush_damage(m_vtermScreen);
|
||||
|
||||
@@ -149,10 +140,8 @@ void TerminalWidget::setupPty()
|
||||
}
|
||||
|
||||
if (m_openParameters.m_exitBehavior == ExitBehavior::Restart) {
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this]() {
|
||||
m_ptyProcess.reset();
|
||||
QMetaObject::invokeMethod(this, [this] {
|
||||
m_process.reset();
|
||||
setupPty();
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
@@ -163,13 +152,20 @@ void TerminalWidget::setupPty()
|
||||
|
||||
if (m_openParameters.m_exitBehavior == ExitBehavior::Keep) {
|
||||
QByteArray msg = QString("\r\nProcess exited with code: %1")
|
||||
.arg(m_ptyProcess ? m_ptyProcess->exitCode() : -1)
|
||||
.arg(m_process ? m_process->exitCode() : -1)
|
||||
.toUtf8();
|
||||
|
||||
vterm_input_write(m_vterm.get(), msg.constData(), msg.size());
|
||||
vterm_screen_flush_damage(m_vtermScreen);
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_process.get(), &QtcProcess::started, this, [this] {
|
||||
applySizeChange();
|
||||
emit started(m_process->processId());
|
||||
});
|
||||
|
||||
m_process->start();
|
||||
}
|
||||
|
||||
void TerminalWidget::setupFont()
|
||||
@@ -229,8 +225,8 @@ void TerminalWidget::setupColors()
|
||||
|
||||
void TerminalWidget::writeToPty(const QByteArray &data)
|
||||
{
|
||||
if (m_ptyProcess)
|
||||
m_ptyProcess->write(data);
|
||||
if (m_process)
|
||||
m_process->writeRaw(data);
|
||||
}
|
||||
|
||||
void TerminalWidget::setupVTerm()
|
||||
@@ -305,7 +301,7 @@ void TerminalWidget::setFont(const QFont &font)
|
||||
|
||||
QAbstractScrollArea::setFont(m_font);
|
||||
|
||||
if (m_ptyProcess) {
|
||||
if (m_process) {
|
||||
applySizeChange();
|
||||
}
|
||||
}
|
||||
@@ -425,7 +421,7 @@ void TerminalWidget::clearContents()
|
||||
|
||||
void TerminalWidget::onReadyRead()
|
||||
{
|
||||
QByteArray data = m_ptyProcess->readAll();
|
||||
QByteArray data = m_process->readAllRawStandardOutput();
|
||||
vterm_input_write(m_vterm.get(), data.constData(), data.size());
|
||||
vterm_screen_flush_damage(m_vtermScreen);
|
||||
}
|
||||
@@ -709,8 +705,8 @@ void TerminalWidget::applySizeChange()
|
||||
if (m_vtermSize.width() <= 0)
|
||||
m_vtermSize.setWidth(1);
|
||||
|
||||
if (m_ptyProcess)
|
||||
m_ptyProcess->resize(m_vtermSize.width(), m_vtermSize.height());
|
||||
if (m_process)
|
||||
m_process->ptyData().resize(m_vtermSize);
|
||||
|
||||
vterm_set_size(m_vterm.get(), m_vtermSize.height(), m_vtermSize.width());
|
||||
vterm_screen_flush_damage(m_vtermScreen);
|
||||
@@ -869,7 +865,7 @@ void TerminalWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
if (!m_ptyProcess)
|
||||
if (!m_process)
|
||||
setupPty();
|
||||
|
||||
QAbstractScrollArea::showEvent(event);
|
||||
|
||||
Reference in New Issue
Block a user