Skip to content
Permalink
Browse files

[processing] Fixes for field calculator and field mapper

- respect project distance, area and ellipsoid settings
- ensure expression variables are correctly evaluated
  • Loading branch information
nyalldawson committed Feb 28, 2016
1 parent b223593 commit d32c41a60ed28abe3d8a93971810ee4f9735e055
@@ -26,7 +26,7 @@
__revision__ = '$Format:%H$'

from PyQt4.QtCore import QVariant
from qgis.core import QgsExpression, QgsFeature, QgsField, QgsDistanceArea, QgsProject, GEO_NONE
from qgis.core import QgsExpression, QgsExpressionContext, QgsExpressionContextUtils, QgsFeature, QgsField, QgsDistanceArea, QgsProject, GEO_NONE
from qgis.utils import iface
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
@@ -111,8 +111,15 @@ def processAlgorithm(self, progress):
da.setEllipsoid(QgsProject.instance().readEntry(
'Measure', '/Ellipsoid', GEO_NONE)[0])
exp.setGeomCalculator(da)
exp.setDistanceUnits(QgsProject.instance().distanceUnits())
exp.setAreaUnits(QgsProject.instance().areaUnits())

if not exp.prepare(layer.pendingFields()):
exp_context = QgsExpressionContext()
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

if not exp.prepare(exp_context):
raise GeoAlgorithmExecutionException(
self.tr('Evaluation error: %s' % exp.evalErrorString()))

@@ -129,8 +136,9 @@ def processAlgorithm(self, progress):
rownum = 1
for current, f in enumerate(features):
rownum = current + 1
exp.setCurrentRowNumber(rownum)
value = exp.evaluate(f)
exp_context.setFeature(f)
exp_context.lastScope().setVariable("row_number", rownum)
value = exp.evaluate(exp_context)
if exp.hasEvalError():
calculationSuccess = False
error = exp.evalErrorString()
@@ -26,7 +26,8 @@
__revision__ = '$Format:%H$'


from qgis.core import QgsField, QgsExpression, QgsFeature
from qgis.core import QgsField, QgsExpression, QgsExpressionContext, QgsExpressionContextUtils, QgsDistanceArea, QgsProject, QgsFeature, GEO_NONE
from qgis.utils import iface
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
@@ -68,19 +69,36 @@ def processAlgorithm(self, progress):
provider = layer.dataProvider()
fields = []
expressions = []

da = QgsDistanceArea()
da.setSourceCrs(layer.crs().srsid())
da.setEllipsoidalMode(
iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
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))

for field_def in mapping:
fields.append(QgsField(name=field_def['name'],
type=field_def['type'],
len=field_def['length'],
prec=field_def['precision']))

expression = QgsExpression(field_def['expression'])
expression.setGeomCalculator(da)
expression.setDistanceUnits(QgsProject.instance().distanceUnits())
expression.setAreaUnits(QgsProject.instance().areaUnits())

if expression.hasParserError():
raise GeoAlgorithmExecutionException(
self.tr(u'Parser error in expression "{}": {}')
.format(unicode(field_def['expression']),
unicode(expression.parserErrorString())))
expression.prepare(provider.fields())
expression.prepare(exp_context)
if expression.hasEvalError():
raise GeoAlgorithmExecutionException(
self.tr(u'Evaluation error in expression "{}": {}')
@@ -108,8 +126,9 @@ def processAlgorithm(self, progress):
for i in xrange(0, len(mapping)):
field_def = mapping[i]
expression = expressions[i]
expression.setCurrentRowNumber(rownum)
value = expression.evaluate(inFeat)
exp_context.setFeature(inFeat)
exp_context.lastScope().setVariable("row_number", rownum)
value = expression.evaluate(exp_context)
if expression.hasEvalError():
calculationSuccess = False
error = expression.evalErrorString()
@@ -31,6 +31,7 @@
from PyQt4 import uic
from PyQt4.QtCore import Qt, QSettings
from PyQt4.QtGui import QDialog, QFileDialog, QApplication, QCursor, QMessageBox
from qgis.core import QgsExpressionContext, QgsExpressionContextUtils
from qgis.gui import QgsEncodingFileDialog

from processing.core.ProcessingConfig import ProcessingConfig
@@ -95,6 +96,14 @@ def updateLayer(self):
self.builder.setLayer(self.layer)
self.builder.loadFieldNames()

exp_context = QgsExpressionContext()
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
exp_context.appendScope(QgsExpressionContextUtils.layerScope(self.layer))
exp_context.lastScope().setVariable("row_number", 1)
exp_context.setHighlightedVariables(["row_number"])
self.builder.setExpressionContext(exp_context)

self.populateFields()

def setupSpinboxes(self, index):

2 comments on commit d32c41a

@nyalldawson

This comment has been minimized.

Copy link
Contributor Author

@nyalldawson nyalldawson replied Feb 28, 2016

@alexbruy what's the correct way to backport processing fixes to 2.14? just push it to the 2.14 branch?

@alexbruy

This comment has been minimized.

Copy link
Contributor

@alexbruy alexbruy replied Feb 28, 2016

Yes, just puch them to the 2.14 branch and they will be included in the next point release

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