void QgsGeometryValidationService::onFeatureAdded( QgsVectorLayer *layer, QgsFeatureId fid ) { if ( !mLayerChecks[layer].topologyChecks.empty() ) { invalidateTopologyChecks( layer ); } processFeature( layer, fid ); }
QVariantMap QgsProcessingFeatureBasedAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { prepareSource( parameters, context ); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outputFields( mSource->fields() ), outputWkbType( mSource->wkbType() ), outputCrs( mSource->sourceCrs() ), sinkFlags() ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); // prepare expression context for feature iteration QgsExpressionContext prevContext = context.expressionContext(); QgsExpressionContext algContext = prevContext; algContext.appendScopes( createExpressionContext( parameters, context, mSource.get() ).takeScopes() ); context.setExpressionContext( algContext ); long count = mSource->featureCount(); QgsFeature f; QgsFeatureIterator it = mSource->getFeatures( request(), sourceFlags() ); double step = count > 0 ? 100.0 / count : 1; int current = 0; while ( it.nextFeature( f ) ) { if ( feedback->isCanceled() ) { break; } context.expressionContext().setFeature( f ); const QgsFeatureList transformed = processFeature( f, context, feedback ); for ( QgsFeature transformedFeature : transformed ) sink->addFeature( transformedFeature, QgsFeatureSink::FastInsert ); feedback->setProgress( current * step ); current++; } mSource.reset(); // probably not necessary - context's aren't usually recycled, but can't hurt context.setExpressionContext( prevContext ); QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); return outputs; }