QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 
34 QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
35 {
36  if ( !project )
37  return QList<QgsRasterLayer *>();
38 
39  QList<QgsRasterLayer *> layers;
40  Q_FOREACH ( QgsRasterLayer *l, project->layers<QgsRasterLayer *>() )
41  {
42  if ( canUseLayer( l ) )
43  layers << l;
44  }
45 
46  if ( sort )
47  {
48  std::sort( layers.begin(), layers.end(), []( const QgsRasterLayer * a, const QgsRasterLayer * b ) -> bool
49  {
50  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
51  } );
52  }
53  return layers;
54 }
55 
56 QList<QgsVectorLayer *> QgsProcessingUtils::compatibleVectorLayers( QgsProject *project, const QList<int> &geometryTypes, bool sort )
57 {
58  if ( !project )
59  return QList<QgsVectorLayer *>();
60 
61  QList<QgsVectorLayer *> layers;
62  Q_FOREACH ( QgsVectorLayer *l, project->layers<QgsVectorLayer *>() )
63  {
64  if ( canUseLayer( l, geometryTypes ) )
65  layers << l;
66  }
67 
68  if ( sort )
69  {
70  std::sort( layers.begin(), layers.end(), []( const QgsVectorLayer * a, const QgsVectorLayer * b ) -> bool
71  {
72  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
73  } );
74  }
75  return layers;
76 }
77 
78 QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project, bool sort )
79 {
80  if ( !project )
81  return QList<QgsMapLayer *>();
82 
83  QList<QgsMapLayer *> layers;
84  Q_FOREACH ( QgsRasterLayer *rl, compatibleRasterLayers( project, false ) )
85  layers << rl;
86  Q_FOREACH ( QgsVectorLayer *vl, compatibleVectorLayers( project, QList< int >(), false ) )
87  layers << vl;
88 
89  if ( sort )
90  {
91  std::sort( layers.begin(), layers.end(), []( const QgsMapLayer * a, const QgsMapLayer * b ) -> bool
92  {
93  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
94  } );
95  }
96  return layers;
97 }
98 
99 QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMapLayerStore *store, QgsProcessingUtils::LayerHint typeHint )
100 {
101  if ( !store || string.isEmpty() )
102  return nullptr;
103 
104  QList< QgsMapLayer * > layers = store->mapLayers().values();
105 
106  layers.erase( std::remove_if( layers.begin(), layers.end(), []( QgsMapLayer * layer )
107  {
108  switch ( layer->type() )
109  {
111  return !canUseLayer( qobject_cast< QgsVectorLayer * >( layer ) );
113  return !canUseLayer( qobject_cast< QgsRasterLayer * >( layer ) );
115  return true;
117  return false;
118  }
119  return true;
120  } ), layers.end() );
121 
122  auto isCompatibleType = [typeHint]( QgsMapLayer * l ) -> bool
123  {
124  switch ( typeHint )
125  {
126  case UnknownType:
127  return true;
128 
129  case Vector:
130  return l->type() == QgsMapLayer::VectorLayer;
131 
132  case Raster:
133  return l->type() == QgsMapLayer::RasterLayer;
134  }
135  return true;
136  };
137 
138  for ( QgsMapLayer *l : qgis::as_const( layers ) )
139  {
140  if ( isCompatibleType( l ) && l->id() == string )
141  return l;
142  }
143  for ( QgsMapLayer *l : qgis::as_const( layers ) )
144  {
145  if ( isCompatibleType( l ) && l->name() == string )
146  return l;
147  }
148  for ( QgsMapLayer *l : qgis::as_const( layers ) )
149  {
150  if ( isCompatibleType( l ) && normalizeLayerSource( l->source() ) == normalizeLayerSource( string ) )
151  return l;
152  }
153  return nullptr;
154 }
155 
157 class ProjectionSettingRestorer
158 {
159  public:
160 
161  ProjectionSettingRestorer()
162  {
163  QgsSettings settings;
164  previousSetting = settings.value( QStringLiteral( "/Projections/defaultBehavior" ) ).toString();
165  settings.setValue( QStringLiteral( "/Projections/defaultBehavior" ), QStringLiteral( "useProject" ) );
166  }
167 
168  ~ProjectionSettingRestorer()
169  {
170  QgsSettings settings;
171  settings.setValue( QStringLiteral( "/Projections/defaultBehavior" ), previousSetting );
172  }
173 
174  QString previousSetting;
175 };
177 
178 QgsMapLayer *QgsProcessingUtils::loadMapLayerFromString( const QString &string, LayerHint typeHint )
179 {
180  QStringList components = string.split( '|' );
181  if ( components.isEmpty() )
182  return nullptr;
183 
184  QFileInfo fi;
185  if ( QFileInfo::exists( string ) )
186  fi = QFileInfo( string );
187  else if ( QFileInfo::exists( components.at( 0 ) ) )
188  fi = QFileInfo( components.at( 0 ) );
189  else
190  return nullptr;
191 
192  // TODO - remove when there is a cleaner way to block the unknown projection dialog!
193  ProjectionSettingRestorer restorer;
194  ( void )restorer; // no warnings
195 
196  QString name = fi.baseName();
197 
198  // brute force attempt to load a matching layer
199  if ( typeHint == UnknownType || typeHint == Vector )
200  {
202  options.loadDefaultStyle = false;
203  std::unique_ptr< QgsVectorLayer > layer( new QgsVectorLayer( string, name, QStringLiteral( "ogr" ), options ) );
204  if ( layer->isValid() )
205  {
206  return layer.release();
207  }
208  }
209  if ( typeHint == UnknownType || typeHint == Raster )
210  {
211  QgsRasterLayer::LayerOptions rasterOptions;
212  rasterOptions.loadDefaultStyle = false;
213  std::unique_ptr< QgsRasterLayer > rasterLayer( new QgsRasterLayer( string, name, QStringLiteral( "gdal" ), rasterOptions ) );
214  if ( rasterLayer->isValid() )
215  {
216  return rasterLayer.release();
217  }
218  }
219  return nullptr;
220 }
221 
222 QgsMapLayer *QgsProcessingUtils::mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers, LayerHint typeHint )
223 {
224  if ( string.isEmpty() )
225  return nullptr;
226 
227  // prefer project layers
228  QgsMapLayer *layer = nullptr;
229  if ( context.project() )
230  {
231  QgsMapLayer *layer = mapLayerFromStore( string, context.project()->layerStore(), typeHint );
232  if ( layer )
233  return layer;
234  }
235 
236  layer = mapLayerFromStore( string, context.temporaryLayerStore(), typeHint );
237  if ( layer )
238  return layer;
239 
240  if ( !allowLoadingNewLayers )
241  return nullptr;
242 
243  layer = loadMapLayerFromString( string, typeHint );
244  if ( layer )
245  {
246  context.temporaryLayerStore()->addMapLayer( layer );
247  return layer;
248  }
249  else
250  {
251  return nullptr;
252  }
253 }
254 
255 QgsProcessingFeatureSource *QgsProcessingUtils::variantToSource( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue )
256 {
257  QVariant val = value;
258  bool selectedFeaturesOnly = false;
259  if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
260  {
261  // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
263  selectedFeaturesOnly = fromVar.selectedFeaturesOnly;
264  val = fromVar.source;
265  }
266  else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
267  {
268  // input is a QgsProcessingOutputLayerDefinition (e.g. an output from earlier in a model) - get extra properties from it
270  val = fromVar.sink;
271  }
272 
273  if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( val ) ) )
274  {
275  return new QgsProcessingFeatureSource( layer, context );
276  }
277 
278  QString layerRef;
279  if ( val.canConvert<QgsProperty>() )
280  {
281  layerRef = val.value< QgsProperty >().valueAsString( context.expressionContext(), fallbackValue.toString() );
282  }
283  else if ( !val.isValid() || val.toString().isEmpty() )
284  {
285  // fall back to default
286  if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( fallbackValue ) ) )
287  {
288  return new QgsProcessingFeatureSource( layer, context );
289  }
290 
291  layerRef = fallbackValue.toString();
292  }
293  else
294  {
295  layerRef = val.toString();
296  }
297 
298  if ( layerRef.isEmpty() )
299  return nullptr;
300 
301  QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context, true, Vector ) );
302  if ( !vl )
303  return nullptr;
304 
305  if ( selectedFeaturesOnly )
306  {
307  return new QgsProcessingFeatureSource( new QgsVectorLayerSelectedFeatureSource( vl ), context, true );
308  }
309  else
310  {
311  return new QgsProcessingFeatureSource( vl, context );
312  }
313 }
314 
315 bool QgsProcessingUtils::canUseLayer( const QgsRasterLayer *layer )
316 {
317  return layer && layer->isValid();
318 }
319 
320 bool QgsProcessingUtils::canUseLayer( const QgsVectorLayer *layer, const QList<int> &sourceTypes )
321 {
322  return layer && layer->isValid() &&
323  ( sourceTypes.isEmpty()
324  || ( sourceTypes.contains( QgsProcessing::TypeVectorPoint ) && layer->geometryType() == QgsWkbTypes::PointGeometry )
325  || ( sourceTypes.contains( QgsProcessing::TypeVectorLine ) && layer->geometryType() == QgsWkbTypes::LineGeometry )
326  || ( sourceTypes.contains( QgsProcessing::TypeVectorPolygon ) && layer->geometryType() == QgsWkbTypes::PolygonGeometry )
327  || ( sourceTypes.contains( QgsProcessing::TypeVectorAnyGeometry ) && layer->isSpatial() )
328  || sourceTypes.contains( QgsProcessing::TypeVector )
329  );
330 }
331 
332 QString QgsProcessingUtils::normalizeLayerSource( const QString &source )
333 {
334  QString normalized = source;
335  normalized.replace( '\\', '/' );
336  return normalized.trimmed();
337 }
338 
339 QString QgsProcessingUtils::stringToPythonLiteral( const QString &string )
340 {
341  QString s = string;
342  s.replace( '\\', QStringLiteral( "\\\\" ) );
343  s.replace( '\n', QStringLiteral( "\\n" ) );
344  s.replace( '\r', QStringLiteral( "\\r" ) );
345  s.replace( '\t', QStringLiteral( "\\t" ) );
346  s.replace( '"', QStringLiteral( "\\\"" ) );
347  s.replace( '\'', QStringLiteral( "\\\'" ) );
348  s = s.prepend( '\'' ).append( '\'' );
349  return s;
350 }
351 
352 void QgsProcessingUtils::parseDestinationString( QString &destination, QString &providerKey, QString &uri, QString &layerName, QString &format, QMap<QString, QVariant> &options, bool &useWriter, QString &extension )
353 {
354  extension.clear();
355  QRegularExpression splitRx( QStringLiteral( "^(.{3,}?):(.*)$" ) );
356  QRegularExpressionMatch match = splitRx.match( destination );
357  if ( match.hasMatch() )
358  {
359  providerKey = match.captured( 1 );
360  if ( providerKey == QStringLiteral( "postgis" ) ) // older processing used "postgis" instead of "postgres"
361  {
362  providerKey = QStringLiteral( "postgres" );
363  }
364  uri = match.captured( 2 );
365  if ( providerKey == QLatin1String( "ogr" ) )
366  {
367  QgsDataSourceUri dsUri( uri );
368  if ( !dsUri.database().isEmpty() )
369  {
370  if ( !dsUri.table().isEmpty() )
371  {
372  layerName = dsUri.table();
373  options.insert( QStringLiteral( "layerName" ), layerName );
374  }
375  uri = dsUri.database();
376  extension = QFileInfo( uri ).completeSuffix();
377  format = QgsVectorFileWriter::driverForExtension( extension );
378  }
379  else
380  {
381  extension = QFileInfo( uri ).completeSuffix();
382  }
383  options.insert( QStringLiteral( "update" ), true );
384  }
385  useWriter = false;
386  }
387  else
388  {
389  useWriter = true;
390  providerKey = QStringLiteral( "ogr" );
391  QRegularExpression splitRx( QStringLiteral( "^(.*)\\.(.*?)$" ) );
392  QRegularExpressionMatch match = splitRx.match( destination );
393  if ( match.hasMatch() )
394  {
395  extension = match.captured( 2 );
396  format = QgsVectorFileWriter::driverForExtension( extension );
397  }
398 
399  if ( format.isEmpty() )
400  {
401  format = QStringLiteral( "GPKG" );
402  destination = destination + QStringLiteral( ".gpkg" );
403  }
404 
405  options.insert( QStringLiteral( "driverName" ), format );
406  uri = destination;
407  }
408 }
409 
410 QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &createOptions, QgsFeatureSink::SinkFlags sinkFlags )
411 {
412  QVariantMap options = createOptions;
413  if ( !options.contains( QStringLiteral( "fileEncoding" ) ) )
414  {
415  // no destination encoding specified, use default
416  options.insert( QStringLiteral( "fileEncoding" ), context.defaultEncoding().isEmpty() ? QStringLiteral( "system" ) : context.defaultEncoding() );
417  }
418 
419  if ( destination.isEmpty() || destination.startsWith( QLatin1String( "memory:" ) ) )
420  {
421  // strip "memory:" from start of destination
422  if ( destination.startsWith( QLatin1String( "memory:" ) ) )
423  destination = destination.mid( 7 );
424 
425  if ( destination.isEmpty() )
426  destination = QStringLiteral( "output" );
427 
428  // memory provider cannot be used with QgsVectorLayerImport - so create layer manually
429  std::unique_ptr< QgsVectorLayer > layer( QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs ) );
430  if ( !layer || !layer->isValid() )
431  {
432  throw QgsProcessingException( QObject::tr( "Could not create memory layer" ) );
433  }
434 
435  // update destination to layer ID
436  destination = layer->id();
437 
438  // this is a factory, so we need to return a proxy
439  std::unique_ptr< QgsProcessingFeatureSink > sink( new QgsProcessingFeatureSink( layer->dataProvider(), destination, context ) );
440  context.temporaryLayerStore()->addMapLayer( layer.release() );
441 
442  return sink.release();
443  }
444  else
445  {
446  QString providerKey;
447  QString uri;
448  QString layerName;
449  QString format;
450  QString extension;
451  bool useWriter = false;
452  parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter, extension );
453 
454  QgsFields newFields = fields;
455  if ( useWriter && providerKey == QLatin1String( "ogr" ) )
456  {
457  // use QgsVectorFileWriter for OGR destinations instead of QgsVectorLayerImport, as that allows
458  // us to use any OGR format which supports feature addition
459  QString finalFileName;
460  std::unique_ptr< QgsVectorFileWriter > writer = qgis::make_unique< QgsVectorFileWriter >( destination, options.value( QStringLiteral( "fileEncoding" ) ).toString(), newFields, geometryType, crs, format, QgsVectorFileWriter::defaultDatasetOptions( format ),
461  QgsVectorFileWriter::defaultLayerOptions( format ), &finalFileName, QgsVectorFileWriter::NoSymbology, sinkFlags );
462 
463  if ( writer->hasError() )
464  {
465  throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, writer->errorMessage() ) );
466  }
467  destination = finalFileName;
468  return new QgsProcessingFeatureSink( writer.release(), destination, context, true );
469  }
470  else
471  {
472  //create empty layer
473  std::unique_ptr< QgsVectorLayerExporter > exporter( new QgsVectorLayerExporter( uri, providerKey, newFields, geometryType, crs, true, options, sinkFlags ) );
474  if ( exporter->errorCode() )
475  {
476  throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, exporter->errorMessage() ) );
477  }
478 
479  // use destination string as layer name (eg "postgis:..." )
480  if ( !layerName.isEmpty() )
481  uri += QStringLiteral( "|layername=%1" ).arg( layerName );
482  std::unique_ptr< QgsVectorLayer > layer( new QgsVectorLayer( uri, destination, providerKey ) );
483  // update destination to layer ID
484  destination = layer->id();
485 
486  context.temporaryLayerStore()->addMapLayer( layer.release() );
487  return new QgsProcessingFeatureSink( exporter.release(), destination, context, true );
488  }
489  }
490  return nullptr;
491 }
492 
493 void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &options )
494 {
495  *sink = createFeatureSink( destination, context, fields, geometryType, crs, options );
496 }
497 
498 
500 {
501  QgsRectangle extent;
502  Q_FOREACH ( QgsMapLayer *layer, layers )
503  {
504  if ( !layer )
505  continue;
506 
507  if ( crs.isValid() )
508  {
509  //transform layer extent to target CRS
511  QgsCoordinateTransform ct( layer->crs(), crs );
513  try
514  {
515  QgsRectangle reprojExtent = ct.transformBoundingBox( layer->extent() );
516  extent.combineExtentWith( reprojExtent );
517  }
518  catch ( QgsCsException & )
519  {
520  // can't reproject... what to do here? hmmm?
521  // let's ignore this layer for now, but maybe we should just use the original extent?
522  }
523  }
524  else
525  {
526  extent.combineExtentWith( layer->extent() );
527  }
528 
529  }
530  return extent;
531 }
532 
533 QVariant QgsProcessingUtils::generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context )
534 {
535  if ( !input.isValid() )
536  return QStringLiteral( "memory:%1" ).arg( id.toString() );
537 
538  if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
539  {
541  QVariant newSink = generateIteratingDestination( fromVar.sink, id, context );
542  fromVar.sink = QgsProperty::fromValue( newSink );
543  return fromVar;
544  }
545  else if ( input.canConvert<QgsProperty>() )
546  {
547  QString res = input.value< QgsProperty>().valueAsString( context.expressionContext() );
548  return generateIteratingDestination( res, id, context );
549  }
550  else
551  {
552  QString res = input.toString();
553  if ( res.startsWith( QLatin1String( "memory:" ) ) )
554  {
555  return res + '_' + id.toString();
556  }
557  else
558  {
559  // assume a filename type output for now
560  // TODO - uris?
561  int lastIndex = res.lastIndexOf( '.' );
562  return res.left( lastIndex ) + '_' + id.toString() + res.mid( lastIndex );
563  }
564  }
565 }
566 
568 {
569  static QString sFolder;
570  static QMutex sMutex;
571  sMutex.lock();
572  if ( sFolder.isEmpty() )
573  {
574  QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' );
575  sFolder = QDir::tempPath() + QStringLiteral( "/processing_" ) + subPath;
576  if ( !QDir( sFolder ).exists() )
577  QDir().mkpath( sFolder );
578  }
579  sMutex.unlock();
580  return sFolder;
581 }
582 
583 QString QgsProcessingUtils::generateTempFilename( const QString &basename )
584 {
585  QString subPath = QUuid::createUuid().toString().remove( '-' ).remove( '{' ).remove( '}' );
586  QString path = tempFolder() + '/' + subPath;
587  if ( !QDir( path ).exists() ) //make sure the directory exists - it shouldn't, but lets be safe...
588  {
589  QDir tmpDir;
590  tmpDir.mkdir( path );
591  }
592  return path + '/' + QgsFileUtils::stringToSafeFilename( basename );
593 }
594 
596 {
597  auto getText = [map]( const QString & key )->QString
598  {
599  if ( map.contains( key ) )
600  return map.value( key ).toString();
601  return QString();
602  };
603 
604  QString s = QObject::tr( "<html><body><h2>Algorithm description</h2>\n" );
605  s += QStringLiteral( "<p>" ) + getText( QStringLiteral( "ALG_DESC" ) ) + QStringLiteral( "</p>\n" );
606 
607  QString inputs;
608  Q_FOREACH ( const QgsProcessingParameterDefinition *def, algorithm->parameterDefinitions() )
609  {
610  inputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
611  inputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
612  }
613  if ( !inputs.isEmpty() )
614  s += QObject::tr( "<h2>Input parameters</h2>\n" ) + inputs;
615 
616  QString outputs;
617  Q_FOREACH ( const QgsProcessingOutputDefinition *def, algorithm->outputDefinitions() )
618  {
619  outputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
620  outputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
621  }
622  if ( !outputs.isEmpty() )
623  s += QObject::tr( "<h2>Outputs</h2>\n" ) + outputs;
624 
625  s += QLatin1String( "<br>" );
626  if ( !map.value( QStringLiteral( "ALG_CREATOR" ) ).toString().isEmpty() )
627  s += QObject::tr( "<p align=\"right\">Algorithm author: %1</p>" ).arg( getText( QStringLiteral( "ALG_CREATOR" ) ) );
628  if ( !map.value( QStringLiteral( "ALG_HELP_CREATOR" ) ).toString().isEmpty() )
629  s += QObject::tr( "<p align=\"right\">Help author: %1</p>" ).arg( getText( QStringLiteral( "ALG_HELP_CREATOR" ) ) );
630  if ( !map.value( QStringLiteral( "ALG_VERSION" ) ).toString().isEmpty() )
631  s += QObject::tr( "<p align=\"right\">Algorithm version: %1</p>" ).arg( getText( QStringLiteral( "ALG_VERSION" ) ) );
632 
633  s += QStringLiteral( "</body></html>" );
634  return s;
635 }
636 
637 QString QgsProcessingUtils::convertToCompatibleFormat( const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
638 {
639  bool requiresTranslation = false;
640 
641  // if we are only looking for selected features then we have to export back to disk,
642  // as we need to subset only selected features, a concept which doesn't exist outside QGIS!
643  requiresTranslation = requiresTranslation || selectedFeaturesOnly;
644 
645  // if the data provider is NOT ogr, then we HAVE to convert. Otherwise we run into
646  // issues with data providers like spatialite, delimited text where the format can be
647  // opened outside of QGIS, but with potentially very different behavior!
648  requiresTranslation = requiresTranslation || vl->dataProvider()->name() != QLatin1String( "ogr" );
649 
650  // if the layer has a feature filter set, then we HAVE to convert. Feature filters are
651  // a purely QGIS concept.
652  requiresTranslation = requiresTranslation || !vl->subsetString().isEmpty();
653 
654  // if the layer opened using GDAL's virtual I/O mechanism (/vsizip/, etc.), then
655  // we HAVE to convert as other tools may not work with it
656  requiresTranslation = requiresTranslation || vl->source().startsWith( QLatin1String( "/vsi" ) );
657 
658  // Check if layer is a disk based format and if so if the layer's path has a compatible filename suffix
659  QString diskPath;
660  if ( !requiresTranslation )
661  {
662  const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( vl->dataProvider()->name(), vl->source() );
663  if ( parts.contains( QStringLiteral( "path" ) ) )
664  {
665  diskPath = parts.value( QStringLiteral( "path" ) ).toString();
666  QFileInfo fi( diskPath );
667  requiresTranslation = !compatibleFormats.contains( fi.suffix(), Qt::CaseInsensitive );
668 
669  // if the layer name doesn't match the filename, we need to convert the layer. This method can only return
670  // a filename, and cannot handle layernames as well as file paths
671  const QString layerName = parts.value( QStringLiteral( "layerName" ) ).toString();
672  requiresTranslation = requiresTranslation || ( !layerName.isEmpty() && layerName != fi.baseName() );
673  }
674  else
675  {
676  requiresTranslation = true; // not a disk-based format
677  }
678  }
679 
680  if ( requiresTranslation )
681  {
682  QString temp = QgsProcessingUtils::generateTempFilename( baseName + '.' + preferredFormat );
683 
684  QgsVectorFileWriter writer( temp, context.defaultEncoding(),
685  vl->fields(), vl->wkbType(), vl->crs(), QgsVectorFileWriter::driverForExtension( preferredFormat ) );
686  QgsFeature f;
688  if ( selectedFeaturesOnly )
689  it = vl->getSelectedFeatures();
690  else
691  it = vl->getFeatures();
692 
693  while ( it.nextFeature( f ) )
694  {
695  if ( feedback->isCanceled() )
696  return QString();
697  writer.addFeature( f, QgsFeatureSink::FastInsert );
698  }
699  return temp;
700  }
701  else
702  {
703  return diskPath;
704  }
705 }
706 
708 {
709  QgsFields outFields = fieldsA;
710  QSet< QString > usedNames;
711  for ( const QgsField &f : fieldsA )
712  {
713  usedNames.insert( f.name().toLower() );
714  }
715 
716  for ( const QgsField &f : fieldsB )
717  {
718  if ( usedNames.contains( f.name().toLower() ) )
719  {
720  int idx = 2;
721  QString newName = f.name() + '_' + QString::number( idx );
722  while ( usedNames.contains( newName.toLower() ) )
723  {
724  idx++;
725  newName = f.name() + '_' + QString::number( idx );
726  }
727  QgsField newField = f;
728  newField.setName( newName );
729  outFields.append( newField );
730  usedNames.insert( newName.toLower() );
731  }
732  else
733  {
734  usedNames.insert( f.name().toLower() );
735  outFields.append( f );
736  }
737  }
738 
739  return outFields;
740 }
741 
742 
743 QList<int> QgsProcessingUtils::fieldNamesToIndices( const QStringList &fieldNames, const QgsFields &fields )
744 {
745  QList<int> indices;
746  if ( !fieldNames.isEmpty() )
747  {
748  indices.reserve( fieldNames.count() );
749  for ( const QString &f : fieldNames )
750  {
751  int idx = fields.lookupField( f );
752  if ( idx >= 0 )
753  indices.append( idx );
754  }
755  }
756  else
757  {
758  indices.reserve( fields.count() );
759  for ( int i = 0; i < fields.count(); ++i )
760  indices.append( i );
761  }
762  return indices;
763 }
764 
765 
766 QgsFields QgsProcessingUtils::indicesToFields( const QList<int> &indices, const QgsFields &fields )
767 {
768  QgsFields fieldsSubset;
769  for ( int i : indices )
770  fieldsSubset.append( fields.at( i ) );
771  return fieldsSubset;
772 }
773 
774 
775 //
776 // QgsProcessingFeatureSource
777 //
778 
779 QgsProcessingFeatureSource::QgsProcessingFeatureSource( QgsFeatureSource *originalSource, const QgsProcessingContext &context, bool ownsOriginalSource )
780  : mSource( originalSource )
781  , mOwnsSource( ownsOriginalSource )
782  , mInvalidGeometryCheck( QgsWkbTypes::geometryType( mSource->wkbType() ) == QgsWkbTypes::PointGeometry
783  ? QgsFeatureRequest::GeometryNoCheck // never run geometry validity checks for point layers!
784  : context.invalidGeometryCheck() )
785  , mInvalidGeometryCallback( context.invalidGeometryCallback() )
786  , mTransformErrorCallback( context.transformErrorCallback() )
787 {}
788 
790 {
791  if ( mOwnsSource )
792  delete mSource;
793 }
794 
796 {
797  QgsFeatureRequest req( request );
798  req.setTransformErrorCallback( mTransformErrorCallback );
799 
800  if ( flags & FlagSkipGeometryValidityChecks )
802  else
803  {
804  req.setInvalidGeometryCheck( mInvalidGeometryCheck );
805  req.setInvalidGeometryCallback( mInvalidGeometryCallback );
806  }
807 
808  return mSource->getFeatures( req );
809 }
810 
812 {
813  FeatureAvailability sourceAvailability = mSource->hasFeatures();
814  if ( sourceAvailability == NoFeaturesAvailable )
815  return NoFeaturesAvailable; // never going to be features if underlying source has no features
816  else if ( mInvalidGeometryCheck == QgsFeatureRequest::GeometryNoCheck )
817  return sourceAvailability;
818  else
819  // we don't know... source has features, but these may be filtered out by invalid geometry check
820  return FeaturesMaybeAvailable;
821 }
822 
824 {
825  QgsFeatureRequest req( request );
826  req.setInvalidGeometryCheck( mInvalidGeometryCheck );
827  req.setInvalidGeometryCallback( mInvalidGeometryCallback );
828  req.setTransformErrorCallback( mTransformErrorCallback );
829  return mSource->getFeatures( req );
830 }
831 
833 {
834  return mSource->sourceCrs();
835 }
836 
838 {
839  return mSource->fields();
840 }
841 
843 {
844  return mSource->wkbType();
845 }
846 
848 {
849  return mSource->featureCount();
850 }
851 
853 {
854  return mSource->sourceName();
855 
856 }
857 
858 QSet<QVariant> QgsProcessingFeatureSource::uniqueValues( int fieldIndex, int limit ) const
859 {
860  return mSource->uniqueValues( fieldIndex, limit );
861 }
862 
863 QVariant QgsProcessingFeatureSource::minimumValue( int fieldIndex ) const
864 {
865  return mSource->minimumValue( fieldIndex );
866 }
867 
868 QVariant QgsProcessingFeatureSource::maximumValue( int fieldIndex ) const
869 {
870  return mSource->maximumValue( fieldIndex );
871 }
872 
874 {
875  return mSource->sourceExtent();
876 }
877 
879 {
880  return mSource->allFeatureIds();
881 }
882 
884 {
885  QgsExpressionContextScope *expressionContextScope = nullptr;
886  QgsExpressionContextScopeGenerator *generator = dynamic_cast<QgsExpressionContextScopeGenerator *>( mSource );
887  if ( generator )
888  {
889  expressionContextScope = generator->createExpressionContextScope();
890  }
891  return expressionContextScope;
892 }
893 
894 
895 //
896 // QgsProcessingFeatureSink
897 //
898 QgsProcessingFeatureSink::QgsProcessingFeatureSink( QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink )
899  : QgsProxyFeatureSink( originalSink )
900  , mContext( context )
901  , mSinkName( sinkName )
902  , mOwnsSink( ownsOriginalSink )
903 {}
904 
906 {
907  if ( mOwnsSink )
908  delete destinationSink();
909 }
910 
911 bool QgsProcessingFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
912 {
913  bool result = QgsProxyFeatureSink::addFeature( feature, flags );
914  if ( !result )
915  mContext.feedback()->reportError( QObject::tr( "Feature could not be written to %1" ).arg( mSinkName ) );
916  return result;
917 }
918 
919 bool QgsProcessingFeatureSink::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags )
920 {
921  bool result = QgsProxyFeatureSink::addFeatures( features, flags );
922  if ( !result )
923  mContext.feedback()->reportError( QObject::tr( "%1 feature(s) could not be written to %2" ).arg( features.count() ).arg( mSinkName ) );
924  return result;
925 }
926 
927 bool QgsProcessingFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags )
928 {
929  bool result = !QgsProxyFeatureSink::addFeatures( iterator, flags );
930  if ( !result )
931  mContext.feedback()->reportError( QObject::tr( "Features could not be written to %1" ).arg( mSinkName ) );
932  return result;
933 }
QgsProperty sink
Sink/layer definition.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Wrapper for iterator of features from vector data provider or vector layer.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
virtual QVariant maximumValue(int fieldIndex) const
Returns the maximum value for an attribute column or an invalid variant in case of error...
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:40
QgsWkbTypes::Type wkbType() const override
Returns the geometry type for features returned by this source.
Base class for all map layer types.
Definition: qgsmaplayer.h:63
static QgsRectangle combineLayerExtents(const QList< QgsMapLayer * > &layers, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Combines the extent of several map layers.
bool loadDefaultStyle
Sets to true if the default layer style should be loaded.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QgsFeatureRequest & setInvalidGeometryCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering an invalid geometry and invalidGeometryCheck() is s...
bool isValid() const
Returns the status of the layer.
Base class for providing feedback from a processing 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.
QgsProcessingParameterDefinitions parameterDefinitions() const
Returns an ordered list of parameter definitions utilized by the algorithm.
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.
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...
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.
QString name() const
Returns the name of the parameter.
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Setting options for loading vector layers.
LayerHint
Layer type hints.
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
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.
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:614
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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:136
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
QString source() const
Returns the source for the layer.
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Returns the components (e.g.
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
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...
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
QgsExpressionContextScope * createExpressionContextScope() const
Returns an expression context scope suitable for this source.
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...
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 to a vector layer of compatible format.
QgsRectangle sourceExtent() const override
Returns the extent of all geometries from the source.
QString description() const
Returns the description for the output.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
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.
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.
virtual QString name() const =0
Returns a provider name.
bool selectedFeaturesOnly
True if only selected features in the source should be used by algorithms.
Added in 3.2.
Definition: qgsmaplayer.h:110
QString database() const
Returns the database.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
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.
virtual QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const
Returns the set of unique values contained within the specified fieldIndex from this source...
QgsProcessingFeedback * feedback()
Returns the associated feedback object.
QString defaultEncoding() const
Returns the default encoding to use for newly created files.
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.
QgsFields fields() const override
Returns the fields associated with features in the source.
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.
virtual QgsRectangle extent() const
Returns the extent of the layer.
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...
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB)
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
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.
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all layers by layer ID.
virtual QgsRectangle sourceExtent() const
Returns the extent of all geometries from the source.
There are certainly no features available in this source.
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 QList< QgsMapLayer * > compatibleLayers(QgsProject *project, bool sort=true)
Returns a list of map layers from a project which are compatible with the processing framework...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request, Flags flags) const
Returns an iterator for the features in the source, respecting the supplied feature flags...
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
Reads and writes project states.
Definition: qgsproject.h:89
Vector polygon layers.
Definition: qgsprocessing.h:50
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
No invalid geometry checking.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a single feature to the sink.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
QString description() const
Returns the description for the parameter.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:320
Single scope for storing variables and functions for use within a QgsExpressionContext.
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
QgsExpressionContext & expressionContext()
Returns the expression context.
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...
A convenience class for exporting vector layers to a destination data provider.
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.
Encapsulates settings relating to a feature source input to a processing algorithm.
static QString generateTempFilename(const QString &basename)
Returns a temporary filename for a given file, putting it into a temporary folder (creating that fold...
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:358
Base class for the definition of processing outputs.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:615
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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.
virtual QgsExpressionContextScope * createExpressionContextScope() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsFeatureSource subclass for the selected features from a QgsVectorLayer.
virtual QVariant minimumValue(int fieldIndex) const
Returns the minimum value for an attribute column or an invalid variant in case of error...
QgsMapLayer * addMapLayer(QgsMapLayer *layer, bool takeOwnership=true)
Add a layer to the store.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
Definition: qgsproject.h:738
Vector point layers.
Definition: qgsprocessing.h:48
Abstract interface for generating an expression context scope.
An interface for objects which provide features via a getFeatures method.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QgsFeatureSource::FeatureAvailability hasFeatures() const override
Determines if there are any features available in the source.
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
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
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
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.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query the layer for features specified in request.
QString name
Definition: qgsmaplayer.h:67
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
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.
There may be features available in this source.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer&#39;s data provider.
QString name() const
Returns the name of the output.
bool nextFeature(QgsFeature &f)
QgsFeatureSink * destinationSink()
Returns the destination QgsFeatureSink which the proxy will forward features to.
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, LayerHint typeHint=UnknownType)
Interprets a string as a map layer within the supplied context.
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 PostgreSQL/RDBMS datasource URI.
Represents a vector layer which manages a vector based data sets.
QString table() const
Returns the table.
Contains information about the context in which a processing algorithm is executed.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Any vector layer with geometry.
Definition: qgsprocessing.h:47
virtual FeatureAvailability hasFeatures() const
Determines if there are any features available in the source.
Setting options for loading raster layers.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:70
QgsProcessingOutputDefinitions outputDefinitions() const
Returns an ordered list of output definitions utilized by the algorithm.
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...
QgsProcessingFeatureSink(QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink=false)
Constructor for QgsProcessingFeatureSink, accepting an original feature sink originalSink and process...