Skip to content
Permalink
Browse files

Merge pull request #3470 from arnaud-morvan/refactor_fields_context_g…

…enerator

[Processing] Fix processing refactor fields algorithm using expression context generators
  • Loading branch information
volaya committed Nov 8, 2016
2 parents 7c4e66b + 78236c0 commit 72fddb8b5e4a566e34d1290a08974134aa018d6a
@@ -1,7 +1,7 @@
/** \ingroup core
* A base class for objects which belong to a map composition.
*/
class QgsComposerObject : QObject
class QgsComposerObject : QObject, QgsExpressionContextGenerator
{
%TypeHeaderCode
#include <qgscomposerobject.h>
@@ -4,7 +4,7 @@
* them in a list in ascending z-Order. This list can be changed to lower/raise items one position
* or to bring them to front/back.
* */
class QgsComposition : QGraphicsScene
class QgsComposition : QGraphicsScene, QgsExpressionContextGenerator
{
%TypeHeaderCode
#include <qgscomposition.h>
@@ -13,7 +13,7 @@
properties.

*/
class QgsProject : QObject
class QgsProject : QObject, QgsExpressionContextGenerator
{
%TypeHeaderCode
#include <qgsproject.h>
@@ -316,7 +316,7 @@ struct QgsVectorJoinInfo
*/


class QgsVectorLayer : QgsMapLayer
class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
{
%TypeHeaderCode
#include "qgsvectorlayer.h"
@@ -78,10 +78,7 @@ def processAlgorithm(self, progress):
da.setEllipsoid(QgsProject.instance().readEntry(
'Measure', '/Ellipsoid', GEO_NONE)[0])

exp_context = QgsExpressionContext()
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))
exp_context = layer.createExpressionContext()

for field_def in mapping:
fields.append(QgsField(name=field_def['name'],
@@ -93,27 +90,20 @@ def processAlgorithm(self, progress):
expression.setGeomCalculator(da)
expression.setDistanceUnits(QgsProject.instance().distanceUnits())
expression.setAreaUnits(QgsProject.instance().areaUnits())

expression.prepare(exp_context)
if expression.hasParserError():
raise GeoAlgorithmExecutionException(
self.tr(u'Parser error in expression "{}": {}')
.format(str(field_def['expression']),
str(expression.parserErrorString())))
expression.prepare(exp_context)
if expression.hasEvalError():
raise GeoAlgorithmExecutionException(
self.tr(u'Evaluation error in expression "{}": {}')
.format(str(field_def['expression']),
str(expression.evalErrorString())))
.format(unicode(expression.expression()),
unicode(expression.parserErrorString())))
expressions.append(expression)

writer = output.getVectorWriter(fields,
layer.wkbType(),
layer.crs())

# Create output vector layer with new attributes
error = ''
calculationSuccess = True
error_exp = None
inFeat = QgsFeature()
outFeat = QgsFeature()
features = vector.features(layer)
@@ -132,8 +122,7 @@ def processAlgorithm(self, progress):
exp_context.lastScope().setVariable("row_number", rownum)
value = expression.evaluate(exp_context)
if expression.hasEvalError():
calculationSuccess = False
error = expression.evalErrorString()
error_exp = expression
break

attrs.append(value)
@@ -145,7 +134,8 @@ def processAlgorithm(self, progress):

del writer

if not calculationSuccess:
if error_exp is not None:
raise GeoAlgorithmExecutionException(
self.tr('An error occurred while evaluating the calculation'
' string:\n') + error)
self.tr(u'Evaluation error in expression "{}": {}')
.format(unicode(error_exp.expression()),
unicode(error_exp.parserErrorString())))
@@ -35,7 +35,7 @@
from qgis.PyQt.QtWidgets import QComboBox, QHeaderView, QLineEdit, QSpacerItem, QMessageBox, QSpinBox, QStyledItemDelegate
from qgis.PyQt.QtCore import QItemSelectionModel, QAbstractTableModel, QModelIndex, QVariant, Qt, pyqtSlot

from qgis.core import QgsExpression, QgsExpressionContextUtils, QgsApplication, QgsFeature
from qgis.core import QgsExpression, QgsProject, QgsApplication
from qgis.gui import QgsFieldExpressionWidget

from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_MODELER
@@ -87,21 +87,30 @@ def testAllExpressions(self):
def testExpression(self, row):
self._errors[row] = None
field = self._mapping[row]
exp_context = self.contextGenerator().createExpressionContext()

expression = QgsExpression(field['expression'])
expression.prepare(exp_context)
if expression.hasParserError():
self._errors[row] = expression.parserErrorString()
return

# test evaluation on the first feature
if self._layer is None:
return
context = QgsExpressionContextUtils.createFeatureBasedContext(QgsFeature(), self._layer.fields())
for feature in self._layer.getFeatures():
context.setFeature(feature)
expression.evaluate(context)
exp_context.setFeature(feature)
exp_context.lastScope().setVariable("row_number", 1)
expression.evaluate(exp_context)
if expression.hasEvalError():
self._errors[row] = expression.evalErrorString()
return
break

def contextGenerator(self):
if self._layer:
return self._layer
return QgsProject.instance()

def layer(self):
return self._layer

@@ -254,6 +263,7 @@ def createEditor(self, parent, option, index):
elif fieldType == QgsExpression:
editor = QgsFieldExpressionWidget(parent)
editor.setLayer(index.model().layer())
editor.registerExpressionContextGenerator(index.model().contextGenerator())
editor.fieldChanged.connect(self.on_expression_fieldChange)

else:

0 comments on commit 72fddb8

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