QGIS API Documentation  3.0.2-Girona (307d082)
qgsprocessingalgorithm.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingalgorithm.cpp
3  --------------------------
4  begin : December 2016
5  copyright : (C) 2016 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 "qgsprocessingalgorithm.h"
19 #include "qgsapplication.h"
20 #include "qgsprocessingprovider.h"
22 #include "qgsprocessingoutputs.h"
23 #include "qgsrectangle.h"
24 #include "qgsprocessingcontext.h"
25 #include "qgsprocessingutils.h"
26 #include "qgsexception.h"
27 #include "qgsmessagelog.h"
28 #include "qgsprocessingfeedback.h"
29 
31 {
32  qDeleteAll( mParameters );
33  qDeleteAll( mOutputs );
34 }
35 
36 QgsProcessingAlgorithm *QgsProcessingAlgorithm::create( const QVariantMap &configuration ) const
37 {
38  std::unique_ptr< QgsProcessingAlgorithm > creation( createInstance() );
39  creation->setProvider( provider() );
40  creation->initAlgorithm( configuration );
41  return creation.release();
42 }
43 
45 {
46  if ( mProvider )
47  return QStringLiteral( "%1:%2" ).arg( mProvider->id(), name() );
48  else
49  return name();
50 }
51 
53 {
54  return QString();
55 }
56 
58 {
59  return QString();
60 }
61 
63 {
64  return QString();
65 }
66 
68 {
69  return QgsApplication::getThemeIcon( "/processingAlgorithm.svg" );
70 }
71 
73 {
74  return QgsApplication::iconPath( QStringLiteral( "processingAlgorithm.svg" ) );
75 }
76 
77 QgsProcessingAlgorithm::Flags QgsProcessingAlgorithm::flags() const
78 {
80 }
81 
82 bool QgsProcessingAlgorithm::canExecute( QString * ) const
83 {
84  return true;
85 }
86 
87 bool QgsProcessingAlgorithm::checkParameterValues( const QVariantMap &parameters, QgsProcessingContext &context, QString *message ) const
88 {
89  Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters )
90  {
91  if ( !def->checkValueIsAcceptable( parameters.value( def->name() ), &context ) )
92  {
93  if ( message )
94  *message = QObject::tr( "Incorrect parameter value for %1" ).arg( def->name() );
95  return false;
96  }
97  }
98  return true;
99 }
100 
101 QVariantMap QgsProcessingAlgorithm::preprocessParameters( const QVariantMap &parameters )
102 {
103  return parameters;
104 }
105 
107 {
108  return mProvider;
109 }
110 
112 {
113  mProvider = provider;
114 
115  if ( mProvider && !mProvider->supportsNonFileBasedOutput() )
116  {
117  // need to update all destination parameters to turn off non file based outputs
118  Q_FOREACH ( const QgsProcessingParameterDefinition *definition, mParameters )
119  {
120  if ( definition->isDestination() )
121  {
122  const QgsProcessingDestinationParameter *destParam = static_cast< const QgsProcessingDestinationParameter *>( definition );
123  const_cast< QgsProcessingDestinationParameter *>( destParam )->setSupportsNonFileBasedOutput( false );
124  }
125  }
126  }
127 }
128 
130 {
131  return nullptr;
132 }
133 
135  QgsProcessingContext &context, QgsProcessingFeatureSource *source ) const
136 {
137  // start with context's expression context
139 
140  // If there's a source capable of generating a context scope, use it
141  if ( source )
142  {
144  if ( scope )
145  c << scope;
146  }
147  else if ( c.scopeCount() == 0 )
148  {
149  //empty scope, populate with initial scopes
152  }
153 
154  c << QgsExpressionContextUtils::processingAlgorithmScope( this, parameters, context );
155  return c;
156 }
157 
158 bool QgsProcessingAlgorithm::validateInputCrs( const QVariantMap &parameters, QgsProcessingContext &context ) const
159 {
160  if ( !( flags() & FlagRequiresMatchingCrs ) )
161  {
162  // I'm a well behaved algorithm - I take work AWAY from users!
163  return true;
164  }
165 
166  bool foundCrs = false;
168  Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters )
169  {
170  if ( def->type() == QStringLiteral( "layer" ) || def->type() == QStringLiteral( "raster" ) )
171  {
172  QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( def, parameters, context );
173  if ( layer )
174  {
175  if ( foundCrs && layer->crs().isValid() && crs != layer->crs() )
176  {
177  return false;
178  }
179  else if ( !foundCrs && layer->crs().isValid() )
180  {
181  foundCrs = true;
182  crs = layer->crs();
183  }
184  }
185  }
186  else if ( def->type() == QStringLiteral( "source" ) )
187  {
188  std::unique_ptr< QgsFeatureSource > source( QgsProcessingParameters::parameterAsSource( def, parameters, context ) );
189  if ( source )
190  {
191  if ( foundCrs && source->sourceCrs().isValid() && crs != source->sourceCrs() )
192  {
193  return false;
194  }
195  else if ( !foundCrs && source->sourceCrs().isValid() )
196  {
197  foundCrs = true;
198  crs = source->sourceCrs();
199  }
200  }
201  }
202  else if ( def->type() == QStringLiteral( "multilayer" ) )
203  {
204  QList< QgsMapLayer *> layers = QgsProcessingParameters::parameterAsLayerList( def, parameters, context );
205  Q_FOREACH ( QgsMapLayer *layer, layers )
206  {
207  if ( !layer )
208  continue;
209 
210  if ( foundCrs && layer->crs().isValid() && crs != layer->crs() )
211  {
212  return false;
213  }
214  else if ( !foundCrs && layer->crs().isValid() )
215  {
216  foundCrs = true;
217  crs = layer->crs();
218  }
219  }
220  }
221  }
222  return true;
223 }
224 
225 QString QgsProcessingAlgorithm::asPythonCommand( const QVariantMap &parameters, QgsProcessingContext &context ) const
226 {
227  QString s = QStringLiteral( "processing.run(\"%1\"," ).arg( id() );
228 
229  QStringList parts;
230  Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters )
231  {
233  continue;
234 
235  if ( !parameters.contains( def->name() ) || !parameters.value( def->name() ).isValid() )
236  continue;
237 
238  parts << QStringLiteral( "'%1':%2" ).arg( def->name(), def->valueAsPythonString( parameters.value( def->name() ), context ) );
239  }
240 
241  s += QStringLiteral( " {%1})" ).arg( parts.join( ',' ) );
242  return s;
243 }
244 
246 {
247  if ( !definition )
248  return false;
249 
250  // check for duplicate named parameters
252  if ( existingDef && existingDef->name() == definition->name() ) // parameterDefinition is case-insensitive, but we DO allow case-different duplicate names
253  {
254  QgsMessageLog::logMessage( QObject::tr( "Duplicate parameter %1 registered for alg %2" ).arg( definition->name(), id() ), QObject::tr( "Processing" ) );
255  delete definition;
256  return false;
257  }
258 
259  if ( definition->isDestination() && mProvider )
260  {
261  QgsProcessingDestinationParameter *destParam = static_cast< QgsProcessingDestinationParameter *>( definition );
262  if ( !mProvider->supportsNonFileBasedOutput() )
263  destParam->setSupportsNonFileBasedOutput( false );
264  }
265 
266  mParameters << definition;
267  definition->mAlgorithm = this;
268 
269  if ( createOutput )
270  return createAutoOutputForParameter( definition );
271  else
272  return true;
273 }
274 
276 {
278  if ( def )
279  {
280  delete def;
281  mParameters.removeAll( def );
282  }
283 }
284 
286 {
287  if ( !definition )
288  return false;
289 
290  // check for duplicate named outputs
291  if ( QgsProcessingAlgorithm::outputDefinition( definition->name() ) )
292  {
293  QgsMessageLog::logMessage( QObject::tr( "Duplicate output %1 registered for alg %2" ).arg( definition->name(), id() ), QObject::tr( "Processing" ) );
294  delete definition;
295  return false;
296  }
297 
298  mOutputs << definition;
299  return true;
300 }
301 
303 {
304  return true;
305 }
306 
308 {
309  return QVariantMap();
310 }
311 
313 {
314  // first pass - case sensitive match
315  for ( const QgsProcessingParameterDefinition *def : mParameters )
316  {
317  if ( def->name() == name )
318  return def;
319  }
320 
321  // second pass - case insensitive
322  for ( const QgsProcessingParameterDefinition *def : mParameters )
323  {
324  if ( def->name().compare( name, Qt::CaseInsensitive ) == 0 )
325  return def;
326  }
327  return nullptr;
328 }
329 
331 {
332  int count = 0;
333  Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters )
334  {
336  count++;
337  }
338  return count;
339 }
340 
342 {
344  Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters )
345  {
346  if ( !def->isDestination() )
347  continue;
348 
349  result << def;
350  }
351  return result;
352 }
353 
355 {
356  Q_FOREACH ( const QgsProcessingOutputDefinition *def, mOutputs )
357  {
358  if ( def->name().compare( name, Qt::CaseInsensitive ) == 0 )
359  return def;
360  }
361  return nullptr;
362 }
363 
365 {
366  Q_FOREACH ( const QgsProcessingOutputDefinition *def, mOutputs )
367  {
368  if ( def->type() == QStringLiteral( "outputHtml" ) )
369  return true;
370  }
371  return false;
372 }
373 
374 QVariantMap QgsProcessingAlgorithm::run( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool *ok ) const
375 {
376  std::unique_ptr< QgsProcessingAlgorithm > alg( create() );
377  if ( ok )
378  *ok = false;
379 
380  bool res = alg->prepare( parameters, context, feedback );
381  if ( !res )
382  return QVariantMap();
383 
384  QVariantMap runRes;
385  try
386  {
387  runRes = alg->runPrepared( parameters, context, feedback );
388  }
389  catch ( QgsProcessingException &e )
390  {
391  QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), Qgis::Critical );
392  feedback->reportError( e.what() );
393  return QVariantMap();
394  }
395 
396  if ( ok )
397  *ok = true;
398 
399  QVariantMap ppRes = alg->postProcess( context, feedback );
400  if ( !ppRes.isEmpty() )
401  return ppRes;
402  else
403  return runRes;
404 }
405 
406 bool QgsProcessingAlgorithm::prepare( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
407 {
408  Q_ASSERT_X( QThread::currentThread() == context.temporaryLayerStore()->thread(), "QgsProcessingAlgorithm::prepare", "prepare() must be called from the same thread as context was created in" );
409  Q_ASSERT_X( !mHasPrepared, "QgsProcessingAlgorithm::prepare", "prepare() has already been called for the algorithm instance" );
410  try
411  {
412  mHasPrepared = prepareAlgorithm( parameters, context, feedback );
413  return mHasPrepared;
414  }
415  catch ( QgsProcessingException &e )
416  {
417  QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), Qgis::Critical );
418  feedback->reportError( e.what() );
419  return false;
420  }
421 }
422 
423 QVariantMap QgsProcessingAlgorithm::runPrepared( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
424 {
425  Q_ASSERT_X( mHasPrepared, "QgsProcessingAlgorithm::runPrepared", QString( "prepare() was not called for the algorithm instance %1" ).arg( name() ).toLatin1() );
426  Q_ASSERT_X( !mHasExecuted, "QgsProcessingAlgorithm::runPrepared", "runPrepared() was already called for this algorithm instance" );
427 
428  // Hey kids, let's all be thread safe! It's the fun thing to do!
429  //
430  // First, let's see if we're going to run into issues.
431  QgsProcessingContext *runContext = nullptr;
432  if ( context.thread() == QThread::currentThread() )
433  {
434  // OH. No issues. Seems you're running everything in the same thread, so go about your business. Sorry about
435  // the intrusion, we're just making sure everything's nice and safe here. We like to keep a clean and tidy neighbourhood,
436  // you know, for the kids and dogs and all.
437  runContext = &context;
438  }
439  else
440  {
441  // HA! I knew things looked a bit suspicious - seems you're running this algorithm in a different thread
442  // from that which the passed context has an affinity for. That's fine and all, but we need to make sure
443  // we proceed safely...
444 
445  // So first we create a temporary local context with affinity for the current thread
446  mLocalContext.reset( new QgsProcessingContext() );
447  // copy across everything we can safely do from the passed context
448  mLocalContext->copyThreadSafeSettings( context );
449  // and we'll run the actual algorithm processing using the local thread safe context
450  runContext = mLocalContext.get();
451  }
452 
453  try
454  {
455  QVariantMap runResults = processAlgorithm( parameters, *runContext, feedback );
456 
457  mHasExecuted = true;
458  if ( mLocalContext )
459  {
460  // ok, time to clean things up. We need to push the temporary context back into
461  // the thread that the passed context is associated with (we can only push from the
462  // current thread, so we HAVE to do this here)
463  mLocalContext->pushToThread( context.thread() );
464  }
465  return runResults;
466  }
467  catch ( QgsProcessingException & )
468  {
469  if ( mLocalContext )
470  {
471  // see above!
472  mLocalContext->pushToThread( context.thread() );
473  }
474  //rethrow
475  throw;
476  }
477 }
478 
480 {
481  Q_ASSERT_X( QThread::currentThread() == context.temporaryLayerStore()->thread(), "QgsProcessingAlgorithm::postProcess", "postProcess() must be called from the same thread the context was created in" );
482  Q_ASSERT_X( mHasExecuted, "QgsProcessingAlgorithm::postProcess", QString( "algorithm instance %1 was not executed" ).arg( name() ).toLatin1() );
483  Q_ASSERT_X( !mHasPostProcessed, "QgsProcessingAlgorithm::postProcess", "postProcess() was already called for this algorithm instance" );
484 
485  if ( mLocalContext )
486  {
487  // algorithm was processed using a temporary thread safe context. So now we need
488  // to take the results from that temporary context, and smash them into the passed
489  // context
490  context.takeResultsFrom( *mLocalContext );
491  // now get lost, we don't need you anymore
492  mLocalContext.reset();
493  }
494 
495  mHasPostProcessed = true;
496  try
497  {
498  return postProcessAlgorithm( context, feedback );
499  }
500  catch ( QgsProcessingException &e )
501  {
502  QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), Qgis::Critical );
503  feedback->reportError( e.what() );
504  return QVariantMap();
505  }
506 }
507 
508 QString QgsProcessingAlgorithm::parameterAsString( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
509 {
510  return QgsProcessingParameters::parameterAsString( parameterDefinition( name ), parameters, context );
511 }
512 
513 QString QgsProcessingAlgorithm::parameterAsExpression( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
514 {
515  return QgsProcessingParameters::parameterAsExpression( parameterDefinition( name ), parameters, context );
516 }
517 
518 double QgsProcessingAlgorithm::parameterAsDouble( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
519 {
520  return QgsProcessingParameters::parameterAsDouble( parameterDefinition( name ), parameters, context );
521 }
522 
523 int QgsProcessingAlgorithm::parameterAsInt( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
524 {
525  return QgsProcessingParameters::parameterAsInt( parameterDefinition( name ), parameters, context );
526 }
527 
528 int QgsProcessingAlgorithm::parameterAsEnum( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
529 {
530  return QgsProcessingParameters::parameterAsEnum( parameterDefinition( name ), parameters, context );
531 }
532 
533 QList<int> QgsProcessingAlgorithm::parameterAsEnums( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
534 {
535  return QgsProcessingParameters::parameterAsEnums( parameterDefinition( name ), parameters, context );
536 }
537 
538 bool QgsProcessingAlgorithm::parameterAsBool( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
539 {
540  return QgsProcessingParameters::parameterAsBool( parameterDefinition( name ), parameters, context );
541 }
542 
543 QgsFeatureSink *QgsProcessingAlgorithm::parameterAsSink( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QString &destinationIdentifier, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs ) const
544 {
545  return QgsProcessingParameters::parameterAsSink( parameterDefinition( name ), parameters, fields, geometryType, crs, context, destinationIdentifier );
546 }
547 
548 QgsProcessingFeatureSource *QgsProcessingAlgorithm::parameterAsSource( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
549 {
550  return QgsProcessingParameters::parameterAsSource( parameterDefinition( name ), parameters, context );
551 }
552 
553 QString QgsProcessingAlgorithm::parameterAsCompatibleSourceLayerPath( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback )
554 {
555  return QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( parameterDefinition( name ), parameters, context, compatibleFormats, preferredFormat, feedback );
556 }
557 
558 QgsMapLayer *QgsProcessingAlgorithm::parameterAsLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
559 {
560  return QgsProcessingParameters::parameterAsLayer( parameterDefinition( name ), parameters, context );
561 }
562 
563 QgsRasterLayer *QgsProcessingAlgorithm::parameterAsRasterLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
564 {
565  return QgsProcessingParameters::parameterAsRasterLayer( parameterDefinition( name ), parameters, context );
566 }
567 
568 QString QgsProcessingAlgorithm::parameterAsOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
569 {
570  return QgsProcessingParameters::parameterAsOutputLayer( parameterDefinition( name ), parameters, context );
571 }
572 
573 QString QgsProcessingAlgorithm::parameterAsFileOutput( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
574 {
575  return QgsProcessingParameters::parameterAsFileOutput( parameterDefinition( name ), parameters, context );
576 }
577 
578 QgsVectorLayer *QgsProcessingAlgorithm::parameterAsVectorLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
579 {
580  return QgsProcessingParameters::parameterAsVectorLayer( parameterDefinition( name ), parameters, context );
581 }
582 
583 QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
584 {
585  return QgsProcessingParameters::parameterAsCrs( parameterDefinition( name ), parameters, context );
586 }
587 
589 {
590  return QgsProcessingParameters::parameterAsExtentCrs( parameterDefinition( name ), parameters, context );
591 }
592 
593 QgsRectangle QgsProcessingAlgorithm::parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
594 {
595  return QgsProcessingParameters::parameterAsExtent( parameterDefinition( name ), parameters, context, crs );
596 }
597 
599 {
600  return QgsProcessingParameters::parameterAsExtentGeometry( parameterDefinition( name ), parameters, context, crs );
601 }
602 
603 QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
604 {
605  return QgsProcessingParameters::parameterAsPoint( parameterDefinition( name ), parameters, context, crs );
606 }
607 
609 {
610  return QgsProcessingParameters::parameterAsPointCrs( parameterDefinition( name ), parameters, context );
611 }
612 
613 QString QgsProcessingAlgorithm::parameterAsFile( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
614 {
615  return QgsProcessingParameters::parameterAsFile( parameterDefinition( name ), parameters, context );
616 }
617 
618 QVariantList QgsProcessingAlgorithm::parameterAsMatrix( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
619 {
620  return QgsProcessingParameters::parameterAsMatrix( parameterDefinition( name ), parameters, context );
621 }
622 
623 QList<QgsMapLayer *> QgsProcessingAlgorithm::parameterAsLayerList( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
624 {
625  return QgsProcessingParameters::parameterAsLayerList( parameterDefinition( name ), parameters, context );
626 }
627 
628 QList<double> QgsProcessingAlgorithm::parameterAsRange( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
629 {
630  return QgsProcessingParameters::parameterAsRange( parameterDefinition( name ), parameters, context );
631 }
632 
633 QStringList QgsProcessingAlgorithm::parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
634 {
635  return QgsProcessingParameters::parameterAsFields( parameterDefinition( name ), parameters, context );
636 }
637 
638 bool QgsProcessingAlgorithm::createAutoOutputForParameter( QgsProcessingParameterDefinition *parameter )
639 {
640  if ( !parameter->isDestination() )
641  return true; // nothing created, but nothing went wrong - so return true
642 
643  QgsProcessingDestinationParameter *dest = static_cast< QgsProcessingDestinationParameter * >( parameter );
645  if ( !output )
646  return true; // nothing created - but nothing went wrong - so return true
647 
648  if ( !addOutput( output ) )
649  {
650  // couldn't add output - probably a duplicate name
651  return false;
652  }
653  else
654  {
655  return true;
656  }
657 }
658 
659 
660 //
661 // QgsProcessingFeatureBasedAlgorithm
662 //
663 
664 void QgsProcessingFeatureBasedAlgorithm::initAlgorithm( const QVariantMap &config )
665 {
666  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), inputLayerTypes() ) );
667  initParameters( config );
668  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), outputName(), outputLayerType() ) );
669 }
670 
672 {
673  return QList<int>();
674 }
675 
677 {
679 }
680 
682 {
683  return static_cast<QgsProcessingFeatureSource::Flag>( 0 );
684 }
685 
687 {
688  return inputWkbType;
689 }
690 
692 {
693  return inputFields;
694 }
695 
697 {
698  return inputCrs;
699 }
700 
702 {
703 }
704 
706 {
707  if ( mSource )
708  return mSource->sourceCrs();
709  else
711 }
712 
713 QVariantMap QgsProcessingFeatureBasedAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
714 {
715  mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
716  if ( !mSource )
717  return QVariantMap();
718 
719  QString dest;
720  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest,
721  outputFields( mSource->fields() ),
722  outputWkbType( mSource->wkbType() ),
723  outputCrs( mSource->sourceCrs() ) ) );
724  if ( !sink )
725  return QVariantMap();
726 
727  // prepare expression context for feature iteration
728  QgsExpressionContext prevContext = context.expressionContext();
729  QgsExpressionContext algContext = prevContext;
730 
731  algContext.appendScopes( createExpressionContext( parameters, context, dynamic_cast< QgsProcessingFeatureSource * >( mSource.get() ) ).takeScopes() );
732  context.setExpressionContext( algContext );
733 
734  long count = mSource->featureCount();
735 
736  QgsFeature f;
737  QgsFeatureIterator it = mSource->getFeatures( QgsFeatureRequest(), sourceFlags() );
738 
739  double step = count > 0 ? 100.0 / count : 1;
740  int current = 0;
741  while ( it.nextFeature( f ) )
742  {
743  if ( feedback->isCanceled() )
744  {
745  break;
746  }
747 
748  context.expressionContext().setFeature( f );
749  const QgsFeatureList transformed = processFeature( f, context, feedback );
750  for ( QgsFeature transformedFeature : transformed )
751  sink->addFeature( transformedFeature, QgsFeatureSink::FastInsert );
752 
753  feedback->setProgress( current * step );
754  current++;
755  }
756 
757  mSource.reset();
758 
759  // probably not necessary - context's aren't usually recycled, but can't hurt
760  context.setExpressionContext( prevContext );
761 
762  QVariantMap outputs;
763  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
764  return outputs;
765 }
766 
768 {
769  return QgsFeatureRequest();
770 }
static QgsCoordinateReferenceSystem parameterAsCrs(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a coordinate reference system.
virtual QgsFields outputFields(const QgsFields &inputFields) const
Maps the input source fields (inputFields) to corresponding output fields generated by the algorithm...
QList< const QgsProcessingParameterDefinition *> QgsProcessingParameterDefinitions
List of processing parameters.
void setProvider(QgsProcessingProvider *provider)
Associates this algorithm with its provider.
QString parameterAsFile(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a file/folder name.
QgsProcessingFeatureSource * parameterAsSource(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a feature source.
virtual QString helpUrl() const
Returns a url pointing to the algorithm&#39;s help page.
static QgsExpressionContextScope * processingAlgorithmScope(const QgsProcessingAlgorithm *algorithm, const QVariantMap &parameters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing algorithm...
Wrapper for iterator of features from vector data provider or vector layer.
double parameterAsDouble(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to a static double value.
QVariantMap run(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool *ok=nullptr) const
Executes the algorithm using the specified parameters.
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
QList< QgsMapLayer * > parameterAsLayerList(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a list of map layers.
A rectangle specified with double values.
Definition: qgsrectangle.h:39
Base class for all map layer types.
Definition: qgsmaplayer.h:56
QgsCoordinateReferenceSystem parameterAsPointCrs(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context)
Returns the coordinate reference system associated with an point parameter value. ...
static QString parameterAsString(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static string value.
QgsRasterLayer * parameterAsRasterLayer(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a raster layer.
QString id() const
Returns the unique ID for the algorithm, which is a combination of the algorithm provider&#39;s ID and th...
virtual QIcon icon() const
Returns an icon for the algorithm.
static int parameterAsEnum(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a enum value.
virtual QString helpString() const
Returns a localised help string for the algorithm.
Base class for providing feedback from a processing algorithm.
static QVariantList parameterAsMatrix(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a matrix/table of values.
int countVisibleParameters() const
Returns the number of visible (non-hidden) parameters defined by this algorithm.
QVariantMap postProcess(QgsProcessingContext &context, QgsProcessingFeedback *feedback)
Should be called in the main thread following the completion of runPrepared().
QgsPointXY parameterAsPoint(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem()) const
Evaluates the parameter with matching name to a point.
QgsExpressionContext createExpressionContext(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeatureSource *source=nullptr) const
Creates an expression context relating to the algorithm.
QgsProcessingAlgorithm * create(const QVariantMap &configuration=QVariantMap()) const
Creates a copy of the algorithm, ready for execution.
bool hasHtmlOutputs() const
Returns true if this algorithm generates HTML outputs.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
static QList< int > parameterAsEnums(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to list of enum values.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:549
QVariantList parameterAsMatrix(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a matrix/table of values.
virtual QString name() const =0
Returns the algorithm name, used for identifying the algorithm.
QgsProcessingProvider * provider() const
Returns the provider to which this algorithm belongs.
QString name() const
Returns the name of the output.
A class to represent a 2D point.
Definition: qgspointxy.h:43
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source&#39;s coordinate reference system.
QList< int > parameterAsEnums(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to list of enum values.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
An interface for objects which accept features via addFeature(s) methods.
QgsProcessingAlgorithm * mAlgorithm
Pointer to algorithm which owns this parameter.
QgsRectangle parameterAsExtent(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem()) const
Evaluates the parameter with matching name to a rectangular extent.
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users...
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
static QgsRasterLayer * parameterAsRasterLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a raster layer.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
static QgsMapLayer * parameterAsLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a map layer.
QgsMapLayer * parameterAsLayer(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a map layer.
Abstract base class for processing providers.
Algorithm requires that all input layers have matching coordinate reference systems.
QThread * thread()
Returns the thread in which the context lives.
virtual bool supportsNonFileBasedOutput() const
Returns true if the provider supports non-file based outputs (such as memory layers or direct databas...
virtual QString asPythonCommand(const QVariantMap &parameters, QgsProcessingContext &context) const
Returns a Python command string which can be executed to run the algorithm using the specified parame...
virtual QString valueAsPythonString(const QVariant &value, QgsProcessingContext &context) const
Returns a string version of the parameter input value, which is suitable for use as an input paramete...
QStringList parameterAsFields(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a list of fields.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
QList< QgsExpressionContextScope * > takeScopes()
Return all scopes from this context and remove them, leaving this context without any context...
virtual QList< int > inputLayerTypes() const
Returns the valid input layer types for the source layer for this algorithm.
virtual QString shortHelpString() const
Returns a localised short helper string for the algorithm.
static QgsVectorLayer * parameterAsVectorLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a vector layer.
Base class for all parameter definitions which represent file or layer destinations, e.g.
Abstract base class for processing algorithms.
QgsCoordinateReferenceSystem parameterAsCrs(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a coordinate reference system.
static QgsPointXY parameterAsPoint(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching definition to a point.
static QString parameterAsFile(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a file/folder name.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning)
add a message to the instance (and create it if necessary)
A feature sink output for processing algorithms.
static QList< QgsMapLayer * > parameterAsLayerList(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of map layers.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
QString what() const
Definition: qgsexception.h:48
static QgsGeometry parameterAsExtentGeometry(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching definition to a rectangular extent, and returns a geometry cove...
static QgsCoordinateReferenceSystem parameterAsExtentCrs(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Returns the coordinate reference system associated with an extent parameter value.
QgsProcessingParameterDefinitions destinationParameterDefinitions() const
Returns a list of destination parameters definitions utilized by the algorithm.
static QgsRectangle parameterAsExtent(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching definition to a rectangular extent.
virtual QVariantMap preprocessParameters(const QVariantMap &parameters)
Pre-processes a set of parameters, allowing the algorithm to clean their values.
void removeParameter(const QString &name)
Removes the parameter with matching name from the algorithm, and deletes any existing definition...
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
static QgsCoordinateReferenceSystem parameterAsPointCrs(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Returns the coordinate reference system associated with an point parameter value. ...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QgsMapLayerStore * temporaryLayerStore()
Returns a reference to the layer store used for storing temporary layers during algorithm execution...
bool prepare(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback)
Prepares the algorithm for execution.
QgsCoordinateReferenceSystem parameterAsExtentCrs(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context)
Returns the coordinate reference system associated with an extent parameter value.
virtual QWidget * createCustomParametersWidget(QWidget *parent=nullptr) const
If an algorithm subclass implements a custom parameters widget, a copy of this widget should be const...
virtual QString id() const =0
Returns the unique provider id, used for identifying the provider.
Flags flags() const
Returns any flags associated with the parameter.
int scopeCount() const
Returns the number of scopes contained in the context.
bool parameterAsBool(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to a static boolean value.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void takeResultsFrom(QgsProcessingContext &context)
Takes the results from another context and merges them with the results currently stored in this cont...
virtual QgsWkbTypes::Type outputWkbType(QgsWkbTypes::Type inputWkbType) const
Maps the input WKB geometry type (inputWkbType) to the corresponding output WKB type generated by the...
virtual QString type() const =0
Unique output type name.
virtual QgsFeatureRequest request() const
Returns the feature request used for fetching features to process from the source layer...
static QList< double > parameterAsRange(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a range of values.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
virtual bool validateInputCrs(const QVariantMap &parameters, QgsProcessingContext &context) const
Checks whether the coordinate reference systems for the specified set of parameters are valid for the...
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
virtual QString type() const =0
Unique parameter type name.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
QgsVectorLayer * parameterAsVectorLayer(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a vector layer.
QString parameterAsString(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to a static string value.
Single scope for storing variables and functions for use within a QgsExpressionContext.
int parameterAsInt(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to a static integer value.
virtual bool checkParameterValues(const QVariantMap &parameters, QgsProcessingContext &context, QString *message=nullptr) const
Checks the supplied parameter values to verify that they satisfy the requirements of this algorithm i...
virtual QgsProcessingAlgorithm * createInstance() const =0
Creates a new instance of the algorithm class.
QString parameterAsExpression(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to an expression.
QgsExpressionContext & expressionContext()
Returns the expression context.
const QgsProcessingParameterDefinition * parameterDefinition(const QString &name) const
Returns a matching parameter by name.
QgsGeometry parameterAsExtentGeometry(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching name to a rectangular extent, and returns a geometry covering t...
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
QString name() const
Returns the name of the parameter.
QgsExpressionContextScope * createExpressionContextScope() const
Returns an expression context scope suitable for this source.
const QgsProcessingOutputDefinition * outputDefinition(const QString &name) const
Returns a matching output by name.
virtual bool isDestination() const
Returns true if this parameter represents a file or layer destination, e.g.
Base class for the definition of processing outputs.
virtual QVariantMap postProcessAlgorithm(QgsProcessingContext &context, QgsProcessingFeedback *feedback)
Allows the algorithm to perform any required cleanup tasks.
QVariantMap runPrepared(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback)
Runs the algorithm, which has been prepared by an earlier call to prepare().
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
bool addOutput(QgsProcessingOutputDefinition *outputDefinition)
Adds an output definition to the algorithm.
QgsFeatureSink * parameterAsSink(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QString &destinationIdentifier, const QgsFields &fields, QgsWkbTypes::Type geometryType=QgsWkbTypes::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem()) const
Evaluates the parameter with matching name to a feature sink.
virtual bool canExecute(QString *errorMessage=nullptr) const
Returns true if the algorithm can execute.
QString parameterAsOutputLayer(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a output layer destination.
QVariantMap processAlgorithm(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback) override
Runs the algorithm using the specified parameters.
An input feature source (such as vector layers) parameter for processing algorithms.
static QgsFeatureSink * parameterAsSink(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context, QString &destinationIdentifier)
Evaluates the parameter with matching definition to a feature sink.
This class represents a coordinate reference system (CRS).
Base class for the definition of processing parameters.
virtual QgsProcessingFeatureSource::Flag sourceFlags() const
Returns the processing feature source flags to be used in the algorithm.
virtual bool checkValueIsAcceptable(const QVariant &input, QgsProcessingContext *context=nullptr) const
Checks whether the specified input value is acceptable for the parameter.
static double parameterAsDouble(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static double value.
void initAlgorithm(const QVariantMap &configuration=QVariantMap()) override
Initializes the algorithm using the specified configuration.
SourceType
Data source types enum.
Definition: qgsprocessing.h:45
static QString parameterAsOutputLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a output layer destination.
static int parameterAsInt(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static integer value.
static QgsProcessingFeatureSource * parameterAsSource(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a feature source.
virtual void initParameters(const QVariantMap &configuration=QVariantMap())
Initializes any extra parameters added by the algorithm subclass.
static bool parameterAsBool(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static boolean value.
void setSupportsNonFileBasedOutput(bool supportsNonFileBasedOutput)
Sets whether the destination parameter supports non filed-based outputs, such as memory layers or dir...
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
bool nextFeature(QgsFeature &f)
QString parameterAsCompatibleSourceLayerPath(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat=QString("shp"), QgsProcessingFeedback *feedback=nullptr)
Evaluates the parameter with matching name to a source vector layer file path of compatible format...
static QString parameterAsCompatibleSourceLayerPath(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat=QString("shp"), QgsProcessingFeedback *feedback=nullptr)
Evaluates the parameter with matching definition to a source vector layer file path of compatible for...
Parameter is hidden and should not be shown to users.
bool addParameter(QgsProcessingParameterDefinition *parameterDefinition, bool createOutput=true)
Adds a parameter definition to the algorithm.
QList< double > parameterAsRange(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a range of values.
Represents a vector layer which manages a vector based data sets.
static QString parameterAsExpression(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to an expression.
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.
virtual QVariantMap processAlgorithm(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback)=0
Runs the algorithm using the specified parameters.
virtual QgsProcessingOutputDefinition * toOutputDefinition() const =0
Returns a new QgsProcessingOutputDefinition corresponding to the definition of the destination parame...
Any vector layer with geometry.
Definition: qgsprocessing.h:48
virtual QgsCoordinateReferenceSystem outputCrs(const QgsCoordinateReferenceSystem &inputCrs) const
Maps the input source coordinate reference system (inputCrs) to a corresponding output CRS generated ...
virtual QgsProcessing::SourceType outputLayerType() const
Returns the layer type for layers generated by this algorithm, if this is possible to determine in ad...
virtual QString svgIconPath() const
Returns a path to an SVG version of the algorithm&#39;s icon.
QString parameterAsFileOutput(const QVariantMap &parameters, const QString &name, QgsProcessingContext &context) const
Evaluates the parameter with matching name to a file based output destination.
int parameterAsEnum(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to a enum value.
static QString parameterAsFileOutput(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a file based output destination.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static QStringList parameterAsFields(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of fields.
virtual bool prepareAlgorithm(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback)
Prepares the algorithm to run using the specified parameters.