Skip to content
Permalink
Browse files

Fix loss of callback when invalid geometry handling method is set thr…

…ough

source definition
  • Loading branch information
nyalldawson committed Mar 24, 2020
1 parent afbe727 commit 488c8c739a452b3045ce4d4453ed331203f31ee3
@@ -290,6 +290,7 @@ called using the feature with invalid geometry as a parameter.
%End



void setTransformErrorCallback( SIP_PYCALLABLE / AllowNone / );
%Docstring
Sets a callback function to use when encountering a transform error when iterating
@@ -61,17 +61,20 @@ void QgsProcessingContext::addLayerToLoadOnCompletion( const QString &layer, con
void QgsProcessingContext::setInvalidGeometryCheck( QgsFeatureRequest::InvalidGeometryCheck check )
{
mInvalidGeometryCheck = check;
mInvalidGeometryCallback = defaultInvalidGeometryCallbackForCheck( check );
}

switch ( mInvalidGeometryCheck )
std::function<void ( const QgsFeature & )> QgsProcessingContext::defaultInvalidGeometryCallbackForCheck( QgsFeatureRequest::InvalidGeometryCheck check ) const
{
switch ( check )
{
case QgsFeatureRequest::GeometryAbortOnInvalid:
{
auto callback = []( const QgsFeature & feature )
{
throw QgsProcessingException( QObject::tr( "Feature (%1) has invalid geometry. Please fix the geometry or change the Processing setting to the \"Ignore invalid input features\" option." ).arg( feature.id() ) );
};
mInvalidGeometryCallback = callback;
break;
return callback;
}

case QgsFeatureRequest::GeometrySkipInvalid:
@@ -81,13 +84,13 @@ void QgsProcessingContext::setInvalidGeometryCheck( QgsFeatureRequest::InvalidGe
if ( mFeedback )
mFeedback->reportError( QObject::tr( "Feature (%1) has invalid geometry and has been skipped. Please fix the geometry or change the Processing setting to the \"Ignore invalid input features\" option." ).arg( feature.id() ) );
};
mInvalidGeometryCallback = callback;
break;
return callback;
}

default:
break;
case QgsFeatureRequest::GeometryNoCheck:
return nullptr;
}
return nullptr;
}

void QgsProcessingContext::takeResultsFrom( QgsProcessingContext &context )
@@ -337,6 +337,13 @@ class CORE_EXPORT QgsProcessingContext
*/
SIP_SKIP std::function< void( const QgsFeature & ) > invalidGeometryCallback() const { return mInvalidGeometryCallback; }

/**
* Returns the default callback function to use for a particular invalid geometry \a check
* \note not available in Python bindings
* \since QGIS 3.14
*/
SIP_SKIP std::function< void( const QgsFeature & ) > defaultInvalidGeometryCallbackForCheck( QgsFeatureRequest::InvalidGeometryCheck check ) const;

/**
* Sets a callback function to use when encountering a transform error when iterating
* features. This function will be
@@ -1061,6 +1061,8 @@ QgsProcessingFeatureSource::QgsProcessingFeatureSource( QgsFeatureSource *origin
: context.invalidGeometryCheck() )
, mInvalidGeometryCallback( context.invalidGeometryCallback() )
, mTransformErrorCallback( context.transformErrorCallback() )
, mInvalidGeometryCallbackSkip( context.defaultInvalidGeometryCallbackForCheck( QgsFeatureRequest::GeometrySkipInvalid ) )
, mInvalidGeometryCallbackAbort( context.defaultInvalidGeometryCallbackForCheck( QgsFeatureRequest::GeometryAbortOnInvalid ) )
, mFeatureLimit( featureLimit )
{}

@@ -1191,6 +1193,21 @@ QgsExpressionContextScope *QgsProcessingFeatureSource::createExpressionContextSc
void QgsProcessingFeatureSource::setInvalidGeometryCheck( QgsFeatureRequest::InvalidGeometryCheck method )
{
mInvalidGeometryCheck = method;
switch ( mInvalidGeometryCheck )
{
case QgsFeatureRequest::GeometryNoCheck:
mInvalidGeometryCallback = nullptr;
break;

case QgsFeatureRequest::GeometrySkipInvalid:
mInvalidGeometryCallback = mInvalidGeometryCallbackSkip;
break;

case QgsFeatureRequest::GeometryAbortOnInvalid:
mInvalidGeometryCallback = mInvalidGeometryCallbackAbort;
break;

}
}


@@ -506,6 +506,10 @@ class CORE_EXPORT QgsProcessingFeatureSource : public QgsFeatureSource
QgsFeatureRequest::InvalidGeometryCheck mInvalidGeometryCheck = QgsFeatureRequest::GeometryNoCheck;
std::function< void( const QgsFeature & ) > mInvalidGeometryCallback;
std::function< void( const QgsFeature & ) > mTransformErrorCallback;

std::function< void( const QgsFeature & ) > mInvalidGeometryCallbackSkip;
std::function< void( const QgsFeature & ) > mInvalidGeometryCallbackAbort;

long long mFeatureLimit = -1;

};
@@ -1418,6 +1418,19 @@ void TestQgsProcessing::features()
ids = getIds( source->getFeatures() );
QVERIFY( !encountered );

QgsProcessingContext context2;
// context wants to skip, source wants to abort
context2.setInvalidGeometryCheck( QgsFeatureRequest::GeometrySkipInvalid );
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( polyLayer->id(), false, -1, QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck, QgsFeatureRequest::GeometryAbortOnInvalid ) ) );
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
try
{
ids = getIds( source->getFeatures() );
QVERIFY( false );
}
catch ( QgsProcessingException & )
{}

// equality operator
QVERIFY( QgsProcessingFeatureSourceDefinition( layer->id(), true ) == QgsProcessingFeatureSourceDefinition( layer->id(), true ) );
QVERIFY( QgsProcessingFeatureSourceDefinition( layer->id(), true ) != QgsProcessingFeatureSourceDefinition( "b", true ) );

0 comments on commit 488c8c7

Please sign in to comment.
You can’t perform that action at this time.