forked from qt-creator/qt-creator
Utils: Merge TerminalProcess into TerminalImpl
Change-Id: I60a03f315e84e17877d4ecd809a994f08934bedf Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -212,62 +212,6 @@ public:
|
|||||||
bool keepRawData = true;
|
bool keepRawData = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TerminalImpl : public ProcessInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TerminalImpl() : m_terminal(this)
|
|
||||||
{
|
|
||||||
connect(&m_terminal, &Internal::TerminalProcess::started,
|
|
||||||
this, &ProcessInterface::started);
|
|
||||||
connect(&m_terminal, &Internal::TerminalProcess::finished,
|
|
||||||
this, &ProcessInterface::finished);
|
|
||||||
connect(&m_terminal, &Internal::TerminalProcess::errorOccurred,
|
|
||||||
this, &ProcessInterface::errorOccurred);
|
|
||||||
}
|
|
||||||
~TerminalImpl() override
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray readAllStandardOutput() override { QTC_CHECK(false); return {}; }
|
|
||||||
QByteArray readAllStandardError() override { QTC_CHECK(false); return {}; }
|
|
||||||
|
|
||||||
void start() override
|
|
||||||
{
|
|
||||||
m_terminal.setProcessImpl(m_setup->m_processImpl);
|
|
||||||
m_terminal.setTerminalMode(m_setup->m_terminalMode);
|
|
||||||
m_terminal.setAbortOnMetaChars(m_setup->m_abortOnMetaChars);
|
|
||||||
m_terminal.setCommand(m_setup->m_commandLine);
|
|
||||||
m_terminal.setWorkingDirectory(m_setup->m_workingDirectory);
|
|
||||||
m_terminal.setEnvironment(m_setup->m_environment);
|
|
||||||
m_terminal.start();
|
|
||||||
}
|
|
||||||
void interrupt() override { m_terminal.interrupt(); }
|
|
||||||
void terminate() override { m_terminal.stopProcess(); }
|
|
||||||
void kill() override { m_terminal.stopProcess(); }
|
|
||||||
void close() override { m_terminal.stopProcess(); }
|
|
||||||
qint64 write(const QByteArray &) override { QTC_CHECK(false); return -1; }
|
|
||||||
|
|
||||||
QProcess::ProcessError error() const override { return m_terminal.error(); }
|
|
||||||
QProcess::ProcessState state() const override { return m_terminal.state(); }
|
|
||||||
qint64 processId() const override { return m_terminal.processId(); }
|
|
||||||
int exitCode() const override { return m_terminal.exitCode(); }
|
|
||||||
QProcess::ExitStatus exitStatus() const override { return m_terminal.exitStatus(); }
|
|
||||||
QString errorString() const override { return m_terminal.errorString(); }
|
|
||||||
void setErrorString(const QString &) override { QTC_CHECK(false); }
|
|
||||||
|
|
||||||
// intentionally no-op without an assert
|
|
||||||
bool waitForStarted(int) override { return false; }
|
|
||||||
bool waitForReadyRead(int) override { QTC_CHECK(false); return false; }
|
|
||||||
// intentionally no-op without an assert
|
|
||||||
bool waitForFinished(int) override { return false; }
|
|
||||||
|
|
||||||
void kickoffProcess() override { m_terminal.kickoffProcess(); }
|
|
||||||
qint64 applicationMainThreadID() const override { return m_terminal.applicationMainThreadID(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Internal::TerminalProcess m_terminal;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DefaultImpl : public ProcessInterface
|
class DefaultImpl : public ProcessInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -81,43 +81,43 @@ static QString modeOption(TerminalMode m)
|
|||||||
|
|
||||||
static QString msgCommChannelFailed(const QString &error)
|
static QString msgCommChannelFailed(const QString &error)
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Cannot set up communication channel: %1").arg(error);
|
return TerminalImpl::tr("Cannot set up communication channel: %1").arg(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgPromptToClose()
|
static QString msgPromptToClose()
|
||||||
{
|
{
|
||||||
// Shown in a terminal which might have a different character set on Windows.
|
// Shown in a terminal which might have a different character set on Windows.
|
||||||
return TerminalProcess::tr("Press <RETURN> to close this window...");
|
return TerminalImpl::tr("Press <RETURN> to close this window...");
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgCannotCreateTempFile(const QString &why)
|
static QString msgCannotCreateTempFile(const QString &why)
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Cannot create temporary file: %1").arg(why);
|
return TerminalImpl::tr("Cannot create temporary file: %1").arg(why);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgCannotWriteTempFile()
|
static QString msgCannotWriteTempFile()
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Cannot write temporary file. Disk full?");
|
return TerminalImpl::tr("Cannot write temporary file. Disk full?");
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgCannotCreateTempDir(const QString & dir, const QString &why)
|
static QString msgCannotCreateTempDir(const QString & dir, const QString &why)
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Cannot create temporary directory \"%1\": %2").arg(dir, why);
|
return TerminalImpl::tr("Cannot create temporary directory \"%1\": %2").arg(dir, why);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgUnexpectedOutput(const QByteArray &what)
|
static QString msgUnexpectedOutput(const QByteArray &what)
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Unexpected output from helper program (%1).").arg(QString::fromLatin1(what));
|
return TerminalImpl::tr("Unexpected output from helper program (%1).").arg(QString::fromLatin1(what));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgCannotChangeToWorkDir(const FilePath &dir, const QString &why)
|
static QString msgCannotChangeToWorkDir(const FilePath &dir, const QString &why)
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Cannot change to working directory \"%1\": %2").arg(dir.toString(), why);
|
return TerminalImpl::tr("Cannot change to working directory \"%1\": %2").arg(dir.toString(), why);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString msgCannotExecute(const QString & p, const QString &why)
|
static QString msgCannotExecute(const QString & p, const QString &why)
|
||||||
{
|
{
|
||||||
return TerminalProcess::tr("Cannot execute \"%1\": %2").arg(p, why);
|
return TerminalImpl::tr("Cannot execute \"%1\": %2").arg(p, why);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TerminalProcessPrivate
|
class TerminalProcessPrivate
|
||||||
@@ -126,19 +126,14 @@ public:
|
|||||||
TerminalProcessPrivate(QObject *parent)
|
TerminalProcessPrivate(QObject *parent)
|
||||||
: m_process(parent) {}
|
: m_process(parent) {}
|
||||||
|
|
||||||
TerminalMode m_terminalMode = TerminalMode::On;
|
|
||||||
FilePath m_workingDir;
|
|
||||||
Environment m_environment;
|
|
||||||
qint64 m_processId = 0;
|
qint64 m_processId = 0;
|
||||||
int m_exitCode = 0;
|
int m_exitCode = 0;
|
||||||
CommandLine m_commandLine;
|
|
||||||
QProcess::ExitStatus m_appStatus = QProcess::NormalExit;
|
QProcess::ExitStatus m_appStatus = QProcess::NormalExit;
|
||||||
QLocalServer m_stubServer;
|
QLocalServer m_stubServer;
|
||||||
QLocalSocket *m_stubSocket = nullptr;
|
QLocalSocket *m_stubSocket = nullptr;
|
||||||
QTemporaryFile *m_tempFile = nullptr;
|
QTemporaryFile *m_tempFile = nullptr;
|
||||||
QProcess::ProcessError m_error = QProcess::UnknownError;
|
QProcess::ProcessError m_error = QProcess::UnknownError;
|
||||||
QString m_errorString;
|
QString m_errorString;
|
||||||
bool m_abortOnMetaChars = true;
|
|
||||||
|
|
||||||
// Used on Unix only
|
// Used on Unix only
|
||||||
QtcProcess m_process;
|
QtcProcess m_process;
|
||||||
@@ -156,50 +151,29 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
TerminalProcess::TerminalProcess(QObject *parent)
|
TerminalImpl::TerminalImpl()
|
||||||
: QObject(parent), d(new TerminalProcessPrivate(this))
|
: d(new TerminalProcessPrivate(this))
|
||||||
{
|
{
|
||||||
connect(&d->m_stubServer, &QLocalServer::newConnection,
|
connect(&d->m_stubServer, &QLocalServer::newConnection,
|
||||||
this, &TerminalProcess::stubConnectionAvailable);
|
this, &TerminalImpl::stubConnectionAvailable);
|
||||||
|
|
||||||
d->m_process.setProcessChannelMode(QProcess::ForwardedChannels);
|
d->m_process.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalProcess::~TerminalProcess()
|
TerminalImpl::~TerminalImpl()
|
||||||
{
|
{
|
||||||
stopProcess();
|
stopProcess();
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::setProcessImpl(ProcessImpl processImpl)
|
qint64 TerminalImpl::applicationMainThreadID() const
|
||||||
{
|
|
||||||
d->m_process.setProcessImpl(processImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerminalProcess::setTerminalMode(TerminalMode mode)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(mode != TerminalMode::Off, return);
|
|
||||||
d->m_terminalMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerminalProcess::setCommand(const CommandLine &command)
|
|
||||||
{
|
|
||||||
d->m_commandLine = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerminalProcess::setAbortOnMetaChars(bool abort)
|
|
||||||
{
|
|
||||||
d->m_abortOnMetaChars = abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 TerminalProcess::applicationMainThreadID() const
|
|
||||||
{
|
{
|
||||||
if (HostOsInfo::isWindowsHost())
|
if (HostOsInfo::isWindowsHost())
|
||||||
return d->m_appMainThreadId;
|
return d->m_appMainThreadId;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::start()
|
void TerminalImpl::start()
|
||||||
{
|
{
|
||||||
if (isRunning())
|
if (isRunning())
|
||||||
return;
|
return;
|
||||||
@@ -211,13 +185,13 @@ void TerminalProcess::start()
|
|||||||
|
|
||||||
QString pcmd;
|
QString pcmd;
|
||||||
QString pargs;
|
QString pargs;
|
||||||
if (d->m_terminalMode != TerminalMode::Run) { // The debugger engines already pre-process the arguments.
|
if (m_setup->m_terminalMode != TerminalMode::Run) { // The debugger engines already pre-process the arguments.
|
||||||
pcmd = d->m_commandLine.executable().toString();
|
pcmd = m_setup->m_commandLine.executable().toString();
|
||||||
pargs = d->m_commandLine.arguments();
|
pargs = m_setup->m_commandLine.arguments();
|
||||||
} else {
|
} else {
|
||||||
ProcessArgs outArgs;
|
ProcessArgs outArgs;
|
||||||
ProcessArgs::prepareCommand(d->m_commandLine, &pcmd, &outArgs,
|
ProcessArgs::prepareCommand(m_setup->m_commandLine, &pcmd, &outArgs,
|
||||||
&d->m_environment, &d->m_workingDir);
|
&m_setup->m_environment, &m_setup->m_workingDirectory);
|
||||||
pargs = outArgs.toWindowsArgs();
|
pargs = outArgs.toWindowsArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +201,7 @@ void TerminalProcess::start()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList env = d->m_environment.toStringList();
|
QStringList env = m_setup->m_environment.toStringList();
|
||||||
if (!env.isEmpty()) {
|
if (!env.isEmpty()) {
|
||||||
d->m_tempFile = new QTemporaryFile();
|
d->m_tempFile = new QTemporaryFile();
|
||||||
if (!d->m_tempFile->open()) {
|
if (!d->m_tempFile->open()) {
|
||||||
@@ -274,7 +248,7 @@ void TerminalProcess::start()
|
|||||||
d->m_pid = new PROCESS_INFORMATION;
|
d->m_pid = new PROCESS_INFORMATION;
|
||||||
ZeroMemory(d->m_pid, sizeof(PROCESS_INFORMATION));
|
ZeroMemory(d->m_pid, sizeof(PROCESS_INFORMATION));
|
||||||
|
|
||||||
QString workDir = d->m_workingDir.toUserOutput();
|
QString workDir = m_setup->m_workingDirectory.toUserOutput();
|
||||||
if (!workDir.isEmpty() && !workDir.endsWith(QLatin1Char('\\')))
|
if (!workDir.isEmpty() && !workDir.endsWith(QLatin1Char('\\')))
|
||||||
workDir.append(QLatin1Char('\\'));
|
workDir.append(QLatin1Char('\\'));
|
||||||
|
|
||||||
@@ -330,7 +304,7 @@ void TerminalProcess::start()
|
|||||||
};
|
};
|
||||||
|
|
||||||
QStringList stubArgs;
|
QStringList stubArgs;
|
||||||
stubArgs << modeOption(d->m_terminalMode)
|
stubArgs << modeOption(m_setup->m_terminalMode)
|
||||||
<< d->m_stubServer.fullServerName()
|
<< d->m_stubServer.fullServerName()
|
||||||
<< workDir
|
<< workDir
|
||||||
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
|
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
|
||||||
@@ -356,27 +330,27 @@ void TerminalProcess::start()
|
|||||||
|
|
||||||
d->processFinishedNotifier = new QWinEventNotifier(d->m_pid->hProcess, this);
|
d->processFinishedNotifier = new QWinEventNotifier(d->m_pid->hProcess, this);
|
||||||
connect(d->processFinishedNotifier, &QWinEventNotifier::activated,
|
connect(d->processFinishedNotifier, &QWinEventNotifier::activated,
|
||||||
this, &TerminalProcess::stubExited);
|
this, &TerminalImpl::stubExited);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
ProcessArgs::SplitError perr;
|
ProcessArgs::SplitError perr;
|
||||||
ProcessArgs pargs = ProcessArgs::prepareArgs(d->m_commandLine.arguments(),
|
ProcessArgs pargs = ProcessArgs::prepareArgs(m_setup->m_commandLine.arguments(),
|
||||||
&perr,
|
&perr,
|
||||||
HostOsInfo::hostOs(),
|
HostOsInfo::hostOs(),
|
||||||
&d->m_environment,
|
&m_setup->m_environment,
|
||||||
&d->m_workingDir,
|
&m_setup->m_workingDirectory,
|
||||||
d->m_abortOnMetaChars);
|
m_setup->m_abortOnMetaChars);
|
||||||
|
|
||||||
QString pcmd;
|
QString pcmd;
|
||||||
if (perr == ProcessArgs::SplitOk) {
|
if (perr == ProcessArgs::SplitOk) {
|
||||||
pcmd = d->m_commandLine.executable().toString();
|
pcmd = m_setup->m_commandLine.executable().toString();
|
||||||
} else {
|
} else {
|
||||||
if (perr != ProcessArgs::FoundMeta) {
|
if (perr != ProcessArgs::FoundMeta) {
|
||||||
emitError(QProcess::FailedToStart, tr("Quoting error in command."));
|
emitError(QProcess::FailedToStart, tr("Quoting error in command."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (d->m_terminalMode == TerminalMode::Debug) {
|
if (m_setup->m_terminalMode == TerminalMode::Debug) {
|
||||||
// FIXME: QTCREATORBUG-2809
|
// FIXME: QTCREATORBUG-2809
|
||||||
emitError(QProcess::FailedToStart, tr("Debugging complex shell commands in a terminal"
|
emitError(QProcess::FailedToStart, tr("Debugging complex shell commands in a terminal"
|
||||||
" is currently not supported."));
|
" is currently not supported."));
|
||||||
@@ -384,8 +358,8 @@ void TerminalProcess::start()
|
|||||||
}
|
}
|
||||||
pcmd = qEnvironmentVariable("SHELL", "/bin/sh");
|
pcmd = qEnvironmentVariable("SHELL", "/bin/sh");
|
||||||
pargs = ProcessArgs::createUnixArgs(
|
pargs = ProcessArgs::createUnixArgs(
|
||||||
{"-c", (ProcessArgs::quoteArg(d->m_commandLine.executable().toString())
|
{"-c", (ProcessArgs::quoteArg(m_setup->m_commandLine.executable().toString())
|
||||||
+ ' ' + d->m_commandLine.arguments())});
|
+ ' ' + m_setup->m_commandLine.arguments())});
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessArgs::SplitError qerr;
|
ProcessArgs::SplitError qerr;
|
||||||
@@ -393,8 +367,8 @@ void TerminalProcess::start()
|
|||||||
const ProcessArgs terminalArgs = ProcessArgs::prepareArgs(terminal.executeArgs,
|
const ProcessArgs terminalArgs = ProcessArgs::prepareArgs(terminal.executeArgs,
|
||||||
&qerr,
|
&qerr,
|
||||||
HostOsInfo::hostOs(),
|
HostOsInfo::hostOs(),
|
||||||
&d->m_environment,
|
&m_setup->m_environment,
|
||||||
&d->m_workingDir);
|
&m_setup->m_workingDirectory);
|
||||||
if (qerr != ProcessArgs::SplitOk) {
|
if (qerr != ProcessArgs::SplitOk) {
|
||||||
emitError(QProcess::FailedToStart, qerr == ProcessArgs::BadQuoting
|
emitError(QProcess::FailedToStart, qerr == ProcessArgs::BadQuoting
|
||||||
? tr("Quoting error in terminal command.")
|
? tr("Quoting error in terminal command.")
|
||||||
@@ -408,9 +382,9 @@ void TerminalProcess::start()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->m_environment.unset(QLatin1String("TERM"));
|
m_setup->m_environment.unset(QLatin1String("TERM"));
|
||||||
|
|
||||||
const QStringList env = d->m_environment.toStringList();
|
const QStringList env = m_setup->m_environment.toStringList();
|
||||||
if (!env.isEmpty()) {
|
if (!env.isEmpty()) {
|
||||||
d->m_tempFile = new QTemporaryFile();
|
d->m_tempFile = new QTemporaryFile();
|
||||||
if (!d->m_tempFile->open()) {
|
if (!d->m_tempFile->open()) {
|
||||||
@@ -434,10 +408,10 @@ void TerminalProcess::start()
|
|||||||
QStringList allArgs = terminalArgs.toUnixArgs();
|
QStringList allArgs = terminalArgs.toUnixArgs();
|
||||||
|
|
||||||
allArgs << stubPath
|
allArgs << stubPath
|
||||||
<< modeOption(d->m_terminalMode)
|
<< modeOption(m_setup->m_terminalMode)
|
||||||
<< d->m_stubServer.fullServerName()
|
<< d->m_stubServer.fullServerName()
|
||||||
<< msgPromptToClose()
|
<< msgPromptToClose()
|
||||||
<< d->m_workingDir.path()
|
<< m_setup->m_workingDirectory.path()
|
||||||
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
|
<< (d->m_tempFile ? d->m_tempFile->fileName() : QString())
|
||||||
<< QString::number(getpid())
|
<< QString::number(getpid())
|
||||||
<< pcmd
|
<< pcmd
|
||||||
@@ -446,8 +420,9 @@ void TerminalProcess::start()
|
|||||||
if (terminal.needsQuotes)
|
if (terminal.needsQuotes)
|
||||||
allArgs = QStringList { ProcessArgs::joinArgs(allArgs) };
|
allArgs = QStringList { ProcessArgs::joinArgs(allArgs) };
|
||||||
|
|
||||||
d->m_process.setEnvironment(d->m_environment);
|
d->m_process.setEnvironment(m_setup->m_environment);
|
||||||
d->m_process.setCommand({FilePath::fromString(terminal.command), allArgs});
|
d->m_process.setCommand({FilePath::fromString(terminal.command), allArgs});
|
||||||
|
d->m_process.setProcessImpl(m_setup->m_processImpl);
|
||||||
d->m_process.start();
|
d->m_process.start();
|
||||||
if (!d->m_process.waitForStarted()) {
|
if (!d->m_process.waitForStarted()) {
|
||||||
const QString msg = tr("Cannot start the terminal emulator \"%1\", change the setting in the "
|
const QString msg = tr("Cannot start the terminal emulator \"%1\", change the setting in the "
|
||||||
@@ -456,14 +431,14 @@ void TerminalProcess::start()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->m_stubConnectTimer = new QTimer(this);
|
d->m_stubConnectTimer = new QTimer(this);
|
||||||
connect(d->m_stubConnectTimer, &QTimer::timeout, this, &TerminalProcess::stopProcess);
|
connect(d->m_stubConnectTimer, &QTimer::timeout, this, &TerminalImpl::stopProcess);
|
||||||
d->m_stubConnectTimer->setSingleShot(true);
|
d->m_stubConnectTimer->setSingleShot(true);
|
||||||
d->m_stubConnectTimer->start(10000);
|
d->m_stubConnectTimer->start(10000);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::cleanupAfterStartFailure(const QString &errorMessage)
|
void TerminalImpl::cleanupAfterStartFailure(const QString &errorMessage)
|
||||||
{
|
{
|
||||||
stubServerShutdown();
|
stubServerShutdown();
|
||||||
emitError(QProcess::FailedToStart, errorMessage);
|
emitError(QProcess::FailedToStart, errorMessage);
|
||||||
@@ -471,7 +446,7 @@ void TerminalProcess::cleanupAfterStartFailure(const QString &errorMessage)
|
|||||||
d->m_tempFile = nullptr;
|
d->m_tempFile = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::finish(int exitCode, QProcess::ExitStatus exitStatus)
|
void TerminalImpl::finish(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
{
|
{
|
||||||
d->m_processId = 0;
|
d->m_processId = 0;
|
||||||
d->m_exitCode = exitCode;
|
d->m_exitCode = exitCode;
|
||||||
@@ -479,7 +454,7 @@ void TerminalProcess::finish(int exitCode, QProcess::ExitStatus exitStatus)
|
|||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::kickoffProcess()
|
void TerminalImpl::kickoffProcess()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// Not used.
|
// Not used.
|
||||||
@@ -491,7 +466,7 @@ void TerminalProcess::kickoffProcess()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::interrupt()
|
void TerminalImpl::interrupt()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// Not used.
|
// Not used.
|
||||||
@@ -503,7 +478,7 @@ void TerminalProcess::interrupt()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::killProcess()
|
void TerminalImpl::killProcess()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (d->m_hInferior != NULL) {
|
if (d->m_hInferior != NULL) {
|
||||||
@@ -519,7 +494,7 @@ void TerminalProcess::killProcess()
|
|||||||
d->m_processId = 0;
|
d->m_processId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::killStub()
|
void TerminalImpl::killStub()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (d->m_pid) {
|
if (d->m_pid) {
|
||||||
@@ -536,7 +511,7 @@ void TerminalProcess::killStub()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::stopProcess()
|
void TerminalImpl::stopProcess()
|
||||||
{
|
{
|
||||||
killProcess();
|
killProcess();
|
||||||
killStub();
|
killStub();
|
||||||
@@ -549,7 +524,7 @@ void TerminalProcess::stopProcess()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TerminalProcess::isRunning() const
|
bool TerminalImpl::isRunning() const
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return d->m_pid != nullptr;
|
return d->m_pid != nullptr;
|
||||||
@@ -559,7 +534,7 @@ bool TerminalProcess::isRunning() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcess::ProcessState TerminalProcess::state() const
|
QProcess::ProcessState TerminalImpl::state() const
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return (d->m_pid != nullptr) ? QProcess::Running : QProcess::NotRunning;
|
return (d->m_pid != nullptr) ? QProcess::Running : QProcess::NotRunning;
|
||||||
@@ -569,7 +544,7 @@ QProcess::ProcessState TerminalProcess::state() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TerminalProcess::stubServerListen()
|
QString TerminalImpl::stubServerListen()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (d->m_stubServer.listen(QString::fromLatin1("creator-%1-%2")
|
if (d->m_stubServer.listen(QString::fromLatin1("creator-%1-%2")
|
||||||
@@ -604,7 +579,7 @@ QString TerminalProcess::stubServerListen()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::stubServerShutdown()
|
void TerminalImpl::stubServerShutdown()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
delete d->m_stubSocket;
|
delete d->m_stubSocket;
|
||||||
@@ -625,7 +600,7 @@ void TerminalProcess::stubServerShutdown()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::stubConnectionAvailable()
|
void TerminalImpl::stubConnectionAvailable()
|
||||||
{
|
{
|
||||||
if (d->m_stubConnectTimer) {
|
if (d->m_stubConnectTimer) {
|
||||||
delete d->m_stubConnectTimer;
|
delete d->m_stubConnectTimer;
|
||||||
@@ -633,10 +608,10 @@ void TerminalProcess::stubConnectionAvailable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
d->m_stubSocket = d->m_stubServer.nextPendingConnection();
|
d->m_stubSocket = d->m_stubServer.nextPendingConnection();
|
||||||
connect(d->m_stubSocket, &QIODevice::readyRead, this, &TerminalProcess::readStubOutput);
|
connect(d->m_stubSocket, &QIODevice::readyRead, this, &TerminalImpl::readStubOutput);
|
||||||
|
|
||||||
if (HostOsInfo::isAnyUnixHost())
|
if (HostOsInfo::isAnyUnixHost())
|
||||||
connect(d->m_stubSocket, &QLocalSocket::disconnected, this, &TerminalProcess::stubExited);
|
connect(d->m_stubSocket, &QLocalSocket::disconnected, this, &TerminalImpl::stubExited);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString errorMsg(int code)
|
static QString errorMsg(int code)
|
||||||
@@ -644,16 +619,18 @@ static QString errorMsg(int code)
|
|||||||
return QString::fromLocal8Bit(strerror(code));
|
return QString::fromLocal8Bit(strerror(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::readStubOutput()
|
void TerminalImpl::readStubOutput()
|
||||||
{
|
{
|
||||||
while (d->m_stubSocket->canReadLine()) {
|
while (d->m_stubSocket->canReadLine()) {
|
||||||
QByteArray out = d->m_stubSocket->readLine();
|
QByteArray out = d->m_stubSocket->readLine();
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
out.chop(2); // \r\n
|
out.chop(2); // \r\n
|
||||||
if (out.startsWith("err:chdir ")) {
|
if (out.startsWith("err:chdir ")) {
|
||||||
emitError(QProcess::FailedToStart, msgCannotChangeToWorkDir(d->m_workingDir, winErrorMessage(out.mid(10).toInt())));
|
emitError(QProcess::FailedToStart,
|
||||||
|
msgCannotChangeToWorkDir(m_setup->m_workingDirectory, winErrorMessage(out.mid(10).toInt())));
|
||||||
} else if (out.startsWith("err:exec ")) {
|
} else if (out.startsWith("err:exec ")) {
|
||||||
emitError(QProcess::FailedToStart, msgCannotExecute(d->m_commandLine.executable().toUserOutput(), winErrorMessage(out.mid(9).toInt())));
|
emitError(QProcess::FailedToStart,
|
||||||
|
msgCannotExecute(m_setup->m_commandLine.executable().toUserOutput(), winErrorMessage(out.mid(9).toInt())));
|
||||||
} else if (out.startsWith("thread ")) { // Windows only
|
} else if (out.startsWith("thread ")) { // Windows only
|
||||||
d->m_appMainThreadId = out.mid(7).toLongLong();
|
d->m_appMainThreadId = out.mid(7).toLongLong();
|
||||||
} else if (out.startsWith("pid ")) {
|
} else if (out.startsWith("pid ")) {
|
||||||
@@ -691,9 +668,11 @@ void TerminalProcess::readStubOutput()
|
|||||||
#else
|
#else
|
||||||
out.chop(1); // \n
|
out.chop(1); // \n
|
||||||
if (out.startsWith("err:chdir ")) {
|
if (out.startsWith("err:chdir ")) {
|
||||||
emitError(QProcess::FailedToStart, msgCannotChangeToWorkDir(d->m_workingDir, errorMsg(out.mid(10).toInt())));
|
emitError(QProcess::FailedToStart,
|
||||||
|
msgCannotChangeToWorkDir(m_setup->m_workingDirectory, errorMsg(out.mid(10).toInt())));
|
||||||
} else if (out.startsWith("err:exec ")) {
|
} else if (out.startsWith("err:exec ")) {
|
||||||
emitError(QProcess::FailedToStart, msgCannotExecute(d->m_commandLine.executable().toString(), errorMsg(out.mid(9).toInt())));
|
emitError(QProcess::FailedToStart,
|
||||||
|
msgCannotExecute(m_setup->m_commandLine.executable().toString(), errorMsg(out.mid(9).toInt())));
|
||||||
} else if (out.startsWith("spid ")) {
|
} else if (out.startsWith("spid ")) {
|
||||||
delete d->m_tempFile;
|
delete d->m_tempFile;
|
||||||
d->m_tempFile = nullptr;
|
d->m_tempFile = nullptr;
|
||||||
@@ -713,7 +692,7 @@ void TerminalProcess::readStubOutput()
|
|||||||
} // while
|
} // while
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::stubExited()
|
void TerminalImpl::stubExited()
|
||||||
{
|
{
|
||||||
// The stub exit might get noticed before we read the pid for the kill on Windows
|
// The stub exit might get noticed before we read the pid for the kill on Windows
|
||||||
// or the error status elsewhere.
|
// or the error status elsewhere.
|
||||||
@@ -736,7 +715,7 @@ void TerminalProcess::stubExited()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::cleanupInferior()
|
void TerminalImpl::cleanupInferior()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
delete d->inferiorFinishedNotifier;
|
delete d->inferiorFinishedNotifier;
|
||||||
@@ -746,7 +725,7 @@ void TerminalProcess::cleanupInferior()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::cleanupStub()
|
void TerminalImpl::cleanupStub()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
stubServerShutdown();
|
stubServerShutdown();
|
||||||
@@ -761,42 +740,32 @@ void TerminalProcess::cleanupStub()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 TerminalProcess::processId() const
|
qint64 TerminalImpl::processId() const
|
||||||
{
|
{
|
||||||
return d->m_processId;
|
return d->m_processId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TerminalProcess::exitCode() const
|
int TerminalImpl::exitCode() const
|
||||||
{
|
{
|
||||||
return d->m_exitCode;
|
return d->m_exitCode;
|
||||||
} // This will be the signal number if exitStatus == CrashExit
|
} // This will be the signal number if exitStatus == CrashExit
|
||||||
|
|
||||||
QProcess::ExitStatus TerminalProcess::exitStatus() const
|
QProcess::ExitStatus TerminalImpl::exitStatus() const
|
||||||
{
|
{
|
||||||
return d->m_appStatus;
|
return d->m_appStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::setWorkingDirectory(const FilePath &dir)
|
QProcess::ProcessError TerminalImpl::error() const
|
||||||
{
|
|
||||||
d->m_workingDir = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerminalProcess::setEnvironment(const Environment &env)
|
|
||||||
{
|
|
||||||
d->m_environment = env;
|
|
||||||
}
|
|
||||||
|
|
||||||
QProcess::ProcessError TerminalProcess::error() const
|
|
||||||
{
|
{
|
||||||
return d->m_error;
|
return d->m_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TerminalProcess::errorString() const
|
QString TerminalImpl::errorString() const
|
||||||
{
|
{
|
||||||
return d->m_errorString;
|
return d->m_errorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalProcess::emitError(QProcess::ProcessError err, const QString &errorString)
|
void TerminalImpl::emitError(QProcess::ProcessError err, const QString &errorString)
|
||||||
{
|
{
|
||||||
d->m_error = err;
|
d->m_error = err;
|
||||||
d->m_errorString = errorString;
|
d->m_errorString = errorString;
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "processenums.h"
|
#include "processenums.h"
|
||||||
|
#include "processinterface.h"
|
||||||
|
#include "qtcassert.h"
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
@@ -37,46 +39,48 @@ class FilePath;
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class TerminalProcess : public QObject
|
class TerminalImpl : public ProcessInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TerminalProcess(QObject *parent);
|
TerminalImpl();
|
||||||
~TerminalProcess() override;
|
~TerminalImpl() final;
|
||||||
|
|
||||||
void setProcessImpl(ProcessImpl processImpl);
|
QByteArray readAllStandardOutput() final { QTC_CHECK(false); return {}; }
|
||||||
void setTerminalMode(TerminalMode mode);
|
QByteArray readAllStandardError() final { QTC_CHECK(false); return {}; }
|
||||||
void setCommand(const CommandLine &command);
|
|
||||||
void setWorkingDirectory(const FilePath &dir);
|
|
||||||
void setEnvironment(const Environment &env);
|
|
||||||
|
|
||||||
QProcess::ProcessError error() const;
|
qint64 write(const QByteArray &) final { QTC_CHECK(false); return -1; }
|
||||||
QString errorString() const;
|
void setErrorString(const QString &) final { QTC_CHECK(false); }
|
||||||
|
|
||||||
void start();
|
void terminate() final { stopProcess(); }
|
||||||
void stopProcess();
|
void kill() final { stopProcess(); }
|
||||||
|
void close() final { stopProcess(); }
|
||||||
|
|
||||||
|
// intentionally no-op without an assert
|
||||||
|
bool waitForStarted(int) final { return false; }
|
||||||
|
bool waitForReadyRead(int) final { QTC_CHECK(false); return false; }
|
||||||
|
// intentionally no-op without an assert
|
||||||
|
bool waitForFinished(int) final { return false; }
|
||||||
|
|
||||||
|
QProcess::ProcessError error() const final;
|
||||||
|
QString errorString() const final;
|
||||||
|
|
||||||
|
void start() final;
|
||||||
|
|
||||||
|
QProcess::ProcessState state() const final;
|
||||||
|
qint64 processId() const final;
|
||||||
|
int exitCode() const final;
|
||||||
|
QProcess::ExitStatus exitStatus() const final;
|
||||||
|
|
||||||
|
void kickoffProcess() final; // only debugger terminal, only non-windows
|
||||||
|
void interrupt() final; // only debugger terminal, only non-windows
|
||||||
|
qint64 applicationMainThreadID() const final; // only debugger terminal, only windows (-1 otherwise)
|
||||||
|
|
||||||
|
private:
|
||||||
// OK, however, impl looks a bit different (!= NotRunning vs == Running).
|
// OK, however, impl looks a bit different (!= NotRunning vs == Running).
|
||||||
// Most probably changing it into (== Running) should be OK.
|
// Most probably changing it into (== Running) should be OK.
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|
||||||
QProcess::ProcessState state() const;
|
void stopProcess();
|
||||||
qint64 processId() const;
|
|
||||||
int exitCode() const;
|
|
||||||
QProcess::ExitStatus exitStatus() const;
|
|
||||||
|
|
||||||
void setAbortOnMetaChars(bool abort); // used only in sshDeviceProcess
|
|
||||||
void kickoffProcess(); // only debugger terminal, only non-windows
|
|
||||||
void interrupt(); // only debugger terminal, only non-windows
|
|
||||||
qint64 applicationMainThreadID() const; // only debugger terminal, only windows (-1 otherwise)
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void started();
|
|
||||||
void finished();
|
|
||||||
void errorOccurred(QProcess::ProcessError error);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void stubConnectionAvailable();
|
void stubConnectionAvailable();
|
||||||
void readStubOutput();
|
void readStubOutput();
|
||||||
void stubExited();
|
void stubExited();
|
||||||
|
Reference in New Issue
Block a user