QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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 QgsCoordinateReferenceSystem QgsProcessingUtils::variantToCrs( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue )
342 {
343  QVariant val = value;
344 
345  if ( val.canConvert<QgsCoordinateReferenceSystem>() )
346  {
347  // input is a QgsCoordinateReferenceSystem - done!
348  return val.value< QgsCoordinateReferenceSystem >();
349  }
350  else if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
351  {
352  // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
354  val = fromVar.source;
355  }
356  else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
357  {
358  // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
360  val = fromVar.sink;
361  }
362 
363  if ( val.canConvert<QgsProperty>() && val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
364  {
365  val = val.value< QgsProperty >().staticValue();
366  }
367 
368  // maybe a map layer
369  if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) ) )
370  return layer->crs();
371 
372  if ( val.canConvert<QgsProperty>() )
373  val = val.value< QgsProperty >().valueAsString( context.expressionContext(), fallbackValue.toString() );
374 
375  if ( !val.isValid() )
376  {
377  // fall back to default
378  val = fallbackValue;
379  }
380 
381  QString crsText = val.toString();
382  if ( crsText.isEmpty() )
383  crsText = fallbackValue.toString();
384 
385  if ( crsText.isEmpty() )
387 
388  // maybe special string
389  if ( context.project() && crsText.compare( QLatin1String( "ProjectCrs" ), Qt::CaseInsensitive ) == 0 )
390  return context.project()->crs();
391 
392  // maybe a map layer reference
393  if ( QgsMapLayer *layer = QgsProcessingUtils::mapLayerFromString( crsText, context ) )
394  return layer->crs();
395 
396  // else CRS from string
398  crs.createFromString( crsText );
399  return crs;
400 }
401 
402 bool QgsProcessingUtils::canUseLayer( const QgsMeshLayer *layer )
403 {
404  return layer && layer->dataProvider();
405 }
406 
407 bool QgsProcessingUtils::canUseLayer( const QgsRasterLayer *layer )
408 {
409  return layer && layer->isValid();
410 }
411 
412 bool QgsProcessingUtils::canUseLayer( const QgsVectorLayer *layer, const QList<int> &sourceTypes )
413 {
414  return layer && layer->isValid() &&
415  ( sourceTypes.isEmpty()
416  || ( sourceTypes.contains( QgsProcessing::TypeVectorPoint ) && layer->geometryType() == QgsWkbTypes::PointGeometry )
417  || ( sourceTypes.contains( QgsProcessing::TypeVectorLine ) && layer->geometryType() == QgsWkbTypes::LineGeometry )
418  || ( sourceTypes.contains( QgsProcessing::TypeVectorPolygon ) && layer->geometryType() == QgsWkbTypes::PolygonGeometry )
419  || ( sourceTypes.contains( QgsProcessing::TypeVectorAnyGeometry ) && layer->isSpatial() )
420  || sourceTypes.contains( QgsProcessing::TypeVector )
421  );
422 }
423 
424 QString QgsProcessingUtils::normalizeLayerSource( const QString &source )
425 {
426  QString normalized = source;
427  normalized.replace( '\\', '/' );
428  return normalized.trimmed();
429 }
430 
431 QString QgsProcessingUtils::variantToPythonLiteral( const QVariant &value )
432 {
433  if ( !value.isValid() )
434  return QStringLiteral( "None" );
435 
436  if ( value.canConvert<QgsProperty>() )
437  return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
438  else if ( value.canConvert<QgsCoordinateReferenceSystem>() )
439  {
440  if ( !value.value< QgsCoordinateReferenceSystem >().isValid() )
441  return QStringLiteral( "QgsCoordinateReferenceSystem()" );
442  else
443  return QStringLiteral( "QgsCoordinateReferenceSystem('%1')" ).arg( value.value< QgsCoordinateReferenceSystem >().authid() );
444  }
445  else if ( value.canConvert< QgsRectangle >() )
446  {
447  QgsRectangle r = value.value<QgsRectangle>();
448  return QStringLiteral( "'%1, %3, %2, %4'" ).arg( qgsDoubleToString( r.xMinimum() ),
451  qgsDoubleToString( r.yMaximum() ) );
452  }
453  else if ( value.canConvert< QgsReferencedRectangle >() )
454  {
456  return QStringLiteral( "'%1, %3, %2, %4 [%5]'" ).arg( qgsDoubleToString( r.xMinimum() ),
459  qgsDoubleToString( r.yMaximum() ), r.crs().authid() );
460  }
461  else if ( value.canConvert< QgsPointXY >() )
462  {
463  QgsPointXY r = value.value<QgsPointXY>();
464  return QStringLiteral( "'%1,%2'" ).arg( qgsDoubleToString( r.x() ),
465  qgsDoubleToString( r.y() ) );
466  }
467  else if ( value.canConvert< QgsReferencedPointXY >() )
468  {
469  QgsReferencedPointXY r = value.value<QgsReferencedPointXY>();
470  return QStringLiteral( "'%1,%2 [%3]'" ).arg( qgsDoubleToString( r.x() ),
471  qgsDoubleToString( r.y() ),
472  r.crs().authid() );
473  }
474 
475  switch ( value.type() )
476  {
477  case QVariant::Bool:
478  return value.toBool() ? QStringLiteral( "True" ) : QStringLiteral( "False" );
479 
480  case QVariant::Double:
481  return QString::number( value.toDouble() );
482 
483  case QVariant::Int:
484  case QVariant::UInt:
485  return QString::number( value.toInt() );
486 
487  case QVariant::LongLong:
488  case QVariant::ULongLong:
489  return QString::number( value.toLongLong() );
490 
491  case QVariant::List:
492  {
493  QStringList parts;
494  const QVariantList vl = value.toList();
495  for ( const QVariant &v : vl )
496  {
497  parts << variantToPythonLiteral( v );
498  }
499  return parts.join( ',' ).prepend( '[' ).append( ']' );
500  }
501 
502  default:
503  break;
504  }
505 
506  return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
507 }
508 
509 QString QgsProcessingUtils::stringToPythonLiteral( const QString &string )
510 {
511  QString s = string;
512  s.replace( '\\', QStringLiteral( "\\\\" ) );
513  s.replace( '\n', QStringLiteral( "\\n" ) );
514  s.replace( '\r', QStringLiteral( "\\r" ) );
515  s.replace( '\t', QStringLiteral( "\\t" ) );
516  s.replace( '"', QStringLiteral( "\\\"" ) );
517  s.replace( '\'', QStringLiteral( "\\\'" ) );
518  s = s.prepend( '\'' ).append( '\'' );
519  return s;
520 }
521 
522 void QgsProcessingUtils::parseDestinationString( QString &destination, QString &providerKey, QString &uri, QString &layerName, QString &format, QMap<QString, QVariant> &options, bool &useWriter, QString &extension )
523 {
524  extension.clear();
525  QRegularExpression splitRx( QStringLiteral( "^(.{3,}?):(.*)$" ) );
526  QRegularExpressionMatch match = splitRx.match( destination );
527  if ( match.hasMatch() )
528  {
529  providerKey = match.captured( 1 );
530  if ( providerKey == QStringLiteral( "postgis" ) ) // older processing used "postgis" instead of "postgres"
531  {
532  providerKey = QStringLiteral( "postgres" );
533  }
534  uri = match.captured( 2 );
535  if ( providerKey == QLatin1String( "ogr" ) )
536  {
537  QgsDataSourceUri dsUri( uri );
538  if ( !dsUri.database().isEmpty() )
539  {
540  if ( !dsUri.table().isEmpty() )
541  {
542  layerName = dsUri.table();
543  options.insert( QStringLiteral( "layerName" ), layerName );
544  }
545  uri = dsUri.database();
546  extension = QFileInfo( uri ).completeSuffix();
547  format = QgsVectorFileWriter::driverForExtension( extension );
548  }
549  else
550  {
551  extension = QFileInfo( uri ).completeSuffix();
552  }
553  options.insert( QStringLiteral( "update" ), true );
554  }
555  useWriter = false;
556  }
557  else
558  {
559  useWriter = true;
560  providerKey = QStringLiteral( "ogr" );
561  QRegularExpression splitRx( QStringLiteral( "^(.*)\\.(.*?)$" ) );
562  QRegularExpressionMatch match = splitRx.match( destination );
563  if ( match.hasMatch() )
564  {
565  extension = match.captured( 2 );
566  format = QgsVectorFileWriter::driverForExtension( extension );
567  }
568 
569  if ( format.isEmpty() )
570  {
571  format = QStringLiteral( "GPKG" );
572  destination = destination + QStringLiteral( ".gpkg" );
573  }
574 
575  options.insert( QStringLiteral( "driverName" ), format );
576  uri = destination;
577  }
578 }
579 
580 QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &createOptions, QgsFeatureSink::SinkFlags sinkFlags )
581 {
582  QVariantMap options = createOptions;
583  if ( !options.contains( QStringLiteral( "fileEncoding" ) ) )
584  {
585  // no destination encoding specified, use default
586  options.insert( QStringLiteral( "fileEncoding" ), context.defaultEncoding().isEmpty() ? QStringLiteral( "system" ) : context.defaultEncoding() );
587  }
588 
589  if ( destination.isEmpty() || destination.startsWith( QLatin1String( "memory:" ) ) )
590  {
591  // strip "memory:" from start of destination
592  if ( destination.startsWith( QLatin1String( "memory:" ) ) )
593  destination = destination.mid( 7 );
594 
595  if ( destination.isEmpty() )
596  destination = QStringLiteral( "output" );
597 
598  // memory provider cannot be used with QgsVectorLayerImport - so create layer manually
599  std::unique_ptr< QgsVectorLayer > layer( QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs ) );
600  if ( !layer || !layer->isValid() )
601  {
602  throw QgsProcessingException( QObject::tr( "Could not create memory layer" ) );
603  }
604 
605  // update destination to layer ID
606  destination = layer->id();
607 
608  // this is a factory, so we need to return a proxy
609  std::unique_ptr< QgsProcessingFeatureSink > sink( new QgsProcessingFeatureSink( layer->dataProvider(), destination, context ) );
610  context.temporaryLayerStore()->addMapLayer( layer.release() );
611 
612  return sink.release();
613  }
614  else
615  {
616  QString providerKey;
617  QString uri;
618  QString layerName;
619  QString format;
620  QString extension;
621  bool useWriter = false;
622  parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter, extension );
623 
624  QgsFields newFields = fields;
625  if ( useWriter && providerKey == QLatin1String( "ogr" ) )
626  {
627  // use QgsVectorFileWriter for OGR destinations instead of QgsVectorLayerImport, as that allows
628  // us to use any OGR format which supports feature addition
629  QString finalFileName;
631  saveOptions.fileEncoding = options.value( QStringLiteral( "fileEncoding" ) ).toString();
632  saveOptions.driverName = format;
637  std::unique_ptr< QgsVectorFileWriter > writer( QgsVectorFileWriter::create( destination, newFields, geometryType, crs, context.transformContext(), saveOptions, sinkFlags, &finalFileName ) );
638  if ( writer->hasError() )
639  {
640  throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, writer->errorMessage() ) );
641  }
642  destination = finalFileName;
643  return new QgsProcessingFeatureSink( writer.release(), destination, context, true );
644  }
645  else
646  {
647  //create empty layer
648  const QgsVectorLayer::LayerOptions layerOptions { context.transformContext() };
649  std::unique_ptr< QgsVectorLayerExporter > exporter = qgis::make_unique<QgsVectorLayerExporter>( uri, providerKey, newFields, geometryType, crs, true, options, sinkFlags );
650  if ( exporter->errorCode() )
651  {
652  throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, exporter->errorMessage() ) );
653  }
654 
655  // use destination string as layer name (eg "postgis:..." )
656  if ( !layerName.isEmpty() )
657  uri += QStringLiteral( "|layername=%1" ).arg( layerName );
658  std::unique_ptr< QgsVectorLayer > layer = qgis::make_unique<QgsVectorLayer>( uri, destination, providerKey, layerOptions );
659  // update destination to layer ID
660  destination = layer->id();
661 
662  context.temporaryLayerStore()->addMapLayer( layer.release() );
663  return new QgsProcessingFeatureSink( exporter.release(), destination, context, true );
664  }
665  }
666 }
667 
668 void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &options )
669 {
670  *sink = createFeatureSink( destination, context, fields, geometryType, crs, options );
671 }
672 
673 
675 {
676  QgsRectangle extent;
677  for ( const QgsMapLayer *layer : layers )
678  {
679  if ( !layer )
680  continue;
681 
682  if ( crs.isValid() )
683  {
684  //transform layer extent to target CRS
685  QgsCoordinateTransform ct( layer->crs(), crs, context.transformContext() );
686  try
687  {
688  QgsRectangle reprojExtent = ct.transformBoundingBox( layer->extent() );
689  extent.combineExtentWith( reprojExtent );
690  }
691  catch ( QgsCsException & )
692  {
693  // can't reproject... what to do here? hmmm?
694  // let's ignore this layer for now, but maybe we should just use the original extent?
695  }
696  }
697  else
698  {
699  extent.combineExtentWith( layer->extent() );
700  }
701 
702  }
703  return extent;
704 }
705 
706 // Deprecated
708 {
709  QgsProcessingContext context;
710  return QgsProcessingUtils::combineLayerExtents( layers, crs, context );
711 }
712 
713 QVariant QgsProcessingUtils::generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context )
714 {
715  if ( !input.isValid() )
716  return QStringLiteral( "memory:%1" ).arg( id.toString() );
717 
718  if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
719  {
721  QVariant newSink = generateIteratingDestination( fromVar.sink, id, context );
722  fromVar.sink = QgsProperty::fromValue( newSink );
723  return fromVar;
724  }
725  else if ( input.canConvert<QgsProperty>() )
726  {
727  QString res = input.value< QgsProperty>().valueAsString( context.expressionContext() );
728  return generateIteratingDestination( res, id, context );
729  }
730  else
731  {
732  QString res = input.toString();
733  if ( res == QgsProcessing::TEMPORARY_OUTPUT )
734  {
735  // temporary outputs map to temporary outputs!
737  }
738  else if ( res.startsWith( QLatin1String( "memory:" ) ) )
739  {
740  return res + '_' + id.toString();
741  }
742  else
743  {
744  // assume a filename type output for now
745  // TODO - uris?
746  int lastIndex = res.lastIndexOf( '.' );
747  return res.left( lastIndex ) + '_' + id.toString() + res.mid( lastIndex );
748  }
749  }
750 }
751 
753 {
754  // we maintain a list of temporary folders -- this allows us to append additional
755  // folders when a setting change causes the base temp folder to change, while deferring
756  // cleanup of ALL these temp folders until session end (we can't cleanup older folders immediately,
757  // because we don't know whether they have data in them which is still wanted)
758  static std::vector< std::unique_ptr< QTemporaryDir > > sTempFolders;
759  static QString sFolder;
760  static QMutex sMutex;
761  QMutexLocker locker( &sMutex );
762  const QString basePath = QgsSettings().value( QStringLiteral( "Processing/Configuration/TEMP_PATH2" ) ).toString();
763  if ( basePath.isEmpty() )
764  {
765  // default setting -- automatically create a temp folder
766  if ( sTempFolders.empty() )
767  {
768  const QString templatePath = QStringLiteral( "%1/processing_XXXXXX" ).arg( QDir::tempPath() );
769  std::unique_ptr< QTemporaryDir > tempFolder = qgis::make_unique< QTemporaryDir >( templatePath );
770  sFolder = tempFolder->path();
771  sTempFolders.emplace_back( std::move( tempFolder ) );
772  }
773  }
774  else if ( sFolder.isEmpty() || !sFolder.startsWith( basePath ) || sTempFolders.empty() )
775  {
776  if ( !QDir().exists( basePath ) )
777  QDir().mkpath( basePath );
778 
779  const QString templatePath = QStringLiteral( "%1/processing_XXXXXX" ).arg( basePath );
780  std::unique_ptr< QTemporaryDir > tempFolder = qgis::make_unique< QTemporaryDir >( templatePath );
781  sFolder = tempFolder->path();
782  sTempFolders.emplace_back( std::move( tempFolder ) );
783  }
784  return sFolder;
785 }
786 
787 QString QgsProcessingUtils::generateTempFilename( const QString &basename )
788 {
789  QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' );
790  QString path = tempFolder() + '/' + subPath;
791  if ( !QDir( path ).exists() ) //make sure the directory exists - it shouldn't, but lets be safe...
792  {
793  QDir tmpDir;
794  tmpDir.mkdir( path );
795  }
796  return path + '/' + QgsFileUtils::stringToSafeFilename( basename );
797 }
798 
800 {
801  auto getText = [map]( const QString & key )->QString
802  {
803  if ( map.contains( key ) )
804  return map.value( key ).toString();
805  return QString();
806  };
807 
808  QString s = QObject::tr( "<html><body><h2>Algorithm description</h2>\n" );
809  s += QStringLiteral( "<p>" ) + getText( QStringLiteral( "ALG_DESC" ) ) + QStringLiteral( "</p>\n" );
810 
811  QString inputs;
812 
813  const auto parameterDefinitions = algorithm->parameterDefinitions();
814  for ( const QgsProcessingParameterDefinition *def : parameterDefinitions )
815  {
816  inputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
817  inputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
818  }
819  if ( !inputs.isEmpty() )
820  s += QObject::tr( "<h2>Input parameters</h2>\n" ) + inputs;
821 
822  QString outputs;
823  const auto outputDefinitions = algorithm->outputDefinitions();
824  for ( const QgsProcessingOutputDefinition *def : outputDefinitions )
825  {
826  outputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
827  outputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
828  }
829  if ( !outputs.isEmpty() )
830  s += QObject::tr( "<h2>Outputs</h2>\n" ) + outputs;
831 
832  s += QLatin1String( "<br>" );
833  if ( !map.value( QStringLiteral( "ALG_CREATOR" ) ).toString().isEmpty() )
834  s += QObject::tr( "<p align=\"right\">Algorithm author: %1</p>" ).arg( getText( QStringLiteral( "ALG_CREATOR" ) ) );
835  if ( !map.value( QStringLiteral( "ALG_HELP_CREATOR" ) ).toString().isEmpty() )
836  s += QObject::tr( "<p align=\"right\">Help author: %1</p>" ).arg( getText( QStringLiteral( "ALG_HELP_CREATOR" ) ) );
837  if ( !map.value( QStringLiteral( "ALG_VERSION" ) ).toString().isEmpty() )
838  s += QObject::tr( "<p align=\"right\">Algorithm version: %1</p>" ).arg( getText( QStringLiteral( "ALG_VERSION" ) ) );
839 
840  s += QStringLiteral( "</body></html>" );
841  return s;
842 }
843 
844 QString convertToCompatibleFormatInternal( const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback, QString *layerName )
845 {
846  bool requiresTranslation = false;
847 
848  // if we are only looking for selected features then we have to export back to disk,
849  // as we need to subset only selected features, a concept which doesn't exist outside QGIS!
850  requiresTranslation = requiresTranslation || selectedFeaturesOnly;
851 
852  // if the data provider is NOT ogr, then we HAVE to convert. Otherwise we run into
853  // issues with data providers like spatialite, delimited text where the format can be
854  // opened outside of QGIS, but with potentially very different behavior!
855  requiresTranslation = requiresTranslation || vl->providerType() != QLatin1String( "ogr" );
856 
857  // if the layer has a feature filter set, then we HAVE to convert. Feature filters are
858  // a purely QGIS concept.
859  requiresTranslation = requiresTranslation || !vl->subsetString().isEmpty();
860 
861  // if the layer opened using GDAL's virtual I/O mechanism (/vsizip/, etc.), then
862  // we HAVE to convert as other tools may not work with it
863  requiresTranslation = requiresTranslation || vl->source().startsWith( QLatin1String( "/vsi" ) );
864 
865  // Check if layer is a disk based format and if so if the layer's path has a compatible filename suffix
866  QString diskPath;
867  if ( !requiresTranslation )
868  {
869  const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( vl->providerType(), vl->source() );
870  if ( parts.contains( QStringLiteral( "path" ) ) )
871  {
872  diskPath = parts.value( QStringLiteral( "path" ) ).toString();
873  QFileInfo fi( diskPath );
874  requiresTranslation = !compatibleFormats.contains( fi.suffix(), Qt::CaseInsensitive );
875 
876  // if the layer name doesn't match the filename, we need to convert the layer. This method can only return
877  // a filename, and cannot handle layernames as well as file paths
878  const QString srcLayerName = parts.value( QStringLiteral( "layerName" ) ).toString();
879  if ( layerName )
880  {
881  // differing layer names are acceptable
882  *layerName = srcLayerName;
883  }
884  else
885  {
886  // differing layer names are NOT acceptable
887  requiresTranslation = requiresTranslation || ( !srcLayerName.isEmpty() && srcLayerName != fi.baseName() );
888  }
889  }
890  else
891  {
892  requiresTranslation = true; // not a disk-based format
893  }
894  }
895 
896  if ( requiresTranslation )
897  {
898  QString temp = QgsProcessingUtils::generateTempFilename( baseName + '.' + preferredFormat );
899 
901  saveOptions.fileEncoding = context.defaultEncoding();
902  saveOptions.driverName = QgsVectorFileWriter::driverForExtension( preferredFormat );
903  std::unique_ptr< QgsVectorFileWriter > writer( QgsVectorFileWriter::create( temp, vl->fields(), vl->wkbType(), vl->crs(), context.transformContext(), saveOptions ) );
904  QgsFeature f;
906  if ( selectedFeaturesOnly )
907  it = vl->getSelectedFeatures();
908  else
909  it = vl->getFeatures();
910 
911  while ( it.nextFeature( f ) )
912  {
913  if ( feedback->isCanceled() )
914  return QString();
915  writer->addFeature( f, QgsFeatureSink::FastInsert );
916  }
917  return temp;
918  }
919  else
920  {
921  return diskPath;
922  }
923 }
924 
925 QString QgsProcessingUtils::convertToCompatibleFormat( const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
926 {
927  return convertToCompatibleFormatInternal( vl, selectedFeaturesOnly, baseName, compatibleFormats, preferredFormat, context, feedback, nullptr );
928 }
929 
930 QString QgsProcessingUtils::convertToCompatibleFormatAndLayerName( const QgsVectorLayer *layer, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback, QString &layerName )
931 {
932  layerName.clear();
933  return convertToCompatibleFormatInternal( layer, selectedFeaturesOnly, baseName, compatibleFormats, preferredFormat, context, feedback, &layerName );
934 }
935 
936 QgsFields QgsProcessingUtils::combineFields( const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix )
937 {
938  QgsFields outFields = fieldsA;
939  QSet< QString > usedNames;
940  for ( const QgsField &f : fieldsA )
941  {
942  usedNames.insert( f.name().toLower() );
943  }
944 
945  for ( const QgsField &f : fieldsB )
946  {
947  QgsField newField = f;
948  newField.setName( fieldsBPrefix + f.name() );
949  if ( usedNames.contains( newField.name().toLower() ) )
950  {
951  int idx = 2;
952  QString newName = newField.name() + '_' + QString::number( idx );
953  while ( usedNames.contains( newName.toLower() ) )
954  {
955  idx++;
956  newName = newField.name() + '_' + QString::number( idx );
957  }
958  newField.setName( newName );
959  outFields.append( newField );
960  }
961  else
962  {
963  outFields.append( newField );
964  }
965  usedNames.insert( newField.name() );
966  }
967 
968  return outFields;
969 }
970 
971 
972 QList<int> QgsProcessingUtils::fieldNamesToIndices( const QStringList &fieldNames, const QgsFields &fields )
973 {
974  QList<int> indices;
975  if ( !fieldNames.isEmpty() )
976  {
977  indices.reserve( fieldNames.count() );
978  for ( const QString &f : fieldNames )
979  {
980  int idx = fields.lookupField( f );
981  if ( idx >= 0 )
982  indices.append( idx );
983  }
984  }
985  else
986  {
987  indices.reserve( fields.count() );
988  for ( int i = 0; i < fields.count(); ++i )
989  indices.append( i );
990  }
991  return indices;
992 }
993 
994 
995 QgsFields QgsProcessingUtils::indicesToFields( const QList<int> &indices, const QgsFields &fields )
996 {
997  QgsFields fieldsSubset;
998  for ( int i : indices )
999  fieldsSubset.append( fields.at( i ) );
1000  return fieldsSubset;
1001 }
1002 
1004 {
1005  QgsSettings settings;
1006  const int setting = settings.value( QStringLiteral( "Processing/Configuration/DefaultOutputVectorLayerExt" ), -1 ).toInt();
1007  if ( setting == -1 )
1008  return QStringLiteral( "gpkg" );
1009  return QgsVectorFileWriter::supportedFormatExtensions().value( setting, QStringLiteral( "gpkg" ) );
1010 }
1011 
1013 {
1014  QgsSettings settings;
1015  const int setting = settings.value( QStringLiteral( "Processing/Configuration/DefaultOutputRasterLayerExt" ), -1 ).toInt();
1016  if ( setting == -1 )
1017  return QStringLiteral( "tif" );
1018  return QgsRasterFileWriter::supportedFormatExtensions().value( setting, QStringLiteral( "tif" ) );
1019 }
1020 
1021 //
1022 // QgsProcessingFeatureSource
1023 //
1024 
1025 QgsProcessingFeatureSource::QgsProcessingFeatureSource( QgsFeatureSource *originalSource, const QgsProcessingContext &context, bool ownsOriginalSource )
1026  : mSource( originalSource )
1027  , mOwnsSource( ownsOriginalSource )
1028  , mInvalidGeometryCheck( QgsWkbTypes::geometryType( mSource->wkbType() ) == QgsWkbTypes::PointGeometry
1029  ? QgsFeatureRequest::GeometryNoCheck // never run geometry validity checks for point layers!
1030  : context.invalidGeometryCheck() )
1031  , mInvalidGeometryCallback( context.invalidGeometryCallback() )
1032  , mTransformErrorCallback( context.transformErrorCallback() )
1033 {}
1034 
1036 {
1037  if ( mOwnsSource )
1038  delete mSource;
1039 }
1040 
1042 {
1043  QgsFeatureRequest req( request );
1044  req.setTransformErrorCallback( mTransformErrorCallback );
1045 
1046  if ( flags & FlagSkipGeometryValidityChecks )
1048  else
1049  {
1050  req.setInvalidGeometryCheck( mInvalidGeometryCheck );
1051  req.setInvalidGeometryCallback( mInvalidGeometryCallback );
1052  }
1053 
1054  return mSource->getFeatures( req );
1055 }
1056 
1058 {
1059  FeatureAvailability sourceAvailability = mSource->hasFeatures();
1060  if ( sourceAvailability == NoFeaturesAvailable )
1061  return NoFeaturesAvailable; // never going to be features if underlying source has no features
1062  else if ( mInvalidGeometryCheck == QgsFeatureRequest::GeometryNoCheck )
1063  return sourceAvailability;
1064  else
1065  // we don't know... source has features, but these may be filtered out by invalid geometry check
1066  return FeaturesMaybeAvailable;
1067 }
1068 
1070 {
1071  QgsFeatureRequest req( request );
1072  req.setInvalidGeometryCheck( mInvalidGeometryCheck );
1073  req.setInvalidGeometryCallback( mInvalidGeometryCallback );
1074  req.setTransformErrorCallback( mTransformErrorCallback );
1075  return mSource->getFeatures( req );
1076 }
1077 
1079 {
1080  return mSource->sourceCrs();
1081 }
1082 
1084 {
1085  return mSource->fields();
1086 }
1087 
1089 {
1090  return mSource->wkbType();
1091 }
1092 
1094 {
1095  return mSource->featureCount();
1096 }
1097 
1099 {
1100  return mSource->sourceName();
1101 
1102 }
1103 
1104 QSet<QVariant> QgsProcessingFeatureSource::uniqueValues( int fieldIndex, int limit ) const
1105 {
1106  return mSource->uniqueValues( fieldIndex, limit );
1107 }
1108 
1109 QVariant QgsProcessingFeatureSource::minimumValue( int fieldIndex ) const
1110 {
1111  return mSource->minimumValue( fieldIndex );
1112 }
1113 
1114 QVariant QgsProcessingFeatureSource::maximumValue( int fieldIndex ) const
1115 {
1116  return mSource->maximumValue( fieldIndex );
1117 }
1118 
1120 {
1121  return mSource->sourceExtent();
1122 }
1123 
1125 {
1126  return mSource->allFeatureIds();
1127 }
1128 
1130 {
1131  return mSource->hasSpatialIndex();
1132 }
1133 
1135 {
1136  QgsExpressionContextScope *expressionContextScope = nullptr;
1137  QgsExpressionContextScopeGenerator *generator = dynamic_cast<QgsExpressionContextScopeGenerator *>( mSource );
1138  if ( generator )
1139  {
1140  expressionContextScope = generator->createExpressionContextScope();
1141  }
1142  return expressionContextScope;
1143 }
1144 
1145 
1146 //
1147 // QgsProcessingFeatureSink
1148 //
1149 QgsProcessingFeatureSink::QgsProcessingFeatureSink( QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink )
1150  : QgsProxyFeatureSink( originalSink )
1151  , mContext( context )
1152  , mSinkName( sinkName )
1153  , mOwnsSink( ownsOriginalSink )
1154 {}
1155 
1157 {
1158  if ( mOwnsSink )
1159  delete destinationSink();
1160 }
1161 
1162 bool QgsProcessingFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
1163 {
1164  bool result = QgsProxyFeatureSink::addFeature( feature, flags );
1165  if ( !result )
1166  mContext.feedback()->reportError( QObject::tr( "Feature could not be written to %1" ).arg( mSinkName ) );
1167  return result;
1168 }
1169 
1170 bool QgsProcessingFeatureSink::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags )
1171 {
1172  bool result = QgsProxyFeatureSink::addFeatures( features, flags );
1173  if ( !result )
1174  mContext.feedback()->reportError( QObject::tr( "%1 feature(s) could not be written to %2" ).arg( features.count() ).arg( mSinkName ) );
1175  return result;
1176 }
1177 
1178 bool QgsProcessingFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags )
1179 {
1180  bool result = QgsProxyFeatureSink::addFeatures( iterator, flags );
1181  if ( !result )
1182  mContext.feedback()->reportError( QObject::tr( "Features could not be written to %1" ).arg( mSinkName ) );
1183  return result;
1184 }
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.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
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:59
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
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.
Q_INVOKABLE 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.
Represents a raster layer.
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.
Q_INVOKABLE 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:152
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.
QStringList layerOptions
List of OGR layer creation options.
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
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:99
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.
static QgsCoordinateReferenceSystem variantToCrs(const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue=QVariant())
Converts a variant value to a coordinate reference system.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
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.
Options to pass to writeAsVectorFormat()
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.
Mesh layer type, since QGIS 3.6.
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:275
There are certainly no features available in this source.
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:97
QStringList datasourceOptions
List of OGR data source creation options.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Definition: qgsmeshlayer.h:125
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
virtual SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source, if it can be determined.
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:91
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:49
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...
SpatialIndexPresence hasSpatialIndex() const override
Returns an enum value representing the presence of a valid spatial index on the source, if it can be determined.
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:885
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:55
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:91
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
SpatialIndexPresence
Enumeration of spatial index presence states.
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.
Static property (QgsStaticProperty)
Definition: qgsproperty.h:237
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...