Skip to content

Commit

Permalink
Move iterator exception handling to c++
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 23, 2017
1 parent a8b364e commit d667bf5
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 32 deletions.
22 changes: 17 additions & 5 deletions python/core/processing/qgsprocessingcontext.sip
Expand Up @@ -142,7 +142,6 @@ Destination project
.. seealso:: invalidGeometryCheck()
%End


void setInvalidGeometryCallback( SIP_PYCALLABLE / AllowNone / );
%Docstring
Sets a callback function to use when encountering an invalid geometry and
Expand Down Expand Up @@ -198,16 +197,29 @@ Destination project
%Docstring
Sets the default ``encoding`` to use for newly created files.
.. seealso:: defaultEncoding()
%End

QgsProcessingFeedback *feedback();
%Docstring
Returns the associated feedback object.
.. seealso:: setFeedback()
:rtype: QgsProcessingFeedback
%End

void setFeedback( QgsProcessingFeedback *feedback );
%Docstring
Sets an associated ``feedback`` object. This allows context related functions
to report feedback and errors to users and processing logs. While ideally this feedback
object should outlive the context, only a weak pointer to ``feedback`` is stored
and no errors will occur if feedback is deleted before the context.
Ownership of ``feedback`` is not transferred.
.. seealso:: setFeedback()
%End

private:
QgsProcessingContext( const QgsProcessingContext &other );
};





QFlags<QgsProcessingContext::Flag> operator|(QgsProcessingContext::Flag f1, QFlags<QgsProcessingContext::Flag> f2);


Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/gui/AlgorithmDialogBase.py
Expand Up @@ -189,7 +189,7 @@ def resetGUI(self):

def setInfo(self, msg, error=False, escape_html=True):
if error:
self.txtLog.append('<span style="color:red"><br>{}<br></span>'.format(msg, quote=False))
self.txtLog.append('<span style="color:red">{}</span><br />'.format(msg, quote=False))
elif escape_html:
self.txtLog.append(html.escape(msg))
else:
Expand Down
16 changes: 1 addition & 15 deletions python/plugins/processing/tools/dataobjects.py
Expand Up @@ -71,27 +71,13 @@ def createContext(feedback=None):
"""
context = QgsProcessingContext()
context.setProject(QgsProject.instance())
context.setFeedback(feedback)

invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
if invalid_features_method is None:
invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
context.setInvalidGeometryCheck(invalid_features_method)

def raise_invalid_geometry_error(f, feedback=feedback):
if feedback:
feedback.pushInfo(QCoreApplication.translate("FeatureIterator",
'Feature with id {} has invalid geometry, skipping feature.'.format(f.id())))

if context.invalidGeometryCheck() == QgsFeatureRequest.GeometrySkipInvalid:
context.setInvalidGeometryCallback(raise_invalid_geometry_error)

def raise_transform_error(f, feedback=feedback):
if feedback:
feedback.pushInfo(QCoreApplication.translate("FeatureIterator",
'Encountered a transform error when reprojecting feature with id {}.'.format(f.id())))

context.setTransformErrorCallback(raise_transform_error)

settings = QgsSettings()
context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))

Expand Down
62 changes: 51 additions & 11 deletions src/core/processing/qgsprocessingcontext.h
Expand Up @@ -25,6 +25,7 @@
#include "qgsfeaturerequest.h"
#include "qgsmaplayerlistutils.h"
#include "qgsexception.h"
#include "qgsprocessingfeedback.h"

/**
* \class QgsProcessingContext
Expand All @@ -50,7 +51,15 @@ class CORE_EXPORT QgsProcessingContext
/**
* Constructor for QgsProcessingContext.
*/
QgsProcessingContext() = default;
QgsProcessingContext()
{
auto callback = [ = ]( const QgsFeature & feature )
{
if ( mFeedback )
mFeedback->reportError( QObject::tr( "Encountered a transform error when reprojecting feature with id %1." ).arg( feature.id() ) );
};
mTransformErrorCallback = callback;
}

//! QgsProcessingContext cannot be copied
QgsProcessingContext( const QgsProcessingContext &other ) = delete;
Expand Down Expand Up @@ -176,17 +185,34 @@ class CORE_EXPORT QgsProcessingContext
{
mInvalidGeometryCheck = check;

if ( mInvalidGeometryCheck == QgsFeatureRequest::GeometryAbortOnInvalid )
switch ( mInvalidGeometryCheck )
{
auto callback = []( const QgsFeature & feature )
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;
}

case QgsFeatureRequest::GeometrySkipInvalid:
{
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;
auto callback = [ = ]( const QgsFeature & feature )
{
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;
}

default:
break;
}
}


/**
* Sets a callback function to use when encountering an invalid geometry and
* invalidGeometryCheck() is set to GeometryAbortOnInvalid. This function will be
Expand Down Expand Up @@ -268,6 +294,22 @@ class CORE_EXPORT QgsProcessingContext
*/
void setDefaultEncoding( const QString &encoding ) { mDefaultEncoding = encoding; }

/**
* Returns the associated feedback object.
* \see setFeedback()
*/
QgsProcessingFeedback *feedback() { return mFeedback; }

/**
* Sets an associated \a feedback object. This allows context related functions
* to report feedback and errors to users and processing logs. While ideally this feedback
* object should outlive the context, only a weak pointer to \a feedback is stored
* and no errors will occur if feedback is deleted before the context.
* Ownership of \a feedback is not transferred.
* \see setFeedback()
*/
void setFeedback( QgsProcessingFeedback *feedback ) { mFeedback = feedback; }

private:

QgsProcessingContext::Flags mFlags = 0;
Expand All @@ -282,15 +324,13 @@ class CORE_EXPORT QgsProcessingContext
QString mDefaultEncoding;
QMap< QString, LayerDetails > mLayersToLoadOnCompletion;

QPointer< QgsProcessingFeedback > mFeedback;

#ifdef SIP_RUN
QgsProcessingContext( const QgsProcessingContext &other );
#endif
};





Q_DECLARE_OPERATORS_FOR_FLAGS( QgsProcessingContext::Flags )

#endif // QGSPROCESSINGPARAMETERS_H
Expand Down

0 comments on commit d667bf5

Please sign in to comment.