Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add a pure virtual clone method for algorithms
This is required for safely executing the algorithm in a background
thread.
  • Loading branch information
nyalldawson committed Jul 6, 2017
1 parent 603168e commit 9156933
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 6 deletions.
7 changes: 7 additions & 0 deletions python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -43,6 +43,13 @@ class QgsProcessingAlgorithm
virtual ~QgsProcessingAlgorithm();



virtual QgsProcessingAlgorithm *clone() const = 0 /Factory/;
%Docstring
Clones the algorithm, returning a new copy for safe use in background threads.
:rtype: QgsProcessingAlgorithm
%End

virtual QString name() const = 0;
%Docstring
Returns the algorithm name, used for identifying the algorithm. This string
Expand Down
2 changes: 2 additions & 0 deletions python/core/processing/qgsprocessingmodelalgorithm.sip
Expand Up @@ -588,6 +588,8 @@ Copies are protected to avoid slicing

virtual QString asPythonCommand( const QVariantMap &parameters, QgsProcessingContext &context ) const;

virtual QgsProcessingModelAlgorithm *clone() const /Factory/;


void setName( const QString &name );
%Docstring
Expand Down
8 changes: 4 additions & 4 deletions python/plugins/processing/modeler/ModelerDialog.py
Expand Up @@ -237,9 +237,9 @@ def _mimeDataAlgorithm(items):
self.mActionRun.triggered.connect(self.runModel)

if model is not None:
self.model = model
self.textGroup.setText(model.group())
self.textName.setText(model.displayName())
self.model = model.clone()
self.textGroup.setText(self.model.group())
self.textName.setText(self.model.displayName())
self.repaintModel()

else:
Expand Down Expand Up @@ -440,7 +440,7 @@ def saveModel(self, saveAs):
return
self.model.setName(str(self.textName.text()))
self.model.setGroup(str(self.textGroup.text()))
if self.model.sourceFilePath() is not None and not saveAs:
if self.model.sourceFilePath() and not saveAs:
filename = self.model.sourceFilePath()
else:
filename, filter = QFileDialog.getSaveFileName(self,
Expand Down
45 changes: 45 additions & 0 deletions src/core/processing/qgsnativealgorithms.cpp
Expand Up @@ -84,6 +84,11 @@ QString QgsCentroidAlgorithm::shortHelpString() const
"The attributes associated to each point in the output layer are the same ones associated to the original features." );
}

QgsCentroidAlgorithm *QgsCentroidAlgorithm::clone() const
{
return new QgsCentroidAlgorithm();
}

QVariantMap QgsCentroidAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -159,6 +164,11 @@ QString QgsBufferAlgorithm::shortHelpString() const
"The mitre limit parameter is only applicable for mitre join styles, and controls the maximum distance from the offset curve to use when creating a mitred join." );
}

QgsBufferAlgorithm *QgsBufferAlgorithm::clone() const
{
return new QgsBufferAlgorithm();
}

QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -263,6 +273,11 @@ QString QgsDissolveAlgorithm::shortHelpString() const
"In case the input is a polygon layer, common boundaries of adjacent polygons being dissolved will get erased." );
}

QgsDissolveAlgorithm *QgsDissolveAlgorithm::clone() const
{
return new QgsDissolveAlgorithm();
}

QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -406,6 +421,11 @@ QString QgsClipAlgorithm::shortHelpString() const
"be manually updated." );
}

QgsClipAlgorithm *QgsClipAlgorithm::clone() const
{
return new QgsClipAlgorithm();
}

QVariantMap QgsClipAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > featureSource( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -554,6 +574,11 @@ QString QgsTransformAlgorithm::shortHelpString() const
"Attributes are not modified by this algorithm." );
}

QgsTransformAlgorithm *QgsTransformAlgorithm::clone() const
{
return new QgsTransformAlgorithm();
}

QVariantMap QgsTransformAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -618,6 +643,11 @@ QString QgsSubdivideAlgorithm::shortHelpString() const
"Curved geometries will be segmentized before subdivision." );
}

QgsSubdivideAlgorithm *QgsSubdivideAlgorithm::clone() const
{
return new QgsSubdivideAlgorithm();
}

QVariantMap QgsSubdivideAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -684,6 +714,11 @@ QString QgsMultipartToSinglepartAlgorithm::shortHelpString() const
"contain, and the same attributes are used for each of them." );
}

QgsMultipartToSinglepartAlgorithm *QgsMultipartToSinglepartAlgorithm::clone() const
{
return new QgsMultipartToSinglepartAlgorithm();
}

QVariantMap QgsMultipartToSinglepartAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -766,6 +801,11 @@ QString QgsExtractByExpressionAlgorithm::shortHelpString() const
"For more information about expressions see the <a href =\"{qgisdocs}/user_manual/working_with_vector/expression.html\">user manual</a>" );
}

QgsExtractByExpressionAlgorithm *QgsExtractByExpressionAlgorithm::clone() const
{
return new QgsExtractByExpressionAlgorithm();
}

