QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsprocessingutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingutils.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 
18 #include "qgsprocessingutils.h"
19 #include "qgsproject.h"
20 #include "qgssettings.h"
21 #include "qgsexception.h"
22 #include "qgsprocessingcontext.h"
23 #include "qgsvectorlayerexporter.h"
24 #include "qgsvectorfilewriter.h"
25 #include "qgsmemoryproviderutils.h"
27 #include "qgsprocessingalgorithm.h"
30 #include "qgsfileutils.h"
31 #include "qgsvectorlayer.h"
32 #include "qgsproviderregistry.h"
33 #include "qgsmeshlayer.h"
34 #include "qgsreferencedgeometry.h"
35 #include "qgsrasterfilewriter.h"
36 
37 QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
38 {
39  if ( !project )
40  return QList<QgsRasterLayer *>();
41 
42  QList<QgsRasterLayer *> layers;
43 
44  const auto rasterLayers = project->layers<QgsRasterLayer *>();
45  for ( QgsRasterLayer *l : rasterLayers )
46  {
47  if ( canUseLayer( l ) )
48  layers << l;
49  }
50 
51  if ( sort )
52  {
53  std::sort( layers.begin(), layers.end(), []( const QgsRasterLayer * a, const QgsRasterLayer * b ) -> bool
54  {
55  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
56  } );
57  }
58  return layers;
59 }
60 
61 QList<QgsVectorLayer *> QgsProcessingUtils::compatibleVectorLayers( QgsProject *project, const QList<int> &geometryTypes, bool sort )
62 {
63  if ( !project )
64  return QList<QgsVectorLayer *>();
65 
66  QList<QgsVectorLayer *> layers;
67  const auto vectorLayers = project->layers<QgsVectorLayer *>();
68  for ( QgsVectorLayer *l : vectorLayers )
69  {
70  if ( canUseLayer( l, geometryTypes ) )
71  layers << l;
72  }
73 
74  if ( sort )
75  {
76  std::sort( layers.begin(), layers.end(), []( const QgsVectorLayer * a, const QgsVectorLayer * b ) -> bool
77  {
78  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
79  } );
80  }
81  return layers;
82 }
83 
84 QList<QgsMeshLayer *> QgsProcessingUtils::compatibleMeshLayers( QgsProject *project, bool sort )
85 {
86  if ( !project )
87  return QList<QgsMeshLayer *>();
88 
89  QList<QgsMeshLayer *> layers;
90  const auto meshLayers = project->layers<QgsMeshLayer *>();
91  for ( QgsMeshLayer *l : meshLayers )
92  {
93  if ( canUseLayer( l ) )
94  layers << l;
95  }
96 
97  if ( sort )
98  {
99  std::sort( layers.begin(), layers.end(), []( const QgsMeshLayer * a, const QgsMeshLayer * b ) -> bool
100  {
101  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
102  } );
103  }
104  return layers;
105 }
106 
107 QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project, bool sort )
108 {
109  if ( !project )
110  return QList<QgsMapLayer *>();
111 
112  QList<QgsMapLayer *> layers;
113 
114  const auto rasterLayers = compatibleRasterLayers( project, false );
115  for ( QgsRasterLayer *rl : rasterLayers )
116  layers << rl;
117 
118  const auto vectorLayers = compatibleVectorLayers( project, QList< int >(), false );
119  for ( QgsVectorLayer *vl : vectorLayers )
120  layers << vl;
121 
122  const auto meshLayers = compatibleMeshLayers( project, false );
123  for ( QgsMeshLayer *vl : meshLayers )
124  layers << vl;
125 
126  if ( sort )
127  {
128  std::sort( layers.begin(), layers.end(), []( const QgsMapLayer * a, const QgsMapLayer * b ) -> bool
129  {
130  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
131  } );
132  }
133  return layers;
134 }
135 
136 QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMapLayerStore *store, QgsProcessingUtils::LayerHint typeHint )
137 {
138  if ( !store || string.isEmpty() )
139  return nullptr;
140 
141  QList< QgsMapLayer * > layers = store->mapLayers().values();
142 
143  layers.erase( std::remove_if( layers.begin(), layers.end(), []( QgsMapLayer * layer )
144  {
145  switch ( layer->type() )
146  {
148  return !canUseLayer( qobject_cast< QgsVectorLayer * >( layer ) );
150  return !canUseLayer( qobject_cast< QgsRasterLayer * >( layer ) );
152  return true;
154  return !canUseLayer( qobject_cast< QgsMeshLayer * >( layer ) );
155  }
156  return true;
157  } ), layers.end() );
158 
159  auto isCompatibleType = [typeHint]( QgsMapLayer * l ) -> bool
160  {
161  switch ( typeHint )
162  {
164  return true;
165 
166  case LayerHint::Vector:
167  return l->type() == QgsMapLayerType::VectorLayer;
168 
169  case LayerHint::Raster:
170  return l->type() == QgsMapLayerType::RasterLayer;
171 
172  case LayerHint::Mesh:
173  return l->type() == QgsMapLayerType::MeshLayer;
174  }
175  return true;
176  };
177 
178  for ( QgsMapLayer *l : qgis::as_const( layers ) )
179  {
180  if ( isCompatibleType( l ) && l->id() == string )
181  return l;
182  }
183  for ( QgsMapLayer *l : qgis::as_const( layers ) )
184  {
185  if ( isCompatibleType( l ) && l->name() == string )
186  return l;
187  }
188  for ( QgsMapLayer *l : qgis::as_const( layers ) )
189  {
190  if ( isCompatibleType( l ) && normalizeLayerSource( l->source() ) == normalizeLayerSource( string ) )
191  return l;
192  }
193  return nullptr;
194 }
195 
196 QgsMapLayer *QgsProcessingUtils::loadMapLayerFromString( const QString &string, const QgsCoordinateTransformContext &transformContext, LayerHint typeHint )
197 {
198  QStringList components = string.split( '|' );
199  if ( components.isEmpty() )
200  return nullptr;
201 
202  QFileInfo fi;
203  if ( QFileInfo::exists( string ) )
204  fi = QFileInfo( string );
205  else if ( QFileInfo::exists( components.at( 0 ) ) )
206  fi = QFileInfo( components.at( 0 ) );
207  else
208  return nullptr;
209 
210  QString name = fi.baseName();
211 
212  // brute force attempt to load a matching layer
213  if ( typeHint == LayerHint::UnknownType || typeHint == LayerHint::Vector )
214  {
215  QgsVectorLayer::LayerOptions options { transformContext };
216  options.loadDefaultStyle = false;
217  options.skipCrsValidation = true;
218  std::unique_ptr< QgsVectorLayer > layer = qgis::make_unique<QgsVectorLayer>( string, name, QStringLiteral( "ogr" ), options );
219  if ( layer->isValid() )
220  {
221  return layer.release();
222  }
223  }
224  if ( typeHint == LayerHint::UnknownType || typeHint == LayerHint::Raster )
225  {
226  QgsRasterLayer::LayerOptions rasterOptions;
227  rasterOptions.loadDefaultStyle = false;
228  rasterOptions.skipCrsValidation = true;
229  std::unique_ptr< QgsRasterLayer > rasterLayer( new QgsRasterLayer( string, name, QStringLiteral( "gdal" ), rasterOptions ) );
230  if ( rasterLayer->isValid() )
231  {
232  return rasterLayer.release();
233  }
234  }
235  if ( typeHint == LayerHint::UnknownType || typeHint == LayerHint::Mesh )
236  {
237  QgsMeshLayer::LayerOptions meshOptions;
238  meshOptions.skipCrsValidation = true;
239  std::unique_ptr< QgsMeshLayer > meshLayer( new QgsMeshLayer( string, name, QStringLiteral( "mdal" ), meshOptions ) );
240  if ( meshLayer->isValid() )
241  {
242  return meshLayer.release();
243  }
244  }
245  return nullptr;
246 }
247 
248 QgsMapLayer *QgsProcessingUtils::mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers, LayerHint typeHint )
249 {
250  if ( string.isEmpty() )
251  return nullptr;
252 
253  // prefer project layers
254  QgsMapLayer *layer = nullptr;
255  if ( context.project() )
256  {
257  QgsMapLayer *layer = mapLayerFromStore( string, context.project()->layerStore(), typeHint );
258  if ( layer )
259  return layer;
260  }
261 
262  layer = mapLayerFromStore( string, context.temporaryLayerStore(), typeHint );
263  if ( layer )
264  return layer;
265 
266  if ( !allowLoadingNewLayers )
267  return nullptr;
268 
269  layer = loadMapLayerFromString( string, context.transformContext(), typeHint );
270  if ( layer )
271  {
272  context.temporaryLayerStore()->addMapLayer( layer );
273  return layer;
274  }
275  else
276  {
277  return nullptr;
278  }
279 }
280 
281 QgsProcessingFeatureSource *QgsProcessingUtils::variantToSource( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue )
282 {
283  QVariant val = value;
284  bool selectedFeaturesOnly = false;
285  if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
286  {
287  // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
289  selectedFeaturesOnly = fromVar.selectedFeaturesOnly;
290  val = fromVar.source;
291  }
292  else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
293  {
294  // input is a QgsProcessingOutputLayerDefinition (e.g. an output from earlier in a model) - get extra properties from it
296  val = fromVar.sink;
297  }
298 
299  if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( val ) ) )
300  {
301  return new QgsProcessingFeatureSource( layer, context );
302  }
303 
304  QString layerRef;
305  if ( val.canConvert<QgsProperty>() )
306  {
307  layerRef = val.value< QgsProperty >().valueAsString( context.expressionContext(), fallbackValue.toString() );
308  }
309  else if ( !val.isValid() || val.toString().isEmpty() )
310  {
311  // fall back to default
312  if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( fallbackValue ) ) )
313  {
314  return new QgsProcessingFeatureSource( layer, context );
315  }
316 
317  layerRef = fallbackValue.toString();
318  }
319  else
320  {
321  layerRef = val.toString();
322  }
323 
324  if ( layerRef.isEmpty() )
325  return nullptr;
326 
327  QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context, true, LayerHint::Vector ) );
328  if ( !vl )
329  return nullptr;
330 
331  if ( selectedFeaturesOnly )
332  {
333  return new QgsProcessingFeatureSource( new QgsVectorLayerSelectedFeatureSource( vl ), context, true );
334  }
335  else
336  {
337  return new QgsProcessingFeatureSource( vl, context );
338  }
339 }
340 
341 bool QgsProcessingUtils::canUseLayer( const QgsMeshLayer *layer )
342 {
343  return layer && layer->dataProvider();
344 }
345 
346 bool QgsProcessingUtils::canUseLayer( const QgsRasterLayer *layer )
347 {
348  return layer && layer->isValid();
349 }
350 
351 bool QgsProcessingUtils::canUseLayer( const QgsVectorLayer *layer, const QList<int> &sourceTypes )
352 {
353  return layer && layer->isValid() &&
354  ( sourceTypes.isEmpty()
355  || ( sourceTypes.contains( QgsProcessing::TypeVectorPoint ) && layer->geometryType() == QgsWkbTypes::PointGeometry )
356  || ( sourceTypes.contains( QgsProcessing::TypeVectorLine ) && layer->geometryType() == QgsWkbTypes::LineGeometry )
357  || ( sourceTypes.contains( QgsProcessing::TypeVectorPolygon ) && layer->geometryType() == QgsWkbTypes::PolygonGeometry )
358  || ( sourceTypes.contains( QgsProcessing::TypeVectorAnyGeometry ) && layer->isSpatial() )
359  || sourceTypes.contains( QgsProcessing::TypeVector )
360  );
361 }
362 
363 QString QgsProcessingUtils::normalizeLayerSource( const QString &source )
364 {
365  QString normalized = source;
366  normalized.replace( '\\', '/' );
367  return normalized.trimmed();
368 }
369 
370 QString QgsProcessingUtils::variantToPythonLiteral( const QVariant &value )
371 {
372  if ( !value.isValid() )
373  return QStringLiteral( "None" );
374 
375  if ( value.canConvert<QgsProperty>() )
376  return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
377  else if ( value.canConvert<QgsCoordinateReferenceSystem>() )
378  {
379  if ( !value.value< QgsCoordinateReferenceSystem >().isValid() )
380  return QStringLiteral( "QgsCoordinateReferenceSystem()" );
381  else
382  return QStringLiteral( "QgsCoordinateReferenceSystem('%1')" ).arg( value.value< QgsCoordinateReferenceSystem >().authid() );
383  }
384  else if ( value.canConvert< QgsRectangle >() )
385  {
386  QgsRectangle r = value.value<QgsRectangle>();
387  return QStringLiteral( "'%1, %3, %2, %4'" ).arg( qgsDoubleToString( r.xMinimum() ),
390  qgsDoubleToString( r.yMaximum() ) );
391  }
392  else if ( value.canConvert< QgsReferencedRectangle >() )
393  {
395  return QStringLiteral( "'%1, %3, %2, %4 [%5]'" ).arg( qgsDoubleToString( r.xMinimum() ),
398  qgsDoubleToString( r.yMaximum() ), r.crs().authid() );
399  }
400  else if ( value.canConvert< QgsPointXY >() )
401  {
402  QgsPointXY r = value.value<QgsPointXY>();
403  return QStringLiteral( "'%1,%2'" ).arg( qgsDoubleToString( r.x() ),
404  qgsDoubleToString( r.y() ) );
405  }
406  else if ( value.canConvert< QgsReferencedPointXY >() )
407  {
408  QgsReferencedPointXY r = value.value<QgsReferencedPointXY>();
409  return QStringLiteral( "'%1,%2 [%3]'" ).arg( qgsDoubleToString( r.x() ),
410  qgsDoubleToString( r.y() ),
411  r.crs().authid() );
412  }
413 
414  switch ( value.type() )
415  {
416  case QVariant::Bool:
417  return value.toBool() ? QStringLiteral( "True" ) : QStringLiteral( "False" );
418 
419  case QVariant::Double:
420  return QString::number( value.toDouble() );
421 
422  case QVariant::Int:
423  case QVariant::UInt:
424  return QString::number( value.toInt() );
425 
426  case QVariant::LongLong:
427  case QVariant::ULongLong:
428  return QString::number( value.toLongLong() );
429 
430  case QVariant::List:
431  {
432  QStringList parts;
433  const QVariantList vl = value.toList();
434  for ( const QVariant &v : vl )
435  {
436  parts << variantToPythonLiteral( v );
437  }
438  return parts.join( ',' ).prepend( '[' ).append( ']' );
439  }
440 
441  default:
442  break;
443  }
444 
445  return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
446 }
447 
448 QString QgsProcessingUtils::stringToPythonLiteral( const QString &string )
449 {
450  QString s = string;
451  s.replace( '\\', QStringLiteral( "\\\\" ) );
452  s.replace( '\n', QStringLiteral( "\\n" ) );
453  s.replace( '\r', QStringLiteral( "\\r" ) );
454  s.replace( '\t', QStringLiteral( "\\t" ) );
455  s.replace( '"', QStringLiteral( "\\\"" ) );
456  s.replace( '\'', QStringLiteral( "\\\'" ) );
457  s = s.prepend( '\'' ).append( '\'' );
458  return s;
459 }
460 
461 void QgsProcessingUtils::parseDestinationString( QString &destination, QString &providerKey, QString &uri, QString &layerName, QString &format, QMap<QString, QVariant> &options, bool &useWriter, QString &extension )
462 {
463  extension.clear();
464  QRegularExpression splitRx( QStringLiteral( "^(.{3,}?):(.*)$" ) );
465  QRegularExpressionMatch match = splitRx.match( destination );
466  if ( match.hasMatch() )
467  {
468  providerKey = match.captured( 1 );
469  if ( providerKey == QStringLiteral( "postgis" ) ) // older processing used "postgis" instead of "postgres"
470  {
471  providerKey = QStringLiteral( "postgres" );
472  }
473  uri = match.captured( 2 );
474  if ( providerKey == QLatin1String( "ogr" ) )
475  {
476  QgsDataSourceUri dsUri( uri );
477  if ( !dsUri.database().isEmpty() )
478  {
479  if ( !dsUri.table().isEmpty() )
480  {
481  layerName = dsUri.table();
482  options.insert( QStringLiteral( "layerName" ), layerName );
483  }
484  uri = dsUri.database();
485  extension = QFileInfo( uri ).completeSuffix();
486  format = QgsVectorFileWriter::driverForExtension( extension );
487  }
488  else
489  {
490  extension = QFileInfo( uri ).completeSuffix();
491  }
492  options.insert( QStringLiteral( "update" ), true );
493  }
494  useWriter = false;
495  }
496  else
497  {
498  useWriter = true;
499  providerKey = QStringLiteral( "ogr" );
500  QRegularExpression splitRx( QStringLiteral( "^(.*)\\.(.*?)$" ) );
501  QRegularExpressionMatch match = splitRx.match( destination );
502  if ( match.hasMatch() )
503  {
504  extension = match.captured( 2 );
505  format = QgsVectorFileWriter::driverForExtension( extension );
506  }
507 
508  if ( format.isEmpty() )
509  {
510  format = QStringLiteral( "GPKG" );
511  destination = destination + QStringLiteral( ".gpkg" );
512  }
513 
514  options.insert( QStringLiteral( "driverName" ), format );
515  uri = destination;
516  }
517 }
518 
519 QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &createOptions, QgsFeatureSink::SinkFlags sinkFlags )
520 {
521  QVariantMap options = createOptions;
522  if ( !options.contains( QStringLiteral( "fileEncoding" ) ) )
523  {
524  // no destination encoding specified, use default
525  options.insert( QStringLiteral( "fileEncoding" ), context.defaultEncoding().isEmpty() ? QStringLiteral( "system" ) : context.defaultEncoding() );
526  }
527 
528  if ( destination.isEmpty() || destination.startsWith( QLatin1String( "memory:" ) ) )
529  {
530  // strip "memory:" from start of destination
531  if ( destination.startsWith( QLatin1String( "memory:" ) ) )
532  destination = destination.mid( 7 );
533 
534  if ( destination.isEmpty() )
535  destination = QStringLiteral( "output" );
536 
537  // memory provider cannot be used with QgsVectorLayerImport - so create layer manually
538  std::unique_ptr< QgsVectorLayer > layer( QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs ) );
539  if ( !layer || !layer->isValid() )
540  {
541  throw QgsProcessingException( QObject::tr( "Could not create memory layer" ) );
542  }
543 
544  // update destination to layer ID
545  destination = layer->id();
546 
547  // this is a factory, so we need to return a proxy
548  std::unique_ptr< QgsProcessingFeatureSink > sink( new QgsProcessingFeatureSink( layer->dataProvider(), destination, context ) );
549  context.temporaryLayerStore()->addMapLayer( layer.release() );
550 
551  return sink.release();
552  }
553  else
554  {
555  QString providerKey;
556  QString uri;
557  QString layerName;
558  QString format;
559  QString extension;
560  bool useWriter = false;
561  parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter, extension );
562 
563  QgsFields newFields = fields;
564  if ( useWriter && providerKey == QLatin1String( "ogr" ) )
565  {
566  // use QgsVectorFileWriter for OGR destinations instead of QgsVectorLayerImport, as that allows
567  // us to use any OGR format which supports feature addition
568  QString finalFileName;
569  std::unique_ptr< QgsVectorFileWriter > writer = qgis::make_unique< QgsVectorFileWriter >( destination, options.value( QStringLiteral( "fileEncoding" ) ).toString(), newFields, geometryType, crs, format, QgsVectorFileWriter::defaultDatasetOptions( format ),
570  QgsVectorFileWriter::defaultLayerOptions( format ), &finalFileName, QgsVectorFileWriter::NoSymbology, sinkFlags );
571 
572  if ( writer->hasError() )
573  {
574  throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, writer->errorMessage() ) );
575  }
576  destination = finalFileName;
577  return new QgsProcessingFeatureSink( writer.release(), destination, context, true );
578  }
579  else
580  {
581  //create empty layer
582  const QgsVectorLayer::LayerOptions layerOptions { context.transformContext() };
583  std::unique_ptr< QgsVectorLayerExporter > exporter = qgis::make_unique<QgsVectorLayerExporter>( uri, providerKey, newFields, geometryType, crs, true, options, sinkFlags );
584  if ( exporter->errorCode() )
585  {
586  throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, exporter->errorMessage() ) );
587  }
588 
589  // use destination string as layer name (eg "postgis:..." )
590  if ( !layerName.isEmpty() )
591  uri += QStringLiteral( "|layername=%1" ).arg( layerName );
592  std::unique_ptr< QgsVectorLayer > layer = qgis::make_unique<QgsVectorLayer>( uri, destination, providerKey, layerOptions );
593  // update destination to layer ID
594  destination = layer->id();
595 
596  context.temporaryLayerStore()->addMapLayer( layer.release() );
597  return new QgsProcessingFeatureSink( exporter.release(), destination, context, true );
598  }
599  }
600 }
601 
602 void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &options )
603 {
604  *sink = createFeatureSink( destination, context, fields, geometryType, crs, options );
605 }
606 
607 
609 {
610  QgsRectangle extent;
611  for ( const QgsMapLayer *layer : layers )
612  {
613  if ( !layer )
614  continue;
615 
616  if ( crs.isValid() )
617  {
618  //transform layer extent to target CRS
619  QgsCoordinateTransform ct( layer->crs(), crs, context.transformContext() );
620  try
621  {
622  QgsRectangle reprojExtent = ct.transformBoundingBox( layer->extent() );
623  extent.combineExtentWith( reprojExtent );
624  }
625  catch ( QgsCsException & )
626  {
627  // can't reproject... what to do here? hmmm?
628  // let's ignore this layer for now, but maybe we should just use the original extent?
629  }
630  }
631  else
632  {
633  extent.combineExtentWith( layer->extent() );
634  }
635 
636  }
637  return extent;
638 }
639 
640 // Deprecated
642 {
643  QgsProcessingContext context;
644  return QgsProcessingUtils::combineLayerExtents( layers, crs, context );
645 }
646 
647 QVariant QgsProcessingUtils::generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context )
648 {
649  if ( !input.isValid() )
650  return QStringLiteral( "memory:%1" ).arg( id.toString() );
651 
652  if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
653  {
655  QVariant newSink = generateIteratingDestination( fromVar.sink, id, context );
656  fromVar.sink = QgsProperty::fromValue( newSink );
657  return fromVar;
658  }
659  else if ( input.canConvert<QgsProperty>() )
660  {
661  QString res = input.value< QgsProperty>().valueAsString( context.expressionContext() );
662  return generateIteratingDestination( res, id, context );
663  }
664  else
665  {
666  QString res = input.toString();
667  if ( res == QgsProcessing::TEMPORARY_OUTPUT )
668  {
669  // temporary outputs map to temporary outputs!
671  }
672  else if ( res.startsWith( QLatin1String( "memory:" ) ) )
673  {
674  return res + '_' + id.toString();
675  }
676  else
677  {
678  // assume a filename type output for now
679  // TODO - uris?
680  int lastIndex = res.lastIndexOf( '.' );
681  return res.left( lastIndex ) + '_' + id.toString() + res.mid( lastIndex );
682  }
683  }
684 }
685 
687 {
688  static QString sFolder;
689  static QMutex sMutex;
690  sMutex.lock();
691  if ( sFolder.isEmpty() )
692  {
693  QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' );
694  sFolder = QDir::tempPath() + QStringLiteral( "/processing_" ) + subPath;
695  if ( !QDir( sFolder ).exists() )
696  QDir().mkpath( sFolder );
697  }
698  sMutex.unlock();
699  return sFolder;
700 }
701 
702 QString QgsProcessingUtils::generateTempFilename( const QString &basename )
703 {
704  QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' );
705  QString path = tempFolder() + '/' + subPath;
706  if ( !QDir( path ).exists() ) //make sure the directory exists - it shouldn't, but lets be safe...
707  {
708  QDir tmpDir;
709  tmpDir.mkdir( path );
710  }
711  return path + '/' + QgsFileUtils::stringToSafeFilename( basename );
712 }
713 
715 {
716  auto getText = [map]( const QString & key )->QString
717  {
718  if ( map.contains( key ) )
719  return map.value( key ).toString();
720  return QString();
721  };
722 
723  QString s = QObject::tr( "<html><body><h2>Algorithm description</h2>\n" );
724  s += QStringLiteral( "<p>" ) + getText( QStringLiteral( "ALG_DESC" ) ) + QStringLiteral( "</p>\n" );
725 
726  QString inputs;
727 
728  const auto parameterDefinitions = algorithm->parameterDefinitions();
729  for ( const QgsProcessingParameterDefinition *def : parameterDefinitions )
730  {
731  inputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
732  inputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
733  }
734  if ( !inputs.isEmpty() )
735  s += QObject::tr( "<h2>Input parameters</h2>\n" ) + inputs;
736 
737  QString outputs;
738  const auto outputDefinitions = algorithm->outputDefinitions();
739  for ( const QgsProcessingOutputDefinition *def : outputDefinitions )
740  {
741  outputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
742  outputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
743  }
744  if ( !outputs.isEmpty() )
745  s += QObject::tr( "<h2>Outputs</h2>\n" ) + outputs;
746 
747  s += QLatin1String( "<br>" );
748  if ( !map.value( QStringLiteral( "ALG_CREATOR" ) ).toString().isEmpty() )
749  s += QObject::tr( "<p align=\"right\">Algorithm author: %1</p>" ).arg( getText( QStringLiteral( "ALG_CREATOR" ) ) );
750  if ( !map.value( QStringLiteral( "ALG_HELP_CREATOR" ) ).toString().isEmpty() )
751  s += QObject::tr( "<p align=\"right\">Help author: %1</p>" ).arg( getText( QStringLiteral( "ALG_HELP_CREATOR" ) ) );
752  if ( !map.value( QStringLiteral( "ALG_VERSION" ) ).toString().isEmpty() )
753  s += QObject::tr( "<p align=\"right\">Algorithm version: %1</p>" ).arg( getText( QStringLiteral( "ALG_VERSION" ) ) );
754 
755  s += QStringLiteral( "</body></html>" );
756  return s;
757 }
758 
759 QString convertToCompatibleFormatInternal( const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback, QString *layerName )
760 {
761  bool requiresTranslation = false;
762 
763  // if we are only looking for selected features then we have to export back to disk,
764  // as we need to subset only selected features, a concept which doesn't exist outside QGIS!
765  requiresTranslation = requiresTranslation || selectedFeaturesOnly;
766 
767  // if the data provider is NOT ogr, then we HAVE to convert. Otherwise we run into
768  // issues with data providers like spatialite, delimited text where the format can be
769  // opened outside of QGIS, but with potentially very different behavior!
770  requiresTranslation = requiresTranslation || vl->providerType() != QLatin1String( "ogr" );
771 
772  // if the layer has a feature filter set, then we HAVE to convert. Feature filters are
773  // a purely QGIS concept.
774  requiresTranslation = requiresTranslation || !vl->subsetString().isEmpty();
775 
776  // if the layer opened using GDAL's virtual I/O mechanism (/vsizip/, etc.), then
777  // we HAVE to convert as other tools may not work with it
778  requiresTranslation = requiresTranslation || vl->source().startsWith( QLatin1String( "/vsi" ) );
779 
780  // Check if layer is a disk based format and if so if the layer's path has a compatible filename suffix
781  QString diskPath;
782  if ( !requiresTranslation )
783  {
784  const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( vl->providerType(), vl->source() );
785  if ( parts.contains( QStringLiteral( "path" ) ) )
786  {
787  diskPath = parts.value( QStringLiteral( "path" ) ).toString();
788  QFileInfo fi( diskPath );
789  requiresTranslation = !compatibleFormats.contains( fi.suffix(), Qt::CaseInsensitive );
790 
791  // if the layer name doesn't match the filename, we need to convert the layer. This method can only return
792  // a filename, and cannot handle layernames as well as file paths
793  const QString srcLayerName = parts.value( QStringLiteral( "layerName" ) ).toString();
794  if ( layerName )
795  {
796  // differing layer names are acceptable
797  *layerName = srcLayerName;
798  }
799  else
800  {
801  // differing layer names are NOT acceptable
802  requiresTranslation = requiresTranslation || ( !srcLayerName.isEmpty() && srcLayerName != fi.baseName() );
803  }
804  }
805  else
806  {
807  requiresTranslation = true; // not a disk-based format
808  }
809  }
810 
811  if ( requiresTranslation )
812  {
813  QString temp = QgsProcessingUtils::generateTempFilename( baseName + '.' + preferredFormat );
814 
815  QgsVectorFileWriter writer( temp, context.defaultEncoding(),
816  vl->fields(), vl->wkbType(), vl->crs(), QgsVectorFileWriter::driverForExtension( preferredFormat ) );
817  QgsFeature f;
819  if ( selectedFeaturesOnly )
820  it = vl->getSelectedFeatures();
821  else
822  it = vl->getFeatures();
823 
824  while ( it.nextFeature( f ) )
825  {
826  if ( feedback->isCanceled() )
827  return QString();
828  writer.addFeature( f, QgsFeatureSink::FastInsert );
829  }
830  return temp;
831  }
832  else
833  {
834  return diskPath;
835  }
836 }
837 
838 QString QgsProcessingUtils::convertToCompatibleFormat( const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
839 {
840  return convertToCompatibleFormatInternal( vl, selectedFeaturesOnly, baseName, compatibleFormats, preferredFormat, context, feedback, nullptr );
841 }
842 
843 QString QgsProcessingUtils::convertToCompatibleFormatAndLayerName( const QgsVectorLayer *layer, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback, QString &layerName )
844 {
845  layerName.clear();
846  return convertToCompatibleFormatInternal( layer, selectedFeaturesOnly, baseName, compatibleFormats, preferredFormat, context, feedback, &layerName );
847 }
848 
849 QgsFields QgsProcessingUtils::combineFields( const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix )
850 {
851  QgsFields outFields = fieldsA;
852  QSet< QString > usedNames;
853  for ( const QgsField &f : fieldsA )
854  {
855  usedNames.insert( f.name().toLower() );
856  }
857 
858  for ( const QgsField &f : fieldsB )
859  {
860  QgsField newField = f;
861  newField.setName( fieldsBPrefix + f.name() );
862  if ( usedNames.contains( newField.name().toLower() ) )
863  {
864  int idx = 2;
865  QString newName = newField.name() + '_' + QString::number( idx );
866  while ( usedNames.contains( newName.toLower() ) )
867  {
868  idx++;
869  newName = newField.name() + '_' + QString::number( idx );
870  }
871  newField.setName( newName );
872  outFields.append( newField );
873  }
874  else
875  {
876  outFields.append( newField );
877  }
878  usedNames.insert( newField.name() );
879  }
880 
881  return outFields;
882 }
883 
884 
885 QList<int> QgsProcessingUtils::fieldNamesToIndices( const QStringList &fieldNames, const QgsFields &fields )
886 {
887  QList<int> indices;
888  if ( !fieldNames.isEmpty() )
889  {
890  indices.reserve( fieldNames.count() );
891  for ( const QString &f : fieldNames )
892  {
893  int idx = fields.lookupField( f );
894  if ( idx >= 0 )
895  indices.append( idx );
896  }
897  }
898  else
899  {
900  indices.reserve( fields.count() );
901  for ( int i = 0; i < fields.count(); ++i )
902  indices.append( i );
903  }
904  return indices;
905 }
906 
907 
908 QgsFields QgsProcessingUtils::indicesToFields( const QList<int> &indices, const QgsFields &fields )
909 {
910  QgsFields fieldsSubset;
911  for ( int i : indices )
912  fieldsSubset.append( fields.at( i ) );
913  return fieldsSubset;
914 }
915 
917 {
918  QgsSettings settings;
919  const int setting = settings.value( QStringLiteral( "Processing/Configuration/DefaultOutputVectorLayerExt" ), -1 ).toInt();
920  if ( setting == -1 )
921  return QStringLiteral( "gpkg" );
922  return QgsVectorFileWriter::supportedFormatExtensions().value( setting, QStringLiteral( "gpkg" ) );
923 }
924 
926 {
927  QgsSettings settings;
928  const int setting = settings.value( QStringLiteral( "Processing/Configuration/DefaultOutputRasterLayerExt" ), -1 ).toInt();
929  if ( setting == -1 )
930  return QStringLiteral( "tif" );
931  return QgsRasterFileWriter::supportedFormatExtensions().value( setting, QStringLiteral( "tif" ) );
932 }
933 
934 //
935 // QgsProcessingFeatureSource
936 //
937 
938 QgsProcessingFeatureSource::QgsProcessingFeatureSource( QgsFeatureSource *originalSource, const QgsProcessingContext &context, bool ownsOriginalSource )
939  : mSource( originalSource )
940  , mOwnsSource( ownsOriginalSource )
941  , mInvalidGeometryCheck( QgsWkbTypes::geometryType( mSource->wkbType() ) == QgsWkbTypes::PointGeometry
942  ? QgsFeatureRequest::GeometryNoCheck // never run geometry validity checks for point layers!
943  : context.invalidGeometryCheck() )
944  , mInvalidGeometryCallback( context.invalidGeometryCallback() )
945  , mTransformErrorCallback( context.transformErrorCallback() )
946 {}
947 
949 {
950  if ( mOwnsSource )
951  delete mSource;
952 }
953 
955 {
956  QgsFeatureRequest req( request );
957  req.setTransformErrorCallback( mTransformErrorCallback );
958 
959  if ( flags & FlagSkipGeometryValidityChecks )
961  else
962  {
963  req.setInvalidGeometryCheck( mInvalidGeometryCheck );
964  req.setInvalidGeometryCallback( mInvalidGeometryCallback );
965  }
966 
967  return mSource->getFeatures( req );
968 }
969 
971 {
972  FeatureAvailability sourceAvailability = mSource->hasFeatures();
973  if ( sourceAvailability == NoFeaturesAvailable )
974  return NoFeaturesAvailable; // never going to be features if underlying source has no features
975  else if ( mInvalidGeometryCheck == QgsFeatureRequest::GeometryNoCheck )
976  return sourceAvailability;
977  else
978  // we don't know... source has features, but these may be filtered out by invalid geometry check
979  return FeaturesMaybeAvailable;
980 }
981 
983 {
984  QgsFeatureRequest req( request );
985  req.setInvalidGeometryCheck( mInvalidGeometryCheck );
986  req.setInvalidGeometryCallback( mInvalidGeometryCallback );
987  req.setTransformErrorCallback( mTransformErrorCallback );
988  return mSource->getFeatures( req );
989 }
990 
992 {
993  return mSource->sourceCrs();
994 }
995 
997 {
998  return mSource->fields();
999 }
1000 
1002 {
1003  return mSource->wkbType();
1004 }
1005 
1007 {
1008  return mSource->featureCount();
1009 }
1010 
1012 {
1013  return mSource->sourceName();
1014 
1015 }
1016 
1017 QSet<QVariant> QgsProcessingFeatureSource::uniqueValues( int fieldIndex, int limit ) const
1018 {
1019  return mSource->uniqueValues( fieldIndex, limit );
1020 }
1021 
1022 QVariant QgsProcessingFeatureSource::minimumValue( int fieldIndex ) const
1023 {
1024  return mSource->minimumValue( fieldIndex );
1025 }
1026 
1027 QVariant QgsProcessingFeatureSource::maximumValue( int fieldIndex ) const
1028 {
1029  return mSource->maximumValue( fieldIndex );
1030 }
1031 
1033 {
1034  return mSource->sourceExtent();
1035 }
1036 
1038 {
1039  return mSource->allFeatureIds();
1040 }
1041 
1043 {
1044  QgsExpressionContextScope *expressionContextScope = nullptr;
1045  QgsExpressionContextScopeGenerator *generator = dynamic_cast<QgsExpressionContextScopeGenerator *>( mSource );
1046  if ( generator )
1047  {
1048  expressionContextScope = generator->createExpressionContextScope();
1049  }
1050  return expressionContextScope;
1051 }
1052 
1053 
1054 //
1055 // QgsProcessingFeatureSink
1056 //
1057 QgsProcessingFeatureSink::QgsProcessingFeatureSink( QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink )
1058  : QgsProxyFeatureSink( originalSink )
1059  , mContext( context )
1060  , mSinkName( sinkName )
1061  , mOwnsSink( ownsOriginalSink )
1062 {}
1063 
1065 {
1066  if ( mOwnsSink )
1067  delete destinationSink();
1068 }
1069 
1070 bool QgsProcessingFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
1071 {
1072  bool result = QgsProxyFeatureSink::addFeature( feature, flags );
1073  if ( !result )
1074  mContext.feedback()->reportError( QObject::tr( "Feature could not be written to %1" ).arg( mSinkName ) );
1075  return result;
1076 }
1077 
1078 bool QgsProcessingFeatureSink::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags )
1079 {
1080  bool result = QgsProxyFeatureSink::addFeatures( features, flags );
1081  if ( !result )
1082  mContext.feedback()->reportError( QObject::tr( "%1 feature(s) could not be written to %2" ).arg( features.count() ).arg( mSinkName ) );
1083  return result;
1084 }
1085 
1086 bool QgsProcessingFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags )
1087 {
1088  bool result = !QgsProxyFeatureSink::addFeatures( iterator, flags );
1089  if ( !result )
1090  mContext.feedback()->reportError( QObject::tr( "Features could not be written to %1" ).arg( mSinkName ) );
1091  return result;
1092 }
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
QgsProperty sink
Sink/layer definition.
Wrapper for iterator of features from vector data provider or vector layer.
virtual QgsRectangle sourceExtent() const
Returns the extent of all geometries from the source.
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsWkbTypes::Type wkbType() const override
Returns the geometry type for features returned by this source.
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
Base class for all map layer types.
Definition: qgsmaplayer.h:79
QString table() const
Returns the table name stored in the URI.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
static QgsRectangle combineLayerExtents(const QList< QgsMapLayer *> &layers, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context)
Combines the extent of several map layers.
QgsFeatureRequest & setInvalidGeometryCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering an invalid geometry and invalidGeometryCheck() is s...
Base class for providing feedback from a processing algorithm.
QgsProcessingParameterDefinitions parameterDefinitions() const
Returns an ordered list of parameter definitions utilized by the algorithm.
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
virtual QgsFields fields() const =0
Returns the fields associated with features in the source.
Encapsulates settings relating to a feature sink or output raster layer for a processing algorithm...
static void createFeatureSinkPython(QgsFeatureSink **sink, QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &createOptions=QVariantMap()) SIP_THROW(QgsProcessingException)
Creates a feature sink ready for adding features.
A simple feature sink which proxies feature addition on to another feature sink.
QString name
Definition: qgsfield.h:58
QgsFeatureRequest & setInvalidGeometryCheck(InvalidGeometryCheck check)
Sets invalid geometry checking behavior.
QgsProcessingFeatureSource(QgsFeatureSource *originalSource, const QgsProcessingContext &context, bool ownsOriginalSource=false)
Constructor for QgsProcessingFeatureSource, accepting an original feature source originalSource and p...
static QString defaultVectorExtension()
Returns the default vector extension to use, in the absence of all other constraints (e...
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
FeatureAvailability
Possible return value for hasFeatures() to determine if a source is empty.
LayerHint
Layer type hints.
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Setting options for loading vector layers.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:40
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
A QgsPointXY with associated coordinate reference system.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsFeatureIds allFeatureIds() const override
Returns a list of all feature IDs for features present in the source.
virtual QgsWkbTypes::Type wkbType() const =0
Returns the geometry type for features returned by this source.
An interface for objects which accept features via addFeature(s) methods.
static QList< QgsRasterLayer *> compatibleRasterLayers(QgsProject *project, bool sort=true)
Returns a list of raster layers from a project which are compatible with the processing framework...
static QString stringToPythonLiteral(const QString &string)
Converts a string to a Python string literal.
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QgsFeatureSource subclass which proxies methods to an underlying QgsFeatureSource, modifying results according to the settings in a QgsProcessingContext.
Container of fields for a vector layer.
Definition: qgsfields.h:42
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:141
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request, Flags flags) const
Returns an iterator for the features in the source, respecting the supplied feature flags...
static QList< QgsVectorLayer *> compatibleVectorLayers(QgsProject *project, const QList< int > &sourceTypes=QList< int >(), bool sort=true)
Returns a list of vector layers from a project which are compatible with the processing framework...
Setting options for loading mesh layers.
Definition: qgsmeshlayer.h:98
A convenience class for writing vector files to disk.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
const QgsCoordinateReferenceSystem & crs
QVariant maximumValue(int fieldIndex) const override
Returns the maximum value for an attribute column or an invalid variant in case of error...
bool isValid() const
Returns the status of the layer.
static QString convertToCompatibleFormat(const QgsVectorLayer *layer, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback)
Converts a source vector layer to a file path of a vector layer of compatible format.
QgsRectangle sourceExtent() const override
Returns the extent of all geometries from the source.
static QString normalizeLayerSource(const QString &source)
Normalizes a layer source string for safe comparison across different operating system environments...
Abstract base class for processing algorithms.
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsMapLayerStore * layerStore()
Returns a pointer to the project&#39;s internal layer store.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
bool selectedFeaturesOnly
true if only selected features in the source should be used by algorithms.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, QgsProcessingUtils::LayerHint typeHint=QgsProcessingUtils::LayerHint::UnknownType)
Interprets a string as a map layer within the supplied context.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set...
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const override
Returns the set of unique values contained within the specified fieldIndex from this source...
static QgsFeatureSink * createFeatureSink(QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &createOptions=QVariantMap(), QgsFeatureSink::SinkFlags sinkFlags=nullptr)
Creates a feature sink ready for adding features.
QgsProcessingFeedback * feedback()
Returns the associated feedback object.
static QList< int > fieldNamesToIndices(const QStringList &fieldNames, const QgsFields &fields)
Returns a list of field indices parsed from the given list of field names.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
virtual QVariant minimumValue(int fieldIndex) const
Returns the minimum value for an attribute column or an invalid variant in case of error...
static QStringList supportedFormatExtensions(RasterFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats.
QgsFields fields() const override
Returns the fields associated with features in the source.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
static QgsProperty fromValue(const QVariant &value, bool isActive=true)
Returns a new StaticProperty created from the specified value.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsMapLayerStore * temporaryLayerStore()
Returns a reference to the layer store used for storing temporary layers during algorithm execution...
QgsProperty source
Source definition.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
QVariant minimumValue(int fieldIndex) const override
Returns the minimum value for an attribute column or an invalid variant in case of error...
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
static QString stringToSafeFilename(const QString &string)
Converts a string to a safe filename, replacing characters which are not safe for filenames with an &#39;...
bool loadDefaultStyle
Sets to true if the default layer style should be loaded.
QgsCoordinateReferenceSystem sourceCrs() const override
Returns the coordinate reference system for features in the source.
static QString convertToCompatibleFormatAndLayerName(const QgsVectorLayer *layer, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback, QString &layerName)
Converts a source vector layer to a file path and layer name of a vector layer of compatible format...
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:240
There are certainly no features available in this source.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Definition: qgsmeshlayer.h:124
static QString defaultRasterExtension()
Returns the default raster extension to use, in the absence of all other constraints (e...
static const QString TEMPORARY_OUTPUT
Constant used to indicate that a Processing algorithm output should be a temporary layer/file...
Definition: qgsprocessing.h:99
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
QString subsetString
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
static QList< QgsMapLayer *> compatibleLayers(QgsProject *project, bool sort=true)
Returns a list of map layers from a project which are compatible with the processing framework...
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfields.cpp:59
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
Vector polygon layers.
Definition: qgsprocessing.h:50
No invalid geometry checking.
A QgsRectangle with associated coordinate reference system.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a single feature to the sink.
QString convertToCompatibleFormatInternal(const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback, QString *layerName)
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
QgsMeshDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be nullptr.
Single scope for storing variables and functions for use within a QgsExpressionContext.
Contains information about the context in which a coordinate transform is executed.
static QgsProcessingFeatureSource * variantToSource(const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue=QVariant())
Converts a variant value to a new feature source.
A store for object properties.
Definition: qgsproperty.h:229
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
virtual QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const
Returns the set of unique values contained within the specified fieldIndex from this source...
QgsExpressionContext & expressionContext()
Returns the expression context.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
double x
Definition: qgspointxy.h:47
static QList< QgsMeshLayer * > compatibleMeshLayers(QgsProject *project, bool sort=true)
Returns a list of mesh layers from a project which are compatible with the processing framework...
QgsFeatureRequest & setTransformErrorCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering a transform error when iterating features and a des...
static QString tempFolder()
Returns a session specific processing temporary folder for use in processing algorithms.
virtual QgsCoordinateReferenceSystem sourceCrs() const =0
Returns the coordinate reference system for features in the source.
QgsExpressionContextScope * createExpressionContextScope() const
Returns an expression context scope suitable for this source.
Encapsulates settings relating to a feature source input to a processing algorithm.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsProcessingOutputDefinitions outputDefinitions() const
Returns an ordered list of output definitions utilized by the algorithm.
static QString generateTempFilename(const QString &basename)
Returns a temporary filename for a given file, putting it into a temporary folder (creating that fold...
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:359
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Base class for the definition of processing outputs.
static QString variantToPythonLiteral(const QVariant &value)
Converts a variant to a Python literal.
QgsProxyFeatureSink subclass which reports feature addition errors to a QgsProcessingContext.
static QString formatHelpMapAsHtml(const QVariantMap &map, const QgsProcessingAlgorithm *algorithm)
Returns a HTML formatted version of the help text encoded in a variant map for a specified algorithm...
static QgsFields indicesToFields(const QList< int > &indices, const QgsFields &fields)
Returns a subset of fields based on the indices of desired fields.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
Definition: qgsproject.h:821
virtual QgsExpressionContextScope * createExpressionContextScope() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all layers by layer ID.
QgsFeatureSource subclass for the selected features from a QgsVectorLayer.
QgsMapLayer * addMapLayer(QgsMapLayer *layer, bool takeOwnership=true)
Add a layer to the store.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Vector point layers.
Definition: qgsprocessing.h:48
Abstract interface for generating an expression context scope.
QString defaultEncoding() const
Returns the default encoding to use for newly created files.
An interface for objects which provide features via a getFeatures method.
QString source() const
Returns the source for the layer.
QgsFeatureSource::FeatureAvailability hasFeatures() const override
Determines if there are any features available in the source.
static QVariant generateIteratingDestination(const QVariant &input, const QVariant &id, QgsProcessingContext &context)
Converts an input parameter value for use in source iterating mode, where one individual sink is crea...
QString sourceName() const override
Returns a friendly display name for the source.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
This class represents a coordinate reference system (CRS).
Base class for the definition of processing parameters.
Vector line layers.
Definition: qgsprocessing.h:49
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:53
Class for doing transforms between two map coordinate systems.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:90
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QString name
Definition: qgsmaplayer.h:83
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a single feature to the sink.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, QgsWkbTypes::Type geometryType=QgsWkbTypes::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Creates a new memory layer using the specified parameters.
virtual QVariant maximumValue(int fieldIndex) const
Returns the maximum value for an attribute column or an invalid variant in case of error...
There may be features available in this source.
bool nextFeature(QgsFeature &f)
QgsFeatureSink * destinationSink()
Returns the destination QgsFeatureSink which the proxy will forward features to.
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
virtual QString sourceName() const =0
Returns a friendly display name for the source.
long featureCount() const override
Returns the number of features contained in the source, or -1 if the feature count is unknown...
Class for storing the component parts of a RDBMS data source URI (e.g.
Represents a vector layer which manages a vector based data sets.
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
Contains information about the context in which a processing algorithm is executed.
virtual FeatureAvailability hasFeatures() const
Determines if there are any features available in the source.
QString database() const
Returns the database name stored in the URI.
Any vector layer with geometry.
Definition: qgsprocessing.h:47
QString authid() const
Returns the authority identifier for the CRS.
Setting options for loading raster layers.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:86
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
virtual long featureCount() const =0
Returns the number of features contained in the source, or -1 if the feature count is unknown...
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QgsProcessingFeatureSink(QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink=false)
Constructor for QgsProcessingFeatureSink, accepting an original feature sink originalSink and process...