QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgsprocessingcontext.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingcontext.cpp
3 ----------------------
4 begin : April 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include "qgsprocessing.h"
21#include "qgsprocessingutils.h"
22#include "qgsproviderregistry.h"
23#include "qgsunittypes.h"
24
25//
26// QgsProcessingContext
27//
28
30 : mPreferredVectorFormat( QgsProcessingUtils::defaultVectorExtension() )
31 , mPreferredRasterFormat( QgsProcessingUtils::defaultRasterExtension() )
32{
33 auto callback = [this]( const QgsFeature & feature )
34 {
35 if ( mFeedback )
36 mFeedback->reportError( QObject::tr( "Encountered a transform error when reprojecting feature with id %1." ).arg( feature.id() ) );
37 };
38 mTransformErrorCallback = callback;
39 mExpressionContext.setLoadedLayerStore( &tempLayerStore );
40}
41
43{
44 for ( auto it = mLayersToLoadOnCompletion.constBegin(); it != mLayersToLoadOnCompletion.constEnd(); ++it )
45 {
46 delete it.value().postProcessor();
47 }
48}
49
51{
52 mExpressionContext = context;
53 // any layers temporarily loaded by expressions should use the same temporary layer store as this context
54 mExpressionContext.setLoadedLayerStore( &tempLayerStore );
55}
56
57void QgsProcessingContext::setLayersToLoadOnCompletion( const QMap<QString, QgsProcessingContext::LayerDetails> &layers )
58{
59 for ( auto it = mLayersToLoadOnCompletion.constBegin(); it != mLayersToLoadOnCompletion.constEnd(); ++it )
60 {
61 if ( !layers.contains( it.key() ) || layers.value( it.key() ).postProcessor() != it.value().postProcessor() )
62 delete it.value().postProcessor();
63 }
64 mLayersToLoadOnCompletion = layers;
65}
66
68{
69 if ( mLayersToLoadOnCompletion.contains( layer ) && mLayersToLoadOnCompletion.value( layer ).postProcessor() != details.postProcessor() )
70 delete mLayersToLoadOnCompletion.value( layer ).postProcessor();
71
72 mLayersToLoadOnCompletion.insert( layer, details );
73}
74
76{
77 mInvalidGeometryCheck = check;
78 mUseDefaultInvalidGeometryCallback = true;
79 mInvalidGeometryCallback = defaultInvalidGeometryCallbackForCheck( check );
80}
81
82std::function<void ( const QgsFeature & )> QgsProcessingContext::invalidGeometryCallback( QgsFeatureSource *source ) const
83{
84 if ( mUseDefaultInvalidGeometryCallback )
85 return defaultInvalidGeometryCallbackForCheck( mInvalidGeometryCheck, source );
86 else
87 return mInvalidGeometryCallback;
88}
89
91{
92 const QString sourceName = source ? source->sourceName() : QString();
93 switch ( check )
94 {
96 {
97 auto callback = [sourceName]( const QgsFeature & feature )
98 {
99 if ( !sourceName.isEmpty() )
100 throw QgsProcessingException( QObject::tr( "Feature (%1) from “%2” has invalid geometry. Please fix the geometry or change the “Invalid features filtering” option for this input or globally in Processing settings." ).arg( feature.id() ).arg( sourceName ) );
101 else
102 throw QgsProcessingException( QObject::tr( "Feature (%1) has invalid geometry. Please fix the geometry or change the “Invalid features filtering” option for input layers or globally in Processing settings." ).arg( feature.id() ) );
103 };
104 return callback;
105 }
106
108 {
109 auto callback = [this, sourceName]( const QgsFeature & feature )
110 {
111 if ( mFeedback )
112 {
113 if ( !sourceName.isEmpty() )
114 mFeedback->reportError( QObject::tr( "Feature (%1) from “%2” has invalid geometry and has been skipped. Please fix the geometry or change the “Invalid features filtering” option for this input or globally in Processing settings." ).arg( feature.id() ).arg( sourceName ) );
115 else
116 mFeedback->reportError( QObject::tr( "Feature (%1) has invalid geometry and has been skipped. Please fix the geometry or change the “Invalid features filtering” option for input layers or globally in Processing settings." ).arg( feature.id() ) );
117 }
118 };
119 return callback;
120 }
121
123 return nullptr;
124 }
125 return nullptr;
126}
127
129{
130 setLayersToLoadOnCompletion( context.mLayersToLoadOnCompletion );
131 mModelResult = context.mModelResult;
132 context.mLayersToLoadOnCompletion.clear();
133 tempLayerStore.transferLayersFromStore( context.temporaryLayerStore() );
134}
135
137{
138 return QgsProcessingUtils::mapLayerFromString( identifier, *this, false );
139}
140
142{
143 return tempLayerStore.takeMapLayer( tempLayerStore.mapLayer( id ) );
144}
145
147{
148 return mLogLevel;
149}
150
152{
153 mLogLevel = level;
154}
155
157{
158 return mTemporaryFolderOverride;
159}
160
161void QgsProcessingContext::setTemporaryFolder( const QString &folder )
162{
163 mTemporaryFolderOverride = folder;
164}
165
167{
168 return mMaximumThreads;
169}
170
172{
173 mMaximumThreads = threads;
174}
175
177{
178 QVariantMap res;
179 if ( mDistanceUnit != Qgis::DistanceUnit::Unknown )
180 res.insert( QStringLiteral( "distance_units" ), QgsUnitTypes::encodeUnit( mDistanceUnit ) );
181 if ( mAreaUnit != Qgis::AreaUnit::Unknown )
182 res.insert( QStringLiteral( "area_units" ), QgsUnitTypes::encodeUnit( mAreaUnit ) );
183 if ( !mEllipsoid.isEmpty() )
184 res.insert( QStringLiteral( "ellipsoid" ), mEllipsoid );
185 if ( mProject )
186 res.insert( QStringLiteral( "project_path" ), mProject->fileName() );
187
188 return res;
189}
190
192{
193 auto escapeIfNeeded = []( const QString & input ) -> QString
194 {
195 // play it safe and escape everything UNLESS it's purely alphanumeric characters (and a very select scattering of other common characters!)
196 const thread_local QRegularExpression nonAlphaNumericRx( QStringLiteral( "[^a-zA-Z0-9.\\-/_]" ) );
197 if ( nonAlphaNumericRx.match( input ).hasMatch() )
198 {
199 QString escaped = input;
200 escaped.replace( '\'', QLatin1String( "'\\''" ) );
201 return QStringLiteral( "'%1'" ).arg( escaped );
202 }
203 else
204 {
205 return input;
206 }
207 };
208
209 QStringList res;
210 if ( mDistanceUnit != Qgis::DistanceUnit::Unknown )
211 res << QStringLiteral( "--distance_units=%1" ).arg( QgsUnitTypes::encodeUnit( mDistanceUnit ) );
212 if ( mAreaUnit != Qgis::AreaUnit::Unknown )
213 res << QStringLiteral( "--area_units=%1" ).arg( QgsUnitTypes::encodeUnit( mAreaUnit ) );
214 if ( !mEllipsoid.isEmpty() )
215 res << QStringLiteral( "--ellipsoid=%1" ).arg( mEllipsoid );
216
218 {
219 res << QStringLiteral( "--project_path=%1" ).arg( escapeIfNeeded( mProject->fileName() ) );
220 }
221
222 return res;
223}
224
226{
227 return mCurrentTimeRange;
228}
229
234
236{
237 return mEllipsoid;
238}
239
241{
242 mEllipsoid = ellipsoid;
243}
244
246{
247 return mDistanceUnit;
248}
249
251{
252 mDistanceUnit = unit;
253}
254
256{
257 return mAreaUnit;
258}
259
264
269
271{
272 if ( mPostProcessor && mPostProcessor != processor )
273 delete mPostProcessor;
274
275 mPostProcessor = processor;
276}
277
279{
280 if ( !layer )
281 return;
282
283 const bool preferFilenameAsLayerName = QgsProcessing::settingsPreferFilenameAsLayerName->value();
284
285 // note - for temporary layers, we don't use the filename, regardless of user setting (it will be meaningless!)
286 if ( ( !forceName && preferFilenameAsLayerName && !layer->isTemporary() ) || name.isEmpty() )
287 {
288 const QVariantMap sourceParts = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->source() );
289 const QString layerName = sourceParts.value( QStringLiteral( "layerName" ) ).toString();
290 // if output layer name exists, use that!
291 if ( !layerName.isEmpty() )
292 layer->setName( layerName );
293 else
294 {
295 const QString path = sourceParts.value( QStringLiteral( "path" ) ).toString();
296 if ( !path.isEmpty() )
297 {
298 const QFileInfo fi( path );
299 layer->setName( fi.baseName() );
300 }
301 else if ( !name.isEmpty() )
302 {
303 // fallback to parameter's name -- shouldn't happen!
304 layer->setName( name );
305 }
306 }
307 }
308 else
309 {
310 layer->setName( name );
311 }
312}
313
314
319
320void QgsProcessingContext::setModelInitialRunConfig( std::unique_ptr< QgsProcessingModelInitialRunConfig > config )
321{
322 mModelConfig = std::move( config );
323}
324
325std::unique_ptr< QgsProcessingModelInitialRunConfig > QgsProcessingContext::takeModelInitialRunConfig()
326{
327 return std::move( mModelConfig );
328}
329
331{
332 mModelResult.clear();
333}
DistanceUnit
Units of distance.
Definition qgis.h:5013
@ Unknown
Unknown distance unit.
Definition qgis.h:5063
AreaUnit
Units of area.
Definition qgis.h:5090
@ Unknown
Unknown areal unit.
Definition qgis.h:5103
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
Definition qgis.h:2238
@ NoCheck
No invalid geometry checking.
Definition qgis.h:2239
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
Definition qgis.h:2241
@ SkipInvalid
Skip any features with invalid geometry. This requires a slow geometry validity check for every featu...
Definition qgis.h:2240
ProcessingLogLevel
Logging level for algorithms to use when pushing feedback messages.
Definition qgis.h:3656
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setLoadedLayerStore(QgsMapLayerStore *store)
Sets the destination layer store for any layers loaded during expression evaluation.
An interface for objects which provide features via a getFeatures method.
virtual QString sourceName() const =0
Returns a friendly display name for the source.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
Base class for all map layer types.
Definition qgsmaplayer.h:80
virtual bool isTemporary() const
Returns true if the layer is considered a temporary layer.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setName(const QString &name)
Set the display name of the layer.
Details for layers to load into projects.
bool forceName
Set to true if LayerDetails::name should always be used as the loaded layer name, regardless of the u...
QgsProcessingLayerPostProcessorInterface * postProcessor() const
Layer post-processor.
QString name
Friendly name for layer, possibly for use when loading layer into project.
void setPostProcessor(QgsProcessingLayerPostProcessorInterface *processor)
Sets the layer post-processor.
void setOutputLayerName(QgsMapLayer *layer) const
Sets a layer name to match this output, respecting any local user settings which affect this name.
QgsProcessingContext::Flags flags() const
Returns any flags set in the context.
@ IncludeProjectPath
Include the associated project path argument.
QFlags< ProcessArgumentFlag > ProcessArgumentFlags
std::unique_ptr< QgsProcessingModelInitialRunConfig > takeModelInitialRunConfig()
Takes the model initial run configuration from the context.
QgsDateTimeRange currentTimeRange() const
Returns the current time range to use for temporal operations.
void takeResultsFrom(QgsProcessingContext &context)
Takes the results from another context and merges them with the results currently stored in this cont...
QVariantMap exportToMap() const
Exports the context's settings to a variant map.
Qgis::AreaUnit areaUnit() const
Returns the area unit to use for area calculations.
QStringList asQgisProcessArguments(QgsProcessingContext::ProcessArgumentFlags flags=QgsProcessingContext::ProcessArgumentFlags()) const
Returns list of the equivalent qgis_process arguments representing the settings from the context.
void setLogLevel(Qgis::ProcessingLogLevel level)
Sets the logging level for algorithms to use when pushing feedback messages to users.
void clearModelResult()
Clears model results previously populated when the context was used to run a model algorithm.
QgsMapLayer * getMapLayer(const QString &identifier)
Returns a map layer from the context with a matching identifier.
std::function< void(const QgsFeature &) > invalidGeometryCallback(QgsFeatureSource *source=nullptr) const
Returns the callback function to use when encountering an invalid geometry and invalidGeometryCheck()...
void setMaximumThreads(int threads)
Sets the (optional) number of threads to use when running algorithms.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
std::function< void(const QgsFeature &) > defaultInvalidGeometryCallbackForCheck(Qgis::InvalidGeometryCheck check, QgsFeatureSource *source=nullptr) const
Returns the default callback function to use for a particular invalid geometry check.
void setLayersToLoadOnCompletion(const QMap< QString, QgsProcessingContext::LayerDetails > &layers)
Sets the map of layers (by ID or datasource) to LayerDetails, to load into the canvas upon completion...
QgsMapLayer * takeResultLayer(const QString &id)
Takes the result map layer with matching id from the context and transfers ownership of it back to th...
void setDistanceUnit(Qgis::DistanceUnit unit)
Sets the unit to use for distance calculations.
void setInvalidGeometryCheck(Qgis::InvalidGeometryCheck check)
Sets the behavior used for checking invalid geometries in input layers.
void addLayerToLoadOnCompletion(const QString &layer, const QgsProcessingContext::LayerDetails &details)
Adds a layer to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
void setAreaUnit(Qgis::AreaUnit areaUnit)
Sets the unit to use for area calculations.
void setEllipsoid(const QString &ellipsoid)
Sets a specified ellipsoid to use for distance and area calculations.
QgsProcessingModelInitialRunConfig * modelInitialRunConfig()
Returns a reference to the model initial run configuration, used to run a model algorithm.
Qgis::DistanceUnit distanceUnit() const
Returns the distance unit to use for distance calculations.
Qgis::ProcessingLogLevel logLevel() const
Returns the logging level for algorithms to use when pushing feedback messages to users.
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
void setModelInitialRunConfig(std::unique_ptr< QgsProcessingModelInitialRunConfig > config)
Sets the model initial run configuration, used to run a model algorithm.
QgsMapLayerStore * temporaryLayerStore()
Returns a reference to the layer store used for storing temporary layers during algorithm execution.
void setTemporaryFolder(const QString &folder)
Sets the (optional) temporary folder to use when running algorithms.
QString temporaryFolder() const
Returns the (optional) temporary folder to use when running algorithms.
void setCurrentTimeRange(const QgsDateTimeRange &currentTimeRange)
Sets the current time range to use for temporal operations.
int maximumThreads() const
Returns the (optional) number of threads to use when running algorithms.
Custom exception class for processing related exceptions.
An interface for layer post-processing handlers for execution following a processing algorithm operat...
Configuration settings which control how a Processing model is executed.
Utility functions for use with processing classes.
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, QgsProcessingUtils::LayerHint typeHint=QgsProcessingUtils::LayerHint::UnknownType, QgsProcessing::LayerOptionsFlags flags=QgsProcessing::LayerOptionsFlags())
Interprets a string as a map layer within the supplied context.
static const QgsSettingsEntryBool * settingsPreferFilenameAsLayerName
Settings entry prefer filename as layer name.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:761