QVariantMap QgsExtractByExpressionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down Expand Up @@ -892,6 +932,11 @@ QString QgsExtractByAttributeAlgorithm::shortHelpString() const
"of an attribute from the input layer." );
}

QgsExtractByAttributeAlgorithm *QgsExtractByAttributeAlgorithm::clone() const
{
return new QgsExtractByAttributeAlgorithm();
}

QVariantMap QgsExtractByAttributeAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
Expand Down
9 changes: 9 additions & 0 deletions src/core/processing/qgsnativealgorithms.h
Expand Up @@ -60,6 +60,7 @@ class QgsCentroidAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "centroid,center,average,point,middle" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry tools" ); }
QString shortHelpString() const override;
QgsCentroidAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -83,6 +84,7 @@ class QgsTransformAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "transform,reproject,crs,srs,warp" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector general tools" ); }
QString shortHelpString() const override;
QgsTransformAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -106,6 +108,7 @@ class QgsBufferAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "buffer,grow" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry tools" ); }
QString shortHelpString() const override;
QgsBufferAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -129,6 +132,7 @@ class QgsDissolveAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "dissolve,union,combine,collect" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry tools" ); }
QString shortHelpString() const override;
QgsDissolveAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand Down Expand Up @@ -167,6 +171,7 @@ class QgsExtractByAttributeAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "extract,filter,attribute,value,contains,null,field" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector selection tools" ); }
QString shortHelpString() const override;
QgsExtractByAttributeAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -190,6 +195,7 @@ class QgsExtractByExpressionAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "extract,filter,expression,field" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector selection tools" ); }
QString shortHelpString() const override;
QgsExtractByExpressionAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -213,6 +219,7 @@ class QgsClipAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "clip,intersect,intersection,mask" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector overlay tools" ); }
QString shortHelpString() const override;
QgsClipAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -237,6 +244,7 @@ class QgsSubdivideAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "subdivide,segmentize,split,tesselate" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry tools" ); }
QString shortHelpString() const override;
QgsSubdivideAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand All @@ -260,6 +268,7 @@ class QgsMultipartToSinglepartAlgorithm : public QgsProcessingAlgorithm
virtual QStringList tags() const override { return QObject::tr( "multi,single,multiple,split,dump" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry tools" ); }
QString shortHelpString() const override;
QgsMultipartToSinglepartAlgorithm *clone() const override SIP_FACTORY;

protected:

Expand Down
10 changes: 8 additions & 2 deletions src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -61,11 +61,17 @@ class CORE_EXPORT QgsProcessingAlgorithm

virtual ~QgsProcessingAlgorithm();

//! Algorithms cannot be copied

//! Algorithms cannot be copied - clone() should be used instead
QgsProcessingAlgorithm( const QgsProcessingAlgorithm &other ) = delete;
//! Algorithms cannot be copied
//! Algorithms cannot be copied- clone() should be used instead
QgsProcessingAlgorithm &operator=( const QgsProcessingAlgorithm &other ) = delete;

/**
* Clones the algorithm, returning a new copy for safe use in background threads.
*/
virtual QgsProcessingAlgorithm *clone() const = 0 SIP_FACTORY;

/**
* Returns the algorithm name, used for identifying the algorithm. This string
* should be fixed for the algorithm, and must not be localised. The name should
Expand Down
7 changes: 7 additions & 0 deletions src/core/processing/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -1101,6 +1101,13 @@ QString QgsProcessingModelAlgorithm::asPythonCommand( const QVariantMap &paramet
return QgsProcessingAlgorithm::asPythonCommand( parameters, context );
}

QgsProcessingModelAlgorithm *QgsProcessingModelAlgorithm::clone() const
{
QgsProcessingModelAlgorithm *alg = new QgsProcessingModelAlgorithm();
alg->loadVariant( toVariant() );
alg->setProvider( provider() );
return alg;
}

bool QgsProcessingModelAlgorithm::ChildParameterSource::operator==( const QgsProcessingModelAlgorithm::ChildParameterSource &other ) const
{
Expand Down
1 change: 1 addition & 0 deletions src/core/processing/qgsprocessingmodelalgorithm.h
Expand Up @@ -590,6 +590,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm

bool canExecute( QString *errorMessage SIP_OUT = nullptr ) const override;
QString asPythonCommand( const QVariantMap &parameters, QgsProcessingContext &context ) const override;
QgsProcessingModelAlgorithm *clone() const override SIP_FACTORY;

/**
* Sets the model \a name.
Expand Down
1 change: 1 addition & 0 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -46,6 +46,7 @@ class DummyAlgorithm : public QgsProcessingAlgorithm
QgsProcessingContext &, QgsProcessingFeedback * ) const override { return QVariantMap(); }

virtual Flags flags() const override { return mFlags; }
DummyAlgorithm *clone() const override { return new DummyAlgorithm( name() ); }

QString mName;

Expand Down

0 comments on commit 9156933

Please sign in to comment.