// Excerpt: RDisagg.Delegate.cpp, 4-20-2012 // private slot bool RDisagg::Delegate::executeRScript (const QString& scriptStr, QString& resultMsg, int& msecsRet) const { static const char* mname ("RDisagg::Delegate::executeRScript"); // DIAG() << mname; Delegate* mutableThis = const_cast (this); resultMsg = ""; msecsRet = 0; // clear execution time display. _ui._execProgressDispLineEdit->setText (""); // ********************************************* // *** (1) Open "R" Script File for Writing *** // ********************************************* const QString plugDir = UtilsNS::pluginDir(); const QFileInfo scriptFileInfo (plugDir, "RDisagg.R"); const QString scriptPath = scriptFileInfo.absoluteFilePath(); QFile scriptFile (scriptPath); const bool openScriptOk = scriptFile.open (QIODevice::WriteOnly); if (!openScriptOk) { DIAG() << mname << " ERROR Opening '" << qPrintable (scriptPath) << "'"; QApplication::beep(); return (false); // failure //----------->> } // DIAG() << mname << " Opened '" << qPrintable (scriptPath) << "'"; // ***************************************** // *** (2) Prepare Script Response File *** // ***************************************** const QFileInfo scriptRespFileInfo (plugDir, ResultFileName); _scriptOutPath = scriptRespFileInfo.absoluteFilePath(); QFile scriptOutFile (_scriptOutPath); if (scriptOutFile.exists()) { const bool removeOk = scriptOutFile.remove(); if (!removeOk) { DIAG() << mname << " ERROR Removing '" << qPrintable (_scriptOutPath) << "'"; QApplication::beep(); return (false); // failure //----------->> } } // ********************************** // *** (3) Write "R" Script File *** // ********************************** // Script Header Comment String QString headerCmtStr = "# RDisagg.R script. Generated: "; headerCmtStr += QDateTime::currentDateTime().toString(); headerCmtStr += "\n"; QString scriptStr2 = scriptStr; scriptStr2.replace (SYM_SCRIPT_OUT_PATH, _scriptOutPath); _recentScriptStr = scriptStr2; scriptFile.write (qPrintable (headerCmtStr)); scriptFile.write (qPrintable (scriptStr2)); scriptFile.close(); // **************************************** // *** (4) Execute the "R" Script File *** // **************************************** _stopRequested = false; _running = true; mutableThis->updateWidgets(); static const QString cmdStrFmt ("Rscript --slave %1"); const QString cmdStr = cmdStrFmt .arg (scriptPath); QProcess cmdProc (mutableThis); cmdProc.start (cmdStr); // Use an actual QTime for a more precise timing. QTime procTime; procTime.start(); double secs (0.0); bool didFinish (false); int waitCount (0); while (!didFinish) { didFinish = cmdProc.waitForFinished (100); // milliseconds ++waitCount; const int tenthSecs = (int) (procTime.elapsed() / 100.0); secs = double (tenthSecs / 10.0); _ui._execProgressDispLineEdit->setText (QString::number (secs)); QApplication::processEvents (QEventLoop::AllEvents, 20); // maxtime, milliseconds if (_stopRequested || (!NO_TIMEOUT && (secs > TIMEOUT_SECS))) { cmdProc.kill(); break; //------ } } _running = false; mutableThis->updateWidgets(); msecsRet = int (secs * 1000.0); const QProcess::ExitStatus exStat = cmdProc.exitStatus(); const QString stdOutTxt = cmdProc.readAllStandardOutput(); const QString stdErrTxt = cmdProc.readAllStandardError(); // ******************************* // *** (5) Read Script Result *** // ******************************* // SIDE EFFECT: Computes QString _scriptOutPath, if undefined. bool resultFileExists (false); // tentative const QString resultFileStr = resultFileText (&resultFileExists); if (!didFinish) { // *********************************** // *** Did Not Finish Successfully *** // *********************************** resultMsg = "DID NOT FINISH, ExitStatus: ["; resultMsg += QString::number ((int) exStat) + "] "; resultMsg += ((exStat == QProcess::NormalExit) ? "NORMAL" : "CRASH"); } if (!resultFileExists) { resultMsg += QString ("\n\nERROR Result File Missing '%1'") .arg (_scriptOutPath); } else { resultMsg += "\n\nRESULT ...\n"; resultMsg += resultFileStr; } static const QString SuccessStr ("FUNCTION STATUS: SUCCESS"); const bool successFound = resultMsg.contains (SuccessStr); if (!successFound || !didFinish || DEBUG_INCLUDE_STD_OUT) { resultMsg += "\n\nSTANDARD OUT ...\n"; resultMsg += stdOutTxt; } if (!successFound || !didFinish || DEBUG_INCLUDE_STD_ERR) { resultMsg += "\n\nSTANDARD ERROR ...\n"; resultMsg += stdErrTxt; } resultMsg = resultMsg.trimmed(); return (didFinish && successFound); }