22#include "moc_qgsrunprocess.cpp"
32#include <QApplication>
35QgsRunProcess::QgsRunProcess(
const QString &action,
bool capture )
44 QStringList arguments = QProcess::splitCommand( action );
45 const QString command = arguments.value( 0 );
46 if ( !arguments.isEmpty() )
47 arguments.removeFirst();
49 mProcess =
new QProcess;
53 connect( mProcess, &QProcess::errorOccurred,
this, &QgsRunProcess::processError );
54 connect( mProcess, &QProcess::readyReadStandardOutput,
this, &QgsRunProcess::stdoutAvailable );
55 connect( mProcess, &QProcess::readyReadStandardError,
this, &QgsRunProcess::stderrAvailable );
59 connect( mProcess,
static_cast < void ( QProcess::* )(
int, QProcess::ExitStatus )
>( &QProcess::finished ),
this, &QgsRunProcess::processExit );
64 mOutput->setTitle( action );
66 mOutput->showMessage(
false );
69 QObject *mOutputObj =
dynamic_cast<QObject *
>( mOutput );
72 connect( mOutputObj, &QObject::destroyed,
this, &QgsRunProcess::dialogGone );
76 mProcess->start( command, arguments );
80 if ( ! QProcess::startDetached( command, arguments ) )
82 QMessageBox::critical(
nullptr, tr(
"Action" ),
83 tr(
"Unable to run command\n%1" ).arg( action ),
84 QMessageBox::Ok, Qt::NoButton );
92QgsRunProcess::~QgsRunProcess()
97void QgsRunProcess::die()
103void QgsRunProcess::stdoutAvailable()
105 const QByteArray bytes( mProcess->readAllStandardOutput() );
106 QTextCodec *codec = QTextCodec::codecForLocale();
107 const QString line( codec->toUnicode( bytes ) );
110 mOutput->appendMessage( line );
113void QgsRunProcess::stderrAvailable()
115 const QByteArray bytes( mProcess->readAllStandardOutput() );
116 QTextCodec *codec = QTextCodec::codecForLocale();
117 const QString line( codec->toUnicode( bytes ) );
120 mOutput->appendMessage(
"<font color=red>" + line +
"</font>" );
123void QgsRunProcess::processExit(
int, QProcess::ExitStatus )
134 mOutput->appendMessage(
"<b>" + tr(
"Done" ) +
"</b>" );
143void QgsRunProcess::dialogGone()
154 disconnect( mProcess, &QProcess::errorOccurred,
this, &QgsRunProcess::processError );
155 disconnect( mProcess, &QProcess::readyReadStandardOutput,
this, &QgsRunProcess::stdoutAvailable );
156 disconnect( mProcess, &QProcess::readyReadStandardError,
this, &QgsRunProcess::stderrAvailable );
157 disconnect( mProcess,
static_cast < void ( QProcess::* )(
int, QProcess::ExitStatus )
>( &QProcess::finished ),
this, &QgsRunProcess::processExit );
162void QgsRunProcess::processError( QProcess::ProcessError err )
164 if ( err == QProcess::FailedToStart )
179 return QProcess::splitCommand( command );
182QgsRunProcess::QgsRunProcess(
const QString &action,
bool )
188QgsRunProcess::~QgsRunProcess()
194 return QStringList();
203#if QT_CONFIG(process)
204QgsBlockingProcess::QgsBlockingProcess(
const QString &process,
const QStringList &arguments )
206 , mProcess( process )
207 , mArguments( arguments )
212int QgsBlockingProcess::run(
QgsFeedback *feedback )
214 const bool requestMadeFromMainThread = QThread::currentThread() == QCoreApplication::instance()->thread();
217 QProcess::ExitStatus exitStatus = QProcess::NormalExit;
218 QProcess::ProcessError error = QProcess::UnknownError;
220 const std::function<void()> runFunction = [
this, &result, &exitStatus, &error, feedback]()
227 const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
228 p.setProcessEnvironment( env );
234 connect( qApp, &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit, Qt::DirectConnection );
248 connect( &p, qOverload< int, QProcess::ExitStatus >( &QProcess::finished ),
this, [&loop, &result, &exitStatus](
int res, QProcess::ExitStatus st )
253 }, Qt::DirectConnection );
255 connect( &p, &QProcess::readyReadStandardOutput, &p, [&p,
this]
257 const QByteArray ba = p.readAllStandardOutput();
258 mStdoutHandler( ba );
260 connect( &p, &QProcess::readyReadStandardError, &p, [&p,
this]
262 const QByteArray ba = p.readAllStandardError();
263 mStderrHandler( ba );
265 p.start( mProcess, mArguments, QProcess::Unbuffered | QProcess::ReadWrite );
266 if ( !p.waitForStarted() )
269 exitStatus = QProcess::NormalExit;
277 mStdoutHandler( p.readAllStandardOutput() );
278 mStderrHandler( p.readAllStandardError() );
281 if ( requestMadeFromMainThread )
283 std::unique_ptr<ProcessThread> processThread = std::make_unique<ProcessThread>( runFunction );
284 processThread->start();
286 processThread->wait();
293 mExitStatus = exitStatus;
294 mProcessError = error;
298QProcess::ExitStatus QgsBlockingProcess::exitStatus()
const
303QProcess::ProcessError QgsBlockingProcess::processError()
const
305 return mProcessError;
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
void canceled()
Internal routines can connect to this signal if they use event loop.
Interface for showing messages from QGIS in GUI independent way.
static QgsMessageOutput * createMessageOutput()
function that returns new class derived from QgsMessageOutput (don't forget to delete it then if show...
virtual void setMessage(const QString &message, MessageType msgType)=0
Sets message, it won't be displayed until.
static QStringList splitCommand(const QString &command)
Splits the string command into a list of tokens, and returns the list.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)