forked from qt-creator/qt-creator
Utils: Pimpl QtcProcess
Change-Id: I51d68ad760c181bfcedcd73d216a0535479ba39f Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -76,6 +76,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
Q_DECLARE_TYPEINFO(MxSave, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(MxSave, Q_MOVABLE_TYPE);
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
using namespace Utils::Internal;
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
static std::function<void(QtcProcess &)> s_remoteRunProcessHook;
|
static std::function<void(QtcProcess &)> s_remoteRunProcessHook;
|
||||||
@@ -687,8 +689,28 @@ bool QtcProcess::prepareCommand(const QString &command, const QString &arguments
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class QtcProcessPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void setupChildProcess_impl();
|
||||||
|
|
||||||
|
CommandLine m_commandLine;
|
||||||
|
Environment m_environment;
|
||||||
|
bool m_haveEnv = false;
|
||||||
|
bool m_useCtrlCStub = false;
|
||||||
|
bool m_lowPriority = false;
|
||||||
|
bool m_disableUnixTerminal = false;
|
||||||
|
|
||||||
|
bool m_synchronous = false;
|
||||||
|
QProcess::OpenMode m_openMode = QProcess::ReadWrite;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
|
||||||
QtcProcess::QtcProcess(QObject *parent)
|
QtcProcess::QtcProcess(QObject *parent)
|
||||||
: QProcess(parent)
|
: QProcess(parent), d(new QtcProcessPrivate)
|
||||||
{
|
{
|
||||||
static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>();
|
static int qProcessExitStatusMeta = qRegisterMetaType<QProcess::ExitStatus>();
|
||||||
static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>();
|
static int qProcessProcessErrorMeta = qRegisterMetaType<QProcess::ProcessError>();
|
||||||
@@ -700,13 +722,39 @@ QtcProcess::QtcProcess(QObject *parent)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QtcProcess::~QtcProcess()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtcProcess::setEnvironment(const Environment &env)
|
||||||
|
{
|
||||||
|
d->m_environment = env;
|
||||||
|
d->m_haveEnv = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Environment &QtcProcess::environment() const
|
||||||
|
{
|
||||||
|
return d->m_environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtcProcess::setCommand(const CommandLine &cmdLine)
|
||||||
|
{
|
||||||
|
d->m_commandLine = cmdLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommandLine &QtcProcess::commandLine() const
|
||||||
|
{
|
||||||
|
return d->m_commandLine;
|
||||||
|
}
|
||||||
|
|
||||||
void QtcProcess::setUseCtrlCStub(bool enabled)
|
void QtcProcess::setUseCtrlCStub(bool enabled)
|
||||||
{
|
{
|
||||||
// Do not use the stub in debug mode. Activating the stub will shut down
|
// Do not use the stub in debug mode. Activating the stub will shut down
|
||||||
// Qt Creator otherwise, because they share the same Windows console.
|
// Qt Creator otherwise, because they share the same Windows console.
|
||||||
// See QTCREATORBUG-11995 for details.
|
// See QTCREATORBUG-11995 for details.
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
m_useCtrlCStub = enabled;
|
d->m_useCtrlCStub = enabled;
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(enabled)
|
Q_UNUSED(enabled)
|
||||||
#endif
|
#endif
|
||||||
@@ -714,7 +762,7 @@ void QtcProcess::setUseCtrlCStub(bool enabled)
|
|||||||
|
|
||||||
void QtcProcess::start()
|
void QtcProcess::start()
|
||||||
{
|
{
|
||||||
if (m_commandLine.executable().needsDevice()) {
|
if (d->m_commandLine.executable().needsDevice()) {
|
||||||
QTC_ASSERT(s_remoteRunProcessHook, return);
|
QTC_ASSERT(s_remoteRunProcessHook, return);
|
||||||
s_remoteRunProcessHook(*this);
|
s_remoteRunProcessHook(*this);
|
||||||
return;
|
return;
|
||||||
@@ -722,11 +770,11 @@ void QtcProcess::start()
|
|||||||
|
|
||||||
Environment env;
|
Environment env;
|
||||||
const OsType osType = HostOsInfo::hostOs();
|
const OsType osType = HostOsInfo::hostOs();
|
||||||
if (m_haveEnv) {
|
if (d->m_haveEnv) {
|
||||||
if (m_environment.size() == 0)
|
if (d->m_environment.size() == 0)
|
||||||
qWarning("QtcProcess::start: Empty environment set when running '%s'.",
|
qWarning("QtcProcess::start: Empty environment set when running '%s'.",
|
||||||
qPrintable(m_commandLine.executable().toString()));
|
qPrintable(d->m_commandLine.executable().toString()));
|
||||||
env = m_environment;
|
env = d->m_environment;
|
||||||
|
|
||||||
QProcess::setProcessEnvironment(env.toProcessEnvironment());
|
QProcess::setProcessEnvironment(env.toProcessEnvironment());
|
||||||
} else {
|
} else {
|
||||||
@@ -736,18 +784,18 @@ void QtcProcess::start()
|
|||||||
const QString &workDir = workingDirectory();
|
const QString &workDir = workingDirectory();
|
||||||
QString command;
|
QString command;
|
||||||
QtcProcess::Arguments arguments;
|
QtcProcess::Arguments arguments;
|
||||||
bool success = prepareCommand(m_commandLine.executable().toString(),
|
bool success = prepareCommand(d->m_commandLine.executable().toString(),
|
||||||
m_commandLine.arguments(),
|
d->m_commandLine.arguments(),
|
||||||
&command, &arguments, osType, &env, &workDir);
|
&command, &arguments, osType, &env, &workDir);
|
||||||
if (osType == OsTypeWindows) {
|
if (osType == OsTypeWindows) {
|
||||||
QString args;
|
QString args;
|
||||||
if (m_useCtrlCStub) {
|
if (d->m_useCtrlCStub) {
|
||||||
if (m_lowPriority)
|
if (d->m_lowPriority)
|
||||||
addArg(&args, "-nice");
|
addArg(&args, "-nice");
|
||||||
addArg(&args, QDir::toNativeSeparators(command));
|
addArg(&args, QDir::toNativeSeparators(command));
|
||||||
command = QCoreApplication::applicationDirPath()
|
command = QCoreApplication::applicationDirPath()
|
||||||
+ QLatin1String("/qtcreator_ctrlc_stub.exe");
|
+ QLatin1String("/qtcreator_ctrlc_stub.exe");
|
||||||
} else if (m_lowPriority) {
|
} else if (d->m_lowPriority) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
setCreateProcessArgumentsModifier([](CreateProcessArguments *args) {
|
setCreateProcessArgumentsModifier([](CreateProcessArguments *args) {
|
||||||
args->flags |= BELOW_NORMAL_PRIORITY_CLASS;
|
args->flags |= BELOW_NORMAL_PRIORITY_CLASS;
|
||||||
@@ -760,7 +808,7 @@ void QtcProcess::start()
|
|||||||
#endif
|
#endif
|
||||||
// Note: Arguments set with setNativeArgs will be appended to the ones
|
// Note: Arguments set with setNativeArgs will be appended to the ones
|
||||||
// passed with start() below.
|
// passed with start() below.
|
||||||
QProcess::start(command, QStringList(), m_openMode);
|
QProcess::start(command, QStringList(), d->m_openMode);
|
||||||
} else {
|
} else {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
setErrorString(tr("Error in command line."));
|
setErrorString(tr("Error in command line."));
|
||||||
@@ -769,10 +817,10 @@ void QtcProcess::start()
|
|||||||
emit errorOccurred(QProcess::UnknownError);
|
emit errorOccurred(QProcess::UnknownError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QProcess::start(command, arguments.toUnixArgs(), m_openMode);
|
QProcess::start(command, arguments.toUnixArgs(), d->m_openMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_synchronous)
|
if (d->m_synchronous)
|
||||||
QProcess::waitForFinished();
|
QProcess::waitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -804,7 +852,7 @@ BOOL CALLBACK sendInterruptMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARA
|
|||||||
void QtcProcess::terminate()
|
void QtcProcess::terminate()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (m_useCtrlCStub)
|
if (d->m_useCtrlCStub)
|
||||||
EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
|
EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId());
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -814,11 +862,21 @@ void QtcProcess::terminate()
|
|||||||
void QtcProcess::interrupt()
|
void QtcProcess::interrupt()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QTC_ASSERT(m_useCtrlCStub, return);
|
QTC_ASSERT(d->m_useCtrlCStub, return);
|
||||||
EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, processId());
|
EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, processId());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtcProcess::setLowPriority()
|
||||||
|
{
|
||||||
|
d->m_lowPriority = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtcProcess::setDisableUnixTerminal()
|
||||||
|
{
|
||||||
|
d->m_disableUnixTerminal = true;
|
||||||
|
}
|
||||||
|
|
||||||
// This function assumes that the resulting string will be quoted.
|
// This function assumes that the resulting string will be quoted.
|
||||||
// That's irrelevant if it does not contain quotes itself.
|
// That's irrelevant if it does not contain quotes itself.
|
||||||
static int quoteArgInternalWin(QString &ret, int bslashes)
|
static int quoteArgInternalWin(QString &ret, int bslashes)
|
||||||
@@ -1257,11 +1315,11 @@ void QtcProcess::setRemoteStartProcessHook(const std::function<void(QtcProcess &
|
|||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
void QtcProcess::setupChildProcess()
|
void QtcProcess::setupChildProcess()
|
||||||
{
|
{
|
||||||
setupChildProcess_impl();
|
d->setupChildProcess_impl();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void QtcProcess::setupChildProcess_impl()
|
void QtcProcessPrivate::setupChildProcess_impl()
|
||||||
{
|
{
|
||||||
#if defined Q_OS_UNIX
|
#if defined Q_OS_UNIX
|
||||||
// nice value range is -20 to +19 where -20 is highest, 0 default and +19 is lowest
|
// nice value range is -20 to +19 where -20 is highest, 0 default and +19 is lowest
|
||||||
@@ -1279,17 +1337,17 @@ void QtcProcess::setupChildProcess_impl()
|
|||||||
|
|
||||||
bool QtcProcess::isSynchronous() const
|
bool QtcProcess::isSynchronous() const
|
||||||
{
|
{
|
||||||
return m_synchronous;
|
return d->m_synchronous;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setSynchronous(bool on)
|
void QtcProcess::setSynchronous(bool on)
|
||||||
{
|
{
|
||||||
m_synchronous = on;
|
d->m_synchronous = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::setOpenMode(OpenMode mode)
|
void QtcProcess::setOpenMode(OpenMode mode)
|
||||||
{
|
{
|
||||||
m_openMode = mode;
|
d->m_openMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtcProcess::stopProcess()
|
bool QtcProcess::stopProcess()
|
||||||
|
@@ -32,21 +32,29 @@
|
|||||||
namespace Utils {
|
namespace Utils {
|
||||||
class AbstractMacroExpander;
|
class AbstractMacroExpander;
|
||||||
|
|
||||||
|
namespace Internal { class QtcProcessPrivate; }
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
|
class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QtcProcess(QObject *parent = nullptr);
|
QtcProcess(QObject *parent = nullptr);
|
||||||
|
~QtcProcess();
|
||||||
|
|
||||||
|
void setEnvironment(const Environment &env);
|
||||||
|
const Environment &environment() const;
|
||||||
|
|
||||||
|
void setCommand(const CommandLine &cmdLine);
|
||||||
|
const CommandLine &commandLine() const;
|
||||||
|
|
||||||
void setEnvironment(const Environment &env) { m_environment = env; m_haveEnv = true; }
|
|
||||||
void setCommand(const CommandLine &cmdLine) { m_commandLine = cmdLine; }
|
|
||||||
void setUseCtrlCStub(bool enabled);
|
void setUseCtrlCStub(bool enabled);
|
||||||
|
void setLowPriority();
|
||||||
|
void setDisableUnixTerminal();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void terminate();
|
void terminate();
|
||||||
void interrupt();
|
void interrupt();
|
||||||
void setLowPriority() { m_lowPriority = true; }
|
|
||||||
void setDisableUnixTerminal() { m_disableUnixTerminal = true; }
|
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT Arguments
|
class QTCREATOR_UTILS_EXPORT Arguments
|
||||||
{
|
{
|
||||||
@@ -142,9 +150,6 @@ public:
|
|||||||
ArgIterator m_ait;
|
ArgIterator m_ait;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CommandLine &commandLine() const { return m_commandLine; }
|
|
||||||
const Environment &environment() const { return m_environment; }
|
|
||||||
|
|
||||||
static void setRemoteStartProcessHook(const std::function<void (QtcProcess &)> &hook);
|
static void setRemoteStartProcessHook(const std::function<void (QtcProcess &)> &hook);
|
||||||
|
|
||||||
bool isSynchronous() const;
|
bool isSynchronous() const;
|
||||||
@@ -167,21 +172,10 @@ private:
|
|||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
void setupChildProcess() override;
|
void setupChildProcess() override;
|
||||||
#endif
|
#endif
|
||||||
|
Internal::QtcProcessPrivate *d = nullptr;
|
||||||
void setupChildProcess_impl();
|
|
||||||
|
|
||||||
void setProcessEnvironment(const QProcessEnvironment &environment) = delete;
|
void setProcessEnvironment(const QProcessEnvironment &environment) = delete;
|
||||||
QProcessEnvironment processEnvironment() const = delete;
|
QProcessEnvironment processEnvironment() const = delete;
|
||||||
|
|
||||||
CommandLine m_commandLine;
|
|
||||||
Environment m_environment;
|
|
||||||
bool m_haveEnv = false;
|
|
||||||
bool m_useCtrlCStub = false;
|
|
||||||
bool m_lowPriority = false;
|
|
||||||
bool m_disableUnixTerminal = false;
|
|
||||||
|
|
||||||
bool m_synchronous = false;
|
|
||||||
OpenMode m_openMode = ReadWrite;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
Reference in New Issue
Block a user