|
@@ -20,6 +20,7 @@
|
|
|
=============================================================================*/
|
|
|
|
|
|
#include "ctkCmdLineModuleProcessTask.h"
|
|
|
+#include "ctkCmdLineModuleProcessWatcher_p.h"
|
|
|
#include "ctkCmdLineModuleRunException.h"
|
|
|
#include "ctkCmdLineModuleXmlProgressWatcher.h"
|
|
|
#include "ctkCmdLineModuleFuture.h"
|
|
@@ -29,124 +30,21 @@
|
|
|
#include <QThreadPool>
|
|
|
#include <QProcess>
|
|
|
|
|
|
-#ifdef Q_OS_UNIX
|
|
|
-#include <signal.h>
|
|
|
-#endif
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-ctkCmdLineModuleProcessWatcher::ctkCmdLineModuleProcessWatcher(QProcess& process, const QString& location,
|
|
|
- ctkCmdLineModuleFutureInterface &futureInterface)
|
|
|
- : process(process), location(location), futureInterface(futureInterface), processXmlWatcher(&process),
|
|
|
- processPaused(false), progressValue(0)
|
|
|
-{
|
|
|
- futureInterface.setProgressRange(0, 1000);
|
|
|
-
|
|
|
- connect(&processXmlWatcher, SIGNAL(filterStarted(QString,QString)), SLOT(filterStarted(QString,QString)));
|
|
|
- connect(&processXmlWatcher, SIGNAL(filterProgress(float)), SLOT(filterProgress(float)));
|
|
|
- connect(&processXmlWatcher, SIGNAL(filterFinished(QString)), SLOT(filterFinished(QString)));
|
|
|
- connect(&processXmlWatcher, SIGNAL(filterXmlError(QString)), SLOT(filterXmlError(QString)));
|
|
|
-
|
|
|
- connect(&futureWatcher, SIGNAL(canceled()), SLOT(cancelProcess()));
|
|
|
-#ifdef Q_OS_UNIX
|
|
|
- connect(&futureWatcher, SIGNAL(resumed()), SLOT(resumeProcess()));
|
|
|
- // Due to Qt bug 12152, we cannot listen to the "paused" signal because it is
|
|
|
- // not emitted directly when the QFuture is paused. Instead, it is emitted after
|
|
|
- // resuming the future, after the "resume" signal has been emitted...
|
|
|
- //connect(&futureWatcher, SIGNAL(paused()), SLOT(pauseProcess()));
|
|
|
- connect(&pollPauseTimer, SIGNAL(timeout()), this, SLOT(pauseProcess()));
|
|
|
- pollPauseTimer.start(500);
|
|
|
-#endif
|
|
|
- futureWatcher.setFuture(futureInterface.future());
|
|
|
-}
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::filterStarted(const QString& name, const QString& comment)
|
|
|
-{
|
|
|
- Q_UNUSED(comment)
|
|
|
- futureInterface.setProgressValueAndText(incrementProgress(), name);
|
|
|
-}
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::filterProgress(float progress)
|
|
|
-{
|
|
|
- futureInterface.setProgressValue(updateProgress(progress));
|
|
|
-}
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::filterFinished(const QString& name)
|
|
|
-{
|
|
|
- futureInterface.setProgressValueAndText(incrementProgress(), "Finished: " + name);
|
|
|
-}
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::filterXmlError(const QString &error)
|
|
|
-{
|
|
|
- qDebug().nospace() << "[Module " << location << "]: " << error;
|
|
|
-}
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::pauseProcess()
|
|
|
-{
|
|
|
- if (processPaused || !futureInterface.isPaused()) return;
|
|
|
-
|
|
|
-#ifdef Q_OS_UNIX
|
|
|
- if (::kill(process.pid(), SIGSTOP))
|
|
|
- {
|
|
|
- // error
|
|
|
- futureInterface.setPaused(false);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- processPaused = true;
|
|
|
- }
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::resumeProcess()
|
|
|
-{
|
|
|
- if (!processPaused) return;
|
|
|
-
|
|
|
-#ifdef Q_OS_UNIX
|
|
|
- if(::kill(process.pid(), SIGCONT))
|
|
|
- {
|
|
|
- // error
|
|
|
- futureInterface.setPaused(true);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- processPaused = false;
|
|
|
- }
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
//----------------------------------------------------------------------------
|
|
|
-void ctkCmdLineModuleProcessWatcher::cancelProcess()
|
|
|
+struct ctkCmdLineModuleProcessTaskPrivate
|
|
|
{
|
|
|
- process.terminate();
|
|
|
-}
|
|
|
-
|
|
|
-int ctkCmdLineModuleProcessWatcher::updateProgress(float progress)
|
|
|
-{
|
|
|
- progressValue = static_cast<int>(progress * 1000.0f);
|
|
|
- // normalize the value to lie between 0 and 1000.
|
|
|
- // 0 is reported when the process starts and 1000 is reserved for
|
|
|
- // reporting completion + standard output text
|
|
|
- if (progressValue < 1) progressValue = 1;
|
|
|
- if (progressValue > 999) progressValue = 999;
|
|
|
- return progressValue;
|
|
|
-}
|
|
|
+ ctkCmdLineModuleProcessTaskPrivate(const QString& location, const QStringList& args)
|
|
|
+ : Location(location)
|
|
|
+ , Args(args)
|
|
|
+ {}
|
|
|
|
|
|
-//----------------------------------------------------------------------------
|
|
|
-int ctkCmdLineModuleProcessWatcher::incrementProgress()
|
|
|
-{
|
|
|
- if (++progressValue > 999) progressValue = 999;
|
|
|
- return progressValue;
|
|
|
-}
|
|
|
+ const QString Location;
|
|
|
+ const QStringList Args;
|
|
|
+};
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
ctkCmdLineModuleProcessTask::ctkCmdLineModuleProcessTask(const QString& location, const QStringList& args)
|
|
|
- : location(location), args(args)
|
|
|
+ : d(new ctkCmdLineModuleProcessTaskPrivate(location, args))
|
|
|
{
|
|
|
this->setCanCancel(true);
|
|
|
#ifdef Q_OS_UNIX
|
|
@@ -185,20 +83,20 @@ void ctkCmdLineModuleProcessTask::run()
|
|
|
QObject::connect(&process, SIGNAL(finished(int)), &localLoop, SLOT(quit()));
|
|
|
QObject::connect(&process, SIGNAL(error(QProcess::ProcessError)), &localLoop, SLOT(quit()));
|
|
|
|
|
|
- process.start(location, args);
|
|
|
+ process.start(d->Location, d->Args);
|
|
|
|
|
|
- ctkCmdLineModuleProcessWatcher progressWatcher(process, location, *this);
|
|
|
+ ctkCmdLineModuleProcessWatcher progressWatcher(process, d->Location, *this);
|
|
|
Q_UNUSED(progressWatcher)
|
|
|
|
|
|
localLoop.exec();
|
|
|
|
|
|
if (process.error() != QProcess::UnknownError)
|
|
|
{
|
|
|
- this->reportException(ctkCmdLineModuleRunException(location, process.exitCode(), process.errorString()));
|
|
|
+ this->reportException(ctkCmdLineModuleRunException(d->Location, process.exitCode(), process.errorString()));
|
|
|
}
|
|
|
else if (process.exitCode() != 0)
|
|
|
{
|
|
|
- this->reportException(ctkCmdLineModuleRunException(location, process.exitCode(), process.readAllStandardError()));
|
|
|
+ this->reportException(ctkCmdLineModuleRunException(d->Location, process.exitCode(), process.readAllStandardError()));
|
|
|
}
|
|
|
|
|
|
this->setProgressValueAndText(1000, process.readAllStandardError());
|