Skip to content

Commit fc8fd1e

Browse files
committedFeb 13, 2019
[processing] When converting models to python, correctly use a
multi-step feedback object to give scripts accurate progress reports And also add in checks for cancelation between child algorithm execution to allow generated scripts to early exit
1 parent 1e431f2 commit fc8fd1e

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed
 

‎src/core/processing/models/qgsprocessingmodelalgorithm.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,21 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
373373

374374
const QString algorithmClassName = safeName( name() );
375375

376+
QSet< QString > toExecute;
377+
for ( auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
378+
{
379+
if ( childIt->isActive() && childIt->algorithm() )
380+
toExecute.insert( childIt->childId() );
381+
}
382+
const int totalSteps = toExecute.count();
383+
376384
switch ( outputType )
377385
{
378386
case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
379387
{
380388
lines << QStringLiteral( "from qgis.core import QgsProcessing" );
381389
lines << QStringLiteral( "from qgis.core import QgsProcessingAlgorithm" );
390+
lines << QStringLiteral( "from qgis.core import QgsProcessingMultiStepFeedback" );
382391
// add specific parameter type imports
383392
const auto params = parameterDefinitions();
384393
QStringList importLines; // not a set - we need regular ordering
@@ -405,8 +414,12 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
405414
}
406415

407416
lines << QString();
408-
lines << indent + QStringLiteral( "def processAlgorithm(self, parameters, context, feedback):" );
417+
lines << indent + QStringLiteral( "def processAlgorithm(self, parameters, context, model_feedback):" );
409418
currentIndent = indent + indent;
419+
420+
lines << currentIndent + QStringLiteral( "# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the" );
421+
lines << currentIndent + QStringLiteral( "# overall progress through the model" );
422+
lines << currentIndent + QStringLiteral( "feedback = QgsProcessingMultiStepFeedback(%1, model_feedback)" ).arg( totalSteps );
410423
break;
411424
}
412425
#if 0
@@ -450,15 +463,9 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
450463
lines << currentIndent + QStringLiteral( "results = {}" );
451464
lines << currentIndent + QStringLiteral( "outputs = {}" );
452465

453-
QSet< QString > toExecute;
454-
for ( auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
455-
{
456-
if ( childIt->isActive() && childIt->algorithm() )
457-
toExecute.insert( childIt->childId() );
458-
}
459-
460466
QSet< QString > executed;
461467
bool executedAlg = true;
468+
int currentStep = 0;
462469
while ( executedAlg && executed.count() < toExecute.count() )
463470
{
464471
executedAlg = false;
@@ -530,7 +537,15 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
530537
}
531538

532539
lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize );
533-
540+
currentStep++;
541+
if ( currentStep < totalSteps )
542+
{
543+
lines << QString();
544+
lines << currentIndent + QStringLiteral( "feedback.setCurrentStep(%1)" ).arg( currentStep );
545+
lines << currentIndent + QStringLiteral( "if feedback.isCanceled():" );
546+
lines << currentIndent + indent + QStringLiteral( "return {}" );
547+
lines << QString();
548+
}
534549
executed.insert( childId );
535550
}
536551
}

‎tests/src/analysis/testqgsprocessing.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6986,6 +6986,7 @@ void TestQgsProcessing::modelExecution()
69866986
QgsDebugMsg( actualParts.join( '\n' ) );
69876987
QStringList expectedParts = QStringLiteral( "from qgis.core import QgsProcessing\n"
69886988
"from qgis.core import QgsProcessingAlgorithm\n"
6989+
"from qgis.core import QgsProcessingMultiStepFeedback\n"
69896990
"from qgis.core import QgsProcessingParameterFeatureSource\n"
69906991
"from qgis.core import QgsProcessingParameterNumber\n"
69916992
"from qgis.core import QgsProcessingParameterFeatureSink\n"
@@ -7000,7 +7001,10 @@ void TestQgsProcessing::modelExecution()
70007001
" self.addParameter(QgsProcessingParameterFeatureSink('cx1:MODEL_OUT_LAYER', '', type=QgsProcessing.TypeVectorPolygon, createByDefault=True, defaultValue=None))\n"
70017002
" self.addParameter(QgsProcessingParameterFeatureSink('cx3:MY_OUT', '', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))\n"
70027003
"\n"
7003-
" def processAlgorithm(self, parameters, context, feedback):\n"
7004+
" def processAlgorithm(self, parameters, context, model_feedback):\n"
7005+
" # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the\n"
7006+
" # overall progress through the model\n"
7007+
" feedback = QgsProcessingMultiStepFeedback(3, model_feedback)\n"
70047008
" results = {}\n"
70057009
" outputs = {}\n"
70067010
" alg_params = {\n"
@@ -7014,11 +7018,21 @@ void TestQgsProcessing::modelExecution()
70147018
" }\n"
70157019
" outputs['cx1'] = processing.run('native:buffer', alg_params, context=context, feedback=feedback, is_child_algorithm=True)\n"
70167020
" results['cx1:MODEL_OUT_LAYER'] = outputs['cx1']['OUTPUT']\n"
7021+
"\n"
7022+
" feedback.setCurrentStep(1)\n"
7023+
" if feedback.isCanceled():\n"
7024+
" return {}\n"
7025+
"\n"
70177026
" alg_params = {\n"
70187027
" 'INPUT': outputs['cx1']['OUTPUT'],\n"
70197028
" 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT\n"
70207029
" }\n"
70217030
" outputs['cx2'] = processing.run('native:centroids', alg_params, context=context, feedback=feedback, is_child_algorithm=True)\n"
7031+
"\n"
7032+
" feedback.setCurrentStep(2)\n"
7033+
" if feedback.isCanceled():\n"
7034+
" return {}\n"
7035+
"\n"
70227036
" alg_params = {\n"
70237037
" 'EXPRESSION': 'true',\n"
70247038
" 'INPUT': outputs['cx1']['OUTPUT'],\n"

0 commit comments

Comments
 (0)
Please sign in to comment.