Make ProcessInterface public

It's going to be subclassed in LinuxDevice.

Change-Id: I6308d7cf75a7e16cd02de585612000a1b983fadc
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2022-02-14 11:14:08 +01:00
parent f555285aa5
commit fd36b4a501
2 changed files with 107 additions and 98 deletions

View File

@@ -32,7 +32,6 @@
#include "launcherpackets.h" #include "launcherpackets.h"
#include "launchersocket.h" #include "launchersocket.h"
#include "processreaper.h" #include "processreaper.h"
#include "qtcassert.h"
#include "stringutils.h" #include "stringutils.h"
#include "terminalprocess_p.h" #include "terminalprocess_p.h"
@@ -212,75 +211,6 @@ public:
bool keepRawData = true; bool keepRawData = true;
}; };
class ProcessSetupData
{
public:
QtcProcess::ProcessImpl m_processImpl = QtcProcess::DefaultImpl;
ProcessMode m_processMode = ProcessMode::Reader;
QtcProcess::TerminalMode m_terminalMode = QtcProcess::TerminalOff;
QString m_nativeArguments;
QString m_standardInputFile;
QString m_initialErrorString;
bool m_belowNormalPriority = false;
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
bool m_abortOnMetaChars = true;
QProcess::ProcessChannelMode m_procesChannelMode = QProcess::SeparateChannels;
};
class ProcessInterface : public QObject
{
Q_OBJECT
public:
ProcessInterface(QObject *parent, ProcessMode processMode)
: QObject(parent)
, m_processMode(processMode) {}
virtual QByteArray readAllStandardOutput() = 0;
virtual QByteArray readAllStandardError() = 0;
virtual void setProcessEnvironment(const QProcessEnvironment &environment) = 0;
virtual void setWorkingDirectory(const QString &dir) = 0;
virtual void start(const QString &program, const QStringList &arguments,
const QByteArray &writeData) = 0;
virtual void customStart(const CommandLine &, const FilePath &workingDirectory,
const Environment &) { Q_UNUSED(workingDirectory); QTC_CHECK(false); }
virtual bool isCustomStart() const { return false; }
virtual void terminate() = 0;
virtual void kill() = 0;
virtual void close() = 0;
virtual qint64 write(const QByteArray &data) = 0;
virtual QString program() const = 0;
virtual QProcess::ProcessError error() const = 0;
virtual QProcess::ProcessState state() const = 0;
virtual qint64 processId() const = 0;
virtual int exitCode() const = 0;
virtual QProcess::ExitStatus exitStatus() const = 0;
virtual QString errorString() const = 0;
virtual void setErrorString(const QString &str) = 0;
virtual bool waitForStarted(int msecs) = 0;
virtual bool waitForReadyRead(int msecs) = 0;
virtual bool waitForFinished(int msecs) = 0;
virtual void kickoffProcess() { QTC_CHECK(false); }
virtual void interruptProcess() { QTC_CHECK(false); }
virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; }
const ProcessMode m_processMode;
ProcessSetupData *m_setup = nullptr;
signals:
void started();
void finished(int exitCode, QProcess::ExitStatus status);
void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput();
void readyReadStandardError();
};
class TerminalImpl : public ProcessInterface class TerminalImpl : public ProcessInterface
{ {
public: public:
@@ -550,40 +480,42 @@ public:
, q(parent) , q(parent)
{} {}
void setupNewProcessInstance() ProcessInterface *createProcessInterface()
{ {
const QtcProcess::ProcessImpl impl = const QtcProcess::ProcessImpl impl = m_setup.m_processImpl == QtcProcess::DefaultImpl
m_setup.m_processImpl == QtcProcess::DefaultImpl ? defaultProcessImpl() : m_setup.m_processImpl;
? defaultProcessImpl()
: m_setup.m_processImpl;
if (m_setup.m_terminalMode != QtcProcess::TerminalOff) if (m_setup.m_terminalMode != QtcProcess::TerminalOff)
m_process = new TerminalImpl(parent(), impl, m_setup.m_terminalMode); return new TerminalImpl(parent(), impl, m_setup.m_terminalMode);
else if (impl == QtcProcess::QProcessImpl) else if (impl == QtcProcess::QProcessImpl)
m_process = new QProcessImpl(parent(), m_setup.m_processMode); return new QProcessImpl(parent(), m_setup.m_processMode);
else return new ProcessLauncherImpl(parent(), m_setup.m_processMode);
m_process = new ProcessLauncherImpl(parent(), m_setup.m_processMode);
m_process->m_setup = &m_setup;
} }
void ensureProcessInstanceExists() void setProcessInterface(ProcessInterface *process)
{
m_process.reset(process);
m_process->m_setup = &m_setup;
m_process->setParent(this);
connect(m_process.get(), &ProcessInterface::started,
q, &QtcProcess::started);
connect(m_process.get(), &ProcessInterface::finished,
this, &QtcProcessPrivate::slotFinished);
connect(m_process.get(), &ProcessInterface::errorOccurred,
this, [this](QProcess::ProcessError error) { handleError(error, OtherFailure); });
connect(m_process.get(), &ProcessInterface::readyReadStandardOutput,
this, &QtcProcessPrivate::handleReadyReadStandardOutput);
connect(m_process.get(), &ProcessInterface::readyReadStandardError,
this, &QtcProcessPrivate::handleReadyReadStandardError);
}
void ensureProcessInterfaceExists()
{ {
if (m_process) if (m_process)
return; return;
setupNewProcessInstance(); setProcessInterface(createProcessInterface());
connect(m_process, &ProcessInterface::started,
q, &QtcProcess::started);
connect(m_process, &ProcessInterface::finished,
this, &QtcProcessPrivate::slotFinished);
connect(m_process, &ProcessInterface::errorOccurred,
this, [this](QProcess::ProcessError error) { handleError(error, OtherFailure); });
connect(m_process, &ProcessInterface::readyReadStandardOutput,
this, &QtcProcessPrivate::handleReadyReadStandardOutput);
connect(m_process, &ProcessInterface::readyReadStandardError,
this, &QtcProcessPrivate::handleReadyReadStandardError);
} }
void handleReadyReadStandardOutput() void handleReadyReadStandardOutput()
@@ -619,7 +551,6 @@ public:
qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << commandLine.toUserOutput(); qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << commandLine.toUserOutput();
} }
ensureProcessInstanceExists();
m_process->setProcessEnvironment(environment.toProcessEnvironment()); m_process->setProcessEnvironment(environment.toProcessEnvironment());
m_process->setWorkingDirectory(workingDirectory.path()); m_process->setWorkingDirectory(workingDirectory.path());
@@ -657,7 +588,6 @@ public:
void start(const QString &program, const QStringList &arguments, void start(const QString &program, const QStringList &arguments,
const FilePath &workingDirectory, const QByteArray &writeData) const FilePath &workingDirectory, const QByteArray &writeData)
{ {
ensureProcessInstanceExists();
const FilePath programFilePath = resolve(workingDirectory, FilePath::fromString(program)); const FilePath programFilePath = resolve(workingDirectory, FilePath::fromString(program));
if (programFilePath.exists() && programFilePath.isExecutableFile()) { if (programFilePath.exists() && programFilePath.isExecutableFile()) {
s_start.measureAndRun(&ProcessInterface::start, m_process, program, arguments, writeData); s_start.measureAndRun(&ProcessInterface::start, m_process, program, arguments, writeData);
@@ -696,7 +626,7 @@ public:
} }
QtcProcess *q; QtcProcess *q;
ProcessInterface *m_process = nullptr; std::unique_ptr<ProcessInterface> m_process;
CommandLine m_commandLine; CommandLine m_commandLine;
FilePath m_workingDirectory; FilePath m_workingDirectory;
Environment m_environment; Environment m_environment;
@@ -772,6 +702,11 @@ QtcProcess::~QtcProcess()
delete d; delete d;
} }
void QtcProcess::setProcessInterface(ProcessInterface *interface)
{
d->setProcessInterface(interface);
}
void QtcProcess::setProcessImpl(ProcessImpl processImpl) void QtcProcess::setProcessImpl(ProcessImpl processImpl)
{ {
d->m_setup.m_processImpl = processImpl; d->m_setup.m_processImpl = processImpl;
@@ -859,12 +794,12 @@ void QtcProcess::setUseCtrlCStub(bool enabled)
void QtcProcess::start() void QtcProcess::start()
{ {
d->ensureProcessInstanceExists();
if (d->m_commandLine.executable().needsDevice()) { if (d->m_commandLine.executable().needsDevice()) {
QTC_ASSERT(s_deviceHooks.startProcessHook, return); QTC_ASSERT(s_deviceHooks.startProcessHook, return);
s_deviceHooks.startProcessHook(*this); s_deviceHooks.startProcessHook(*this);
return; return;
} }
d->ensureProcessInterfaceExists();
d->clearForRun(); d->clearForRun();
const CommandLine cmd = d->fullCommandLine(); const CommandLine cmd = d->fullCommandLine();
const Environment env = d->fullEnvironment(); const Environment env = d->fullEnvironment();

View File

@@ -30,6 +30,7 @@
#include "environment.h" #include "environment.h"
#include "commandline.h" #include "commandline.h"
#include "processutils.h" #include "processutils.h"
#include "qtcassert.h"
#include <QProcess> #include <QProcess>
@@ -44,6 +45,7 @@ namespace Utils {
class CommandLine; class CommandLine;
class Environment; class Environment;
class ProcessInterface;
class QtcProcess; class QtcProcess;
namespace Internal { class QtcProcessPrivate; } namespace Internal { class QtcProcessPrivate; }
@@ -94,6 +96,8 @@ public:
Hang Hang
}; };
void setProcessInterface(ProcessInterface *interface);
void setProcessImpl(ProcessImpl processImpl); void setProcessImpl(ProcessImpl processImpl);
void setTerminalMode(TerminalMode mode); void setTerminalMode(TerminalMode mode);
@@ -236,6 +240,76 @@ private:
void endFeed(); void endFeed();
}; };
class QTCREATOR_UTILS_EXPORT ProcessSetupData
{
public:
QtcProcess::ProcessImpl m_processImpl = QtcProcess::DefaultImpl;
ProcessMode m_processMode = ProcessMode::Reader;
QtcProcess::TerminalMode m_terminalMode = QtcProcess::TerminalOff;
QString m_nativeArguments;
QString m_standardInputFile;
QString m_initialErrorString;
bool m_belowNormalPriority = false;
bool m_lowPriority = false;
bool m_unixTerminalDisabled = false;
bool m_abortOnMetaChars = true;
QProcess::ProcessChannelMode m_procesChannelMode = QProcess::SeparateChannels;
};
class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
{
Q_OBJECT
public:
ProcessInterface(QObject *parent, ProcessMode processMode)
: QObject(parent)
, m_processMode(processMode) {}
virtual QByteArray readAllStandardOutput() = 0;
virtual QByteArray readAllStandardError() = 0;
virtual void setProcessEnvironment(const QProcessEnvironment &environment) = 0;
virtual void setWorkingDirectory(const QString &dir) = 0;
virtual void start(const QString &program, const QStringList &arguments,
const QByteArray &writeData) = 0;
virtual void customStart(const CommandLine &, const FilePath &,
const Environment &) { QTC_CHECK(false); }
virtual bool isCustomStart() const { return false; }
virtual void terminate() = 0;
virtual void kill() = 0;
virtual void close() = 0;
virtual qint64 write(const QByteArray &data) = 0;
virtual QString program() const = 0;
virtual QProcess::ProcessError error() const = 0;
virtual QProcess::ProcessState state() const = 0;
virtual qint64 processId() const = 0;
virtual int exitCode() const = 0;
virtual QProcess::ExitStatus exitStatus() const = 0;
virtual QString errorString() const = 0;
virtual void setErrorString(const QString &str) = 0;
virtual bool waitForStarted(int msecs) = 0;
virtual bool waitForReadyRead(int msecs) = 0;
virtual bool waitForFinished(int msecs) = 0;
virtual void kickoffProcess() { QTC_CHECK(false); }
virtual void interruptProcess() { QTC_CHECK(false); }
virtual qint64 applicationMainThreadID() const { QTC_CHECK(false); return -1; }
const ProcessMode m_processMode;
ProcessSetupData *m_setup = nullptr;
signals:
void started();
void finished(int exitCode, QProcess::ExitStatus status);
void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput();
void readyReadStandardError();
};
using ExitCodeInterpreter = std::function<QtcProcess::Result(int /*exitCode*/)>; using ExitCodeInterpreter = std::function<QtcProcess::Result(int /*exitCode*/)>;
} // namespace Utils } // namespace Utils