Skip to content

Commit 6afe25e

Browse files
committedSep 22, 2017
[processing] Proper progress reports during model execution
Instead of showing the progress reports for each child algorithm individually, which leads to repeated 0->100% progress for every step of a model, we proxy the progress reports and account for the overall progress through a model as well. This means that the progress accounts for both the progress within the current model step AND the total number of steps left to execute.
1 parent 9caa722 commit 6afe25e

File tree

6 files changed

+138
-16
lines changed

6 files changed

+138
-16
lines changed
 

‎python/core/processing/models/qgsprocessingmodelalgorithm.sip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ Translated description of variable
374374
};
375375

376376

377+
378+
377379
/************************************************************************
378380
* This file has been generated automatically from *
379381
* *

‎python/core/qgsfeedback.sip

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ class QgsFeedback : QObject
3838
QgsFeedback( QObject *parent /TransferThis/ = 0 );
3939
%Docstring
4040
Construct a feedback object
41-
%End
42-
43-
void cancel();
44-
%Docstring
45-
Tells the internal routines that the current operation should be canceled. This should be run by the main thread
4641
%End
4742

4843
bool isCanceled() const;
@@ -71,6 +66,13 @@ Tells whether the operation has been canceled already
7166
:rtype: float
7267
%End
7368

69+
public slots:
70+
71+
void cancel();
72+
%Docstring
73+
Tells the internal routines that the current operation should be canceled. This should be run by the main thread
74+
%End
75+
7476
signals:
7577
void canceled();
7678
%Docstring

‎src/core/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ SET(QGIS_CORE_MOC_HDRS
682682
processing/qgsprocessingfeedback.h
683683
processing/qgsprocessingprovider.h
684684
processing/qgsprocessingregistry.h
685+
processing/models/qgsprocessingmodelalgorithm.h
685686

686687
providers/memory/qgsmemoryprovider.h
687688

@@ -978,7 +979,6 @@ SET(QGIS_CORE_HDRS
978979
processing/qgsprocessingoutputs.h
979980
processing/qgsprocessingparameters.h
980981
processing/qgsprocessingutils.h
981-
processing/models/qgsprocessingmodelalgorithm.h
982982
processing/models/qgsprocessingmodelchildalgorithm.h
983983
processing/models/qgsprocessingmodelchildparametersource.h
984984
processing/models/qgsprocessingmodelcomponent.h

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

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
214214
QTime totalTime;
215215
totalTime.start();
216216

217+
QgsProcessingModelFeedback modelFeedback( toExecute.count(), feedback );
217218
QgsExpressionContext baseContext = createExpressionContext( parameters, context );
218219

219220
QVariantMap childResults;
@@ -225,6 +226,9 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
225226
executedAlg = false;
226227
Q_FOREACH ( const QString &childId, toExecute )
227228
{
229+
if ( feedback && feedback->isCanceled() )
230+
break;
231+
228232
if ( executed.contains( childId ) )
229233
continue;
230234

@@ -260,7 +264,7 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
260264

261265
bool ok = false;
262266
std::unique_ptr< QgsProcessingAlgorithm > childAlg( child.algorithm()->create( child.configuration() ) );
263-
QVariantMap results = childAlg->run( childParams, context, feedback, &ok );
267+
QVariantMap results = childAlg->run( childParams, context, &modelFeedback, &ok );
264268
childAlg.reset( nullptr );
265269
if ( !ok )
266270
{
@@ -280,8 +284,12 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
280284
}
281285

282286
executed.insert( childId );
287+
modelFeedback.setCurrentStep( executed.count() );
283288
feedback->pushDebugInfo( QObject::tr( "OK. Execution took %1 s (%2 outputs)." ).arg( childTime.elapsed() / 1000.0 ).arg( results.count() ) );
284289
}
290+
291+
if ( feedback && feedback->isCanceled() )
292+
break;
285293
}
286294
feedback->pushDebugInfo( QObject::tr( "Model processed OK. Executed %1 algorithms total in %2 s." ).arg( executed.count() ).arg( totalTime.elapsed() / 1000.0 ) );
287295

@@ -1123,4 +1131,65 @@ QgsProcessingAlgorithm *QgsProcessingModelAlgorithm::createInstance() const
11231131
return alg;
11241132
}
11251133

1134+
1135+
1136+
1137+
//
1138+
// QgsProcessingModelFeedback
1139+
//
1140+
1141+
QgsProcessingModelFeedback::QgsProcessingModelFeedback( int childAlgorithmCount, QgsProcessingFeedback *feedback )
1142+
: mChildSteps( childAlgorithmCount )
1143+
, mFeedback( feedback )
1144+
{
1145+
connect( mFeedback, &QgsFeedback::canceled, this, &QgsFeedback::cancel, Qt::DirectConnection );
1146+
connect( this, &QgsFeedback::progressChanged, this, &QgsProcessingModelFeedback::updateOverallProgress );
1147+
}
1148+
1149+
void QgsProcessingModelFeedback::setCurrentStep( int step )
1150+
{
1151+
mCurrentStep = step;
1152+
mFeedback->setProgress( 100.0 * static_cast< double >( mCurrentStep ) / mChildSteps );
1153+
}
1154+
1155+
void QgsProcessingModelFeedback::setProgressText( const QString &text )
1156+
{
1157+
mFeedback->setProgressText( text );
1158+
}
1159+
1160+
void QgsProcessingModelFeedback::reportError( const QString &error )
1161+
{
1162+
mFeedback->reportError( error );
1163+
}
1164+
1165+
void QgsProcessingModelFeedback::pushInfo( const QString &info )
1166+
{
1167+
mFeedback->pushInfo( info );
1168+
}
1169+
1170+
void QgsProcessingModelFeedback::pushCommandInfo( const QString &info )
1171+
{
1172+
mFeedback->pushCommandInfo( info );
1173+
}
1174+
1175+
void QgsProcessingModelFeedback::pushDebugInfo( const QString &info )
1176+
{
1177+
mFeedback->pushDebugInfo( info );
1178+
}
1179+
1180+
void QgsProcessingModelFeedback::pushConsoleInfo( const QString &info )
1181+
{
1182+
mFeedback->pushConsoleInfo( info );
1183+
}
1184+
1185+
void QgsProcessingModelFeedback::updateOverallProgress( double progress )
1186+
{
1187+
double baseProgress = 100.0 * static_cast< double >( mCurrentStep ) / mChildSteps;
1188+
double currentAlgorithmProgress = progress / mChildSteps;
1189+
mFeedback->setProgress( baseProgress + currentAlgorithmProgress );
1190+
}
1191+
1192+
1193+
11261194
///@endcond
1195+

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,53 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
403403
friend class TestQgsProcessing;
404404
};
405405

406+
407+
#ifndef SIP_RUN
408+
409+
/**
410+
* Model algorithm feedback which proxies its calls to an underlying
411+
* feedback object, but scales overall progress reports to account
412+
* for the number of child steps in a model.
413+
*/
414+
class QgsProcessingModelFeedback : public QgsProcessingFeedback
415+
{
416+
Q_OBJECT
417+
418+
public:
419+
420+
/**
421+
* Constructor for QgsProcessingModelFeedback, for a model with the specified
422+
* number of active child algorithms. This feedback object will proxy calls
423+
* to the specified \a feedback object.
424+
*/
425+
QgsProcessingModelFeedback( int childAlgorithmCount, QgsProcessingFeedback *feedback );
426+
427+
/**
428+
* Sets the current child algorithm \a step which is being executed. This is used
429+
* to scale the overall progress to account for progress through the overall model.
430+
*/
431+
void setCurrentStep( int step );
432+
433+
void setProgressText( const QString &text ) override;
434+
void reportError( const QString &error ) override;
435+
void pushInfo( const QString &info ) override;
436+
void pushCommandInfo( const QString &info ) override;
437+
void pushDebugInfo( const QString &info ) override;
438+
void pushConsoleInfo( const QString &info ) override;
439+
440+
private slots:
441+
442+
void updateOverallProgress( double progress );
443+
444+
private:
445+
446+
int mChildSteps = 0;
447+
int mCurrentStep = 0;
448+
QgsProcessingFeedback *mFeedback = nullptr;
449+
};
450+
451+
#endif
452+
406453
///@endcond
407454

408455
#endif // QGSPROCESSINGMODELALGORITHM_H

‎src/core/qgsfeedback.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,6 @@ class CORE_EXPORT QgsFeedback : public QObject
5050
, mCanceled( false )
5151
{}
5252

53-
//! Tells the internal routines that the current operation should be canceled. This should be run by the main thread
54-
void cancel()
55-
{
56-
if ( mCanceled )
57-
return; // only emit the signal once
58-
mCanceled = true;
59-
emit canceled();
60-
}
61-
6253
//! Tells whether the operation has been canceled already
6354
bool isCanceled() const { return mCanceled; }
6455

@@ -88,6 +79,17 @@ class CORE_EXPORT QgsFeedback : public QObject
8879
*/
8980
double progress() const { return mProgress; }
9081

82+
public slots:
83+
84+
//! Tells the internal routines that the current operation should be canceled. This should be run by the main thread
85+
void cancel()
86+
{
87+
if ( mCanceled )
88+
return; // only emit the signal once
89+
mCanceled = true;
90+
emit canceled();
91+
}
92+
9193
signals:
9294
//! Internal routines can connect to this signal if they use event loop
9395
void canceled();

0 commit comments

Comments
 (0)
Please sign in to comment.