Add temporary layer store to processing context

This temporary layer store (a QgsProject) is used as a
store for layers that are added if a parameter that
is evaluated to a layer requires that a new, non-active-project
layer is loaded. It means that these layers will remain accessible
for the duration of the algorithm's execution (or models
execution if an algorithm is run as part of a model), before
being automatically discarded when the QgsProcessingContext
used to run the algorithm/model goes out of scope.

This approach has several benefits:
- it means that algorithms (including c++ algorithms) are able
to use both project and non-project layers without needing
to handle any memory management themselves.
- it means that layers are guaranteed to last for the duration
of a model execution. This is currently an issue where models
which use memory layers as intermediate outputs do not
function correctly as the memory layers are destroyed before
the model has finished executing
- there should be no leakage of layers remaining open
after an algorithm exits
This commit is contained in:
Nyall Dawson 2017-04-26 14:06:59 +10:00
parent 5169e0db65
commit 6b4ddb3b0d
2 changed files with 25 additions and 0 deletions

View File

@ -37,6 +37,7 @@ class QgsProcessingContext
Constructor for QgsProcessingContext.
%End
// QgsProcessingContext &operator=( const QgsProcessingContext &other ) = delete;
QgsProcessingContext::Flags flags() const;
%Docstring
Returns any flags set in the context.
@ -74,6 +75,9 @@ class QgsProcessingContext
Sets the expression ``context``.
%End
QgsFeatureRequest::InvalidGeometryCheck invalidGeometryCheck() const;
%Docstring
Returns the behavior used for checking invalid geometries in input layers.
@ -110,6 +114,8 @@ class QgsProcessingContext
%End
private:
QgsProcessingContext( const QgsProcessingContext &other );
};
QFlags<QgsProcessingContext::Flag> operator|(QgsProcessingContext::Flag f1, QFlags<QgsProcessingContext::Flag> f2);

View File

@ -50,6 +50,9 @@ class CORE_EXPORT QgsProcessingContext
*/
QgsProcessingContext() = default;
QgsProcessingContext( const QgsProcessingContext &other ) = delete;
QgsProcessingContext &operator=( const QgsProcessingContext &other ) = delete;
/**
* Returns any flags set in the context.
* \see setFlags()
@ -84,6 +87,17 @@ class CORE_EXPORT QgsProcessingContext
*/
void setExpressionContext( const QgsExpressionContext &context ) { mExpressionContext = context; }
///@cond NOT_STABLE_API
/**
* Returns a reference to the project used for storing temporary layers during
* algorithm execution.
* \note not available in Python bindings
*/
SIP_SKIP QgsProject &temporaryLayerStore() { return tempProject; }
///@endcond
/**
* Returns the behavior used for checking invalid geometries in input layers.
* \see setInvalidGeometryCheck()
@ -135,10 +149,15 @@ class CORE_EXPORT QgsProcessingContext
QgsProcessingContext::Flags mFlags = 0;
QPointer< QgsProject > mProject;
//! Temporary project owned by the context, used for storing temporarily loaded map layers
QgsProject tempProject;
QgsExpressionContext mExpressionContext;
QgsFeatureRequest::InvalidGeometryCheck mInvalidGeometryCheck = QgsFeatureRequest::GeometryNoCheck;
std::function< void( const QgsFeature & ) > mInvalidGeometryCallback;
#ifdef SIP_RUN
QgsProcessingContext( const QgsProcessingContext &other );
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsProcessingContext::Flags )