30 #include <QMessageBox> 
   31 #include <QApplication> 
   33 #if QT_CONFIG(process) 
   34 QgsRunProcess::QgsRunProcess( 
const QString &action, 
bool capture )
 
   43 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) 
   44   QStringList arguments = QProcess::splitCommand( action );
 
   45   const QString command = arguments.value( 0 );
 
   46   if ( !arguments.isEmpty() )
 
   47     arguments.removeFirst();
 
   50   mProcess = 
new QProcess;
 
   54     connect( mProcess, &QProcess::errorOccurred, 
this, &QgsRunProcess::processError );
 
   55     connect( mProcess, &QProcess::readyReadStandardOutput, 
this, &QgsRunProcess::stdoutAvailable );
 
   56     connect( mProcess, &QProcess::readyReadStandardError, 
this, &QgsRunProcess::stderrAvailable );
 
   60     connect( mProcess, 
static_cast < void ( QProcess::* )( 
int,  QProcess::ExitStatus ) 
>( &QProcess::finished ), 
this, &QgsRunProcess::processExit );
 
   65     mOutput->setTitle( action );
 
   67     mOutput->showMessage( 
false ); 
 
   70     QObject *mOutputObj = 
dynamic_cast<QObject *
>( mOutput );
 
   73       connect( mOutputObj, &QObject::destroyed, 
this, &QgsRunProcess::dialogGone );
 
   77 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
   78     mProcess->start( action );
 
   80     mProcess->start( command, arguments );
 
   85 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
   86     if ( ! mProcess->startDetached( action ) ) 
 
   88     if ( ! mProcess->startDetached( command, arguments ) ) 
 
   91       QMessageBox::critical( 
nullptr, tr( 
"Action" ),
 
   92                              tr( 
"Unable to run command\n%1" ).arg( action ),
 
   93                              QMessageBox::Ok, Qt::NoButton );
 
  101 QgsRunProcess::~QgsRunProcess()
 
  106 void QgsRunProcess::die()
 
  112 void QgsRunProcess::stdoutAvailable()
 
  114   QByteArray bytes( mProcess->readAllStandardOutput() );
 
  115   QTextCodec *codec = QTextCodec::codecForLocale();
 
  116   QString line( codec->toUnicode( bytes ) );
 
  119   mOutput->appendMessage( line );
 
  122 void QgsRunProcess::stderrAvailable()
 
  124   QByteArray bytes( mProcess->readAllStandardOutput() );
 
  125   QTextCodec *codec = QTextCodec::codecForLocale();
 
  126   QString line( codec->toUnicode( bytes ) );
 
  129   mOutput->appendMessage( 
"<font color=red>" + line + 
"</font>" );
 
  132 void QgsRunProcess::processExit( 
int, QProcess::ExitStatus )
 
  143     mOutput->appendMessage( 
"<b>" + tr( 
"Done" ) + 
"</b>" );
 
  152 void QgsRunProcess::dialogGone()
 
  163   disconnect( mProcess, &QProcess::errorOccurred, 
this, &QgsRunProcess::processError );
 
  164   disconnect( mProcess, &QProcess::readyReadStandardOutput, 
this, &QgsRunProcess::stdoutAvailable );
 
  165   disconnect( mProcess, &QProcess::readyReadStandardError, 
this, &QgsRunProcess::stderrAvailable );
 
  166   disconnect( mProcess, 
static_cast < void ( QProcess::* )( 
int, QProcess::ExitStatus ) 
>( &QProcess::finished ), 
this, &QgsRunProcess::processExit );
 
  171 void QgsRunProcess::processError( QProcess::ProcessError err )
 
  173   if ( err == QProcess::FailedToStart )
 
  182     QgsDebugMsg( 
"Got error: " + QString( 
"%d" ).arg( err ) );
 
  188 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) 
  189   return QProcess::splitCommand( command );
 
  195   bool inQuote = 
false;
 
  200   for ( 
int i = 0; i < command.size(); ++i )
 
  202     if ( command.at( i ) == QLatin1Char( 
'"' ) )
 
  205       if ( quoteCount == 3 )
 
  209         tmp += command.at( i );
 
  215       if ( quoteCount == 1 )
 
  219     if ( !inQuote && command.at( i ).isSpace() )
 
  221       if ( !tmp.isEmpty() )
 
  229       tmp += command.at( i );
 
  232   if ( !tmp.isEmpty() )
 
  239 QgsRunProcess::QgsRunProcess( 
const QString &action, 
bool )
 
  245 QgsRunProcess::~QgsRunProcess()
 
  251   return QStringList();
 
  260 #if QT_CONFIG(process) 
  261 QgsBlockingProcess::QgsBlockingProcess( 
const QString &process, 
const QStringList &arguments )
 
  263   , mProcess( process )
 
  264   , mArguments( arguments )
 
  269 int QgsBlockingProcess::run( 
QgsFeedback *feedback )
 
  271   const bool requestMadeFromMainThread = QThread::currentThread() == QCoreApplication::instance()->thread();
 
  274   QProcess::ExitStatus exitStatus = QProcess::NormalExit;
 
  275   QProcess::ProcessError error = QProcess::UnknownError;
 
  277   std::function<void()> runFunction = [ 
this, &result, &exitStatus, &error, feedback]()
 
  284     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
 
  285     p.setProcessEnvironment( env );
 
  291     connect( qApp, &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit, Qt::DirectConnection );
 
  305     connect( &p, qgis::overload< int, QProcess::ExitStatus >::of( &QProcess::finished ), 
this, [&loop, &result, &exitStatus]( 
int res, QProcess::ExitStatus st )
 
  310     }, Qt::DirectConnection );
 
  312     connect( &p, &QProcess::readyReadStandardOutput, &p, [&p, 
this]
 
  314       QByteArray ba = p.readAllStandardOutput();
 
  315       mStdoutHandler( ba );
 
  317     connect( &p, &QProcess::readyReadStandardError, &p, [&p, 
this]
 
  319       QByteArray ba = p.readAllStandardError();
 
  320       mStderrHandler( ba );
 
  322     p.start( mProcess, mArguments, QProcess::Unbuffered | QProcess::ReadWrite );
 
  323     if ( !p.waitForStarted() )
 
  326       exitStatus = QProcess::NormalExit;
 
  334     mStdoutHandler( p.readAllStandardOutput() );
 
  335     mStderrHandler( p.readAllStandardError() );
 
  338   if ( requestMadeFromMainThread )
 
  340     std::unique_ptr<ProcessThread> processThread = qgis::make_unique<ProcessThread>( runFunction );
 
  341     processThread->start();
 
  343     processThread->wait();
 
  350   mExitStatus = exitStatus;
 
  351   mProcessError = error;
 
  355 QProcess::ExitStatus QgsBlockingProcess::exitStatus()
 const 
  360 QProcess::ProcessError QgsBlockingProcess::processError()
 const 
  362   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.