Utils: Use std::function instead of signal SynchronousProcess callback

Simpler interface and use.

Change-Id: I8db448b7ccd12927b8f8fd347b0a92c3f76f7114
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
hjk
2021-05-06 08:56:42 +02:00
parent 3229903e8a
commit d825805c39
6 changed files with 31 additions and 85 deletions

View File

@@ -1862,12 +1862,8 @@ QString QtcProcess::locateBinary(const QString &binary)
event loop that blocks only user input events. Thus, it allows for the GUI to event loop that blocks only user input events. Thus, it allows for the GUI to
repaint and append output to log windows. repaint and append output to log windows.
The stdOut(), stdErr() signals are emitted unbuffered as the process The callbacks set with setStdOutCallBack(), setStdErrCallback() are called
writes them. with complete lines based on the '\\n' marker.
The stdOutBuffered(), stdErrBuffered() signals are emitted with complete
lines based on the '\\n' marker if they are enabled using
stdOutBufferedSignalsEnabled()/setStdErrBufferedSignalsEnabled().
They would typically be used for log windows. They would typically be used for log windows.
There is a timeout handling that takes effect after the last data have been There is a timeout handling that takes effect after the last data have been
@@ -1974,8 +1970,6 @@ SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code)
// Data for one channel buffer (stderr/stdout) // Data for one channel buffer (stderr/stdout)
class ChannelBuffer : public QObject class ChannelBuffer : public QObject
{ {
Q_OBJECT
public: public:
void clearForRun(); void clearForRun();
@@ -1987,16 +1981,11 @@ public:
QTextCodec *codec = nullptr; // Not owner QTextCodec *codec = nullptr; // Not owner
std::unique_ptr<QTextCodec::ConverterState> codecState; std::unique_ptr<QTextCodec::ConverterState> codecState;
int rawDataPos = 0; int rawDataPos = 0;
bool bufferedSignalsEnabled = false; std::function<void(const QString &lines)> outputCallback;
bool firstBuffer = true;
signals:
void outputBuffered(const QString &text, bool firstTime);
}; };
void ChannelBuffer::clearForRun() void ChannelBuffer::clearForRun()
{ {
firstBuffer = true;
rawDataPos = 0; rawDataPos = 0;
rawData.clear(); rawData.clear();
codecState.reset(new QTextCodec::ConverterState); codecState.reset(new QTextCodec::ConverterState);
@@ -2035,12 +2024,10 @@ void ChannelBuffer::append(const QByteArray &text, bool emitSignals)
return; return;
// Buffered. Emit complete lines? // Buffered. Emit complete lines?
if (bufferedSignalsEnabled) { if (outputCallback) {
const QString lines = linesRead(); const QString lines = linesRead();
if (!lines.isEmpty()) { if (!lines.isEmpty())
emit outputBuffered(lines, firstBuffer); outputCallback(lines);
firstBuffer = false;
}
} }
} }
@@ -2098,8 +2085,6 @@ SynchronousProcess::SynchronousProcess() :
d->m_hangTimerCount = 0; d->m_hangTimerCount = 0;
processStdErr(true); processStdErr(true);
}); });
connect(&d->m_stdOut, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdOutBuffered);
connect(&d->m_stdErr, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdErrBuffered);
} }
SynchronousProcess::~SynchronousProcess() SynchronousProcess::~SynchronousProcess()
@@ -2133,26 +2118,6 @@ QTextCodec *SynchronousProcess::codec() const
return d->m_codec; return d->m_codec;
} }
bool SynchronousProcess::stdOutBufferedSignalsEnabled() const
{
return d->m_stdOut.bufferedSignalsEnabled;
}
void SynchronousProcess::setStdOutBufferedSignalsEnabled(bool v)
{
d->m_stdOut.bufferedSignalsEnabled = v;
}
bool SynchronousProcess::stdErrBufferedSignalsEnabled() const
{
return d->m_stdErr.bufferedSignalsEnabled;
}
void SynchronousProcess::setStdErrBufferedSignalsEnabled(bool v)
{
d->m_stdErr.bufferedSignalsEnabled = v;
}
Environment SynchronousProcess::environment() const Environment SynchronousProcess::environment() const
{ {
return d->m_process.environment(); return d->m_process.environment();
@@ -2352,6 +2317,16 @@ SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cm
return d->m_result; return d->m_result;
} }
void SynchronousProcess::setStdOutCallback(const std::function<void (const QString &)> &callback)
{
d->m_stdOut.outputCallback = callback;
}
void SynchronousProcess::setStdErrCallback(const std::function<void (const QString &)> &callback)
{
d->m_stdErr.outputCallback = callback;
}
bool SynchronousProcess::terminate() bool SynchronousProcess::terminate()
{ {
return d->m_process.stopProcess(); return d->m_process.stopProcess();
@@ -2423,6 +2398,3 @@ void SynchronousProcess::processStdErr(bool emitSignals)
} }
} // namespace Utils } // namespace Utils
#include "qtcprocess.moc"

View File

@@ -248,12 +248,6 @@ public:
QProcess::ProcessChannelMode processChannelMode () const; QProcess::ProcessChannelMode processChannelMode () const;
void setProcessChannelMode(QProcess::ProcessChannelMode m); void setProcessChannelMode(QProcess::ProcessChannelMode m);
bool stdOutBufferedSignalsEnabled() const;
void setStdOutBufferedSignalsEnabled(bool);
bool stdErrBufferedSignalsEnabled() const;
void setStdErrBufferedSignalsEnabled(bool);
bool timeOutMessageBoxEnabled() const; bool timeOutMessageBoxEnabled() const;
void setTimeOutMessageBoxEnabled(bool); void setTimeOutMessageBoxEnabled(bool);
@@ -274,9 +268,8 @@ public:
// Starts the command blocking the UI fully // Starts the command blocking the UI fully
SynchronousProcessResponse runBlocking(const CommandLine &cmd); SynchronousProcessResponse runBlocking(const CommandLine &cmd);
signals: void setStdOutCallback(const std::function<void(const QString &)> &callback);
void stdOutBuffered(const QString &lines, bool firstTime); void setStdErrCallback(const std::function<void(const QString &)> &callback);
void stdErrBuffered(const QString &lines, bool firstTime);
public slots: public slots:
bool terminate(); bool terminate();

View File

@@ -407,9 +407,7 @@ SynchronousProcessResponse ShellCommand::runSynchronous(const CommandLine &cmd,
if (d->m_flags & MergeOutputChannels) { if (d->m_flags & MergeOutputChannels) {
process.setProcessChannelMode(QProcess::MergedChannels); process.setProcessChannelMode(QProcess::MergedChannels);
} else if (d->m_progressiveOutput || !(d->m_flags & SuppressStdErr)) { } else if (d->m_progressiveOutput || !(d->m_flags & SuppressStdErr)) {
process.setStdErrBufferedSignalsEnabled(true); process.setStdErrCallback([this, proxy](const QString &text) {
connect(&process, &SynchronousProcess::stdErrBuffered,
this, [this, proxy](const QString &text) {
if (d->m_progressParser) if (d->m_progressParser)
d->m_progressParser->parseProgress(text); d->m_progressParser->parseProgress(text);
if (!(d->m_flags & SuppressStdErr)) if (!(d->m_flags & SuppressStdErr))
@@ -421,9 +419,7 @@ SynchronousProcessResponse ShellCommand::runSynchronous(const CommandLine &cmd,
// connect stdout to the output window if desired // connect stdout to the output window if desired
if (d->m_progressParser || d->m_progressiveOutput || (d->m_flags & ShowStdOut)) { if (d->m_progressParser || d->m_progressiveOutput || (d->m_flags & ShowStdOut)) {
process.setStdOutBufferedSignalsEnabled(true); process.setStdOutCallback([this, proxy](const QString &text) {
connect(&process, &SynchronousProcess::stdOutBuffered,
this, [this, proxy](const QString &text) {
if (d->m_progressParser) if (d->m_progressParser)
d->m_progressParser->parseProgress(text); d->m_progressParser->parseProgress(text);
if (d->m_flags & ShowStdOut) if (d->m_flags & ShowStdOut)

View File

@@ -174,18 +174,15 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
SynchronousProcess proc; SynchronousProcess proc;
proc.setEnvironment(AndroidConfigurations::toolsEnvironment(config)); proc.setEnvironment(AndroidConfigurations::toolsEnvironment(config));
bool assertionFound = false; bool assertionFound = false;
proc.setStdErrBufferedSignalsEnabled(true);
proc.setStdOutBufferedSignalsEnabled(true);
proc.setTimeoutS(timeout); proc.setTimeoutS(timeout);
QObject::connect(&proc, &SynchronousProcess::stdOutBuffered, proc.setStdOutCallback([offset, progressQuota, &proc, &assertionFound, &fi](const QString &out) {
[offset, progressQuota, &proc, &assertionFound, &fi](const QString &out) {
int progressPercent = parseProgress(out, assertionFound); int progressPercent = parseProgress(out, assertionFound);
if (assertionFound) if (assertionFound)
proc.terminate(); proc.terminate();
if (progressPercent != -1) if (progressPercent != -1)
fi.setProgressValue(offset + qRound((progressPercent / 100.0) * progressQuota)); fi.setProgressValue(offset + qRound((progressPercent / 100.0) * progressQuota));
}); });
QObject::connect(&proc, &SynchronousProcess::stdErrBuffered, [&output](const QString &err) { proc.setStdErrCallback([&output](const QString &err) {
output.stdError = err; output.stdError = err;
}); });
if (interruptible) { if (interruptible) {

View File

@@ -1249,7 +1249,6 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const QString &workin
{ {
QTC_ASSERT(stdInput.isEmpty(), return PerforceResponse()); // Not supported here QTC_ASSERT(stdInput.isEmpty(), return PerforceResponse()); // Not supported here
VcsOutputWindow *outputWindow = VcsOutputWindow::instance();
// Run, connect stderr to the output window // Run, connect stderr to the output window
SynchronousProcess process; SynchronousProcess process;
const int timeOutS = (flags & LongTimeOut) ? m_settings.longTimeOutS() : m_settings.timeOutS.value(); const int timeOutS = (flags & LongTimeOut) ? m_settings.longTimeOutS() : m_settings.timeOutS.value();
@@ -1262,26 +1261,15 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const QString &workin
process.setWorkingDirectory(workingDir); process.setWorkingDirectory(workingDir);
// connect stderr to the output window if desired // connect stderr to the output window if desired
if (flags & StdErrToWindow) { if (flags & StdErrToWindow)
process.setStdErrBufferedSignalsEnabled(true); process.setStdErrCallback([](const QString &lines) { VcsOutputWindow::append(lines); });
connect(&process, &SynchronousProcess::stdErrBuffered,
outputWindow, [](const QString &lines) {
VcsOutputWindow::append(lines);
});
}
// connect stdout to the output window if desired // connect stdout to the output window if desired
if (flags & StdOutToWindow) { if (flags & StdOutToWindow) {
process.setStdOutBufferedSignalsEnabled(true); if (flags & SilentStdOut)
if (flags & SilentStdOut) { process.setStdOutCallback(&VcsOutputWindow::appendSilently);
connect(&process, &SynchronousProcess::stdOutBuffered, else
outputWindow, &VcsOutputWindow::appendSilently); process.setStdOutCallback([](const QString &lines) { VcsOutputWindow::append(lines); });
} else {
connect(&process, &SynchronousProcess::stdOutBuffered,
outputWindow, [](const QString &lines) {
VcsOutputWindow::append(lines);
});
}
} }
process.setTimeOutMessageBoxEnabled(true); process.setTimeOutMessageBoxEnabled(true);
const SynchronousProcessResponse sp_resp = process.run({m_settings.p4BinaryPath.value(), args}); const SynchronousProcessResponse sp_resp = process.run({m_settings.p4BinaryPath.value(), args});

View File

@@ -55,8 +55,8 @@ void MainWindow::test()
Utils::SynchronousProcess process; Utils::SynchronousProcess process;
process.setTimeoutS(2); process.setTimeoutS(2);
qDebug() << "Async: " << cmd << args; qDebug() << "Async: " << cmd << args;
connect(&process, &Utils::SynchronousProcess::stdOutBuffered, this, &MainWindow::append); process.setStdOutCallback([this](const QString &s) { append(s); });
connect(&process, &Utils::SynchronousProcess::stdErrBuffered, this, &MainWindow::append); process.setStdErrCallback([this](const QString &s) { append(s); });
const Utils::SynchronousProcessResponse resp = process.run({Utils::FilePath::fromString(cmd), args}); const Utils::SynchronousProcessResponse resp = process.run({cmd, args});
qDebug() << resp; qDebug() << resp;
} }