Skip to content

Commit 3ea7860

Browse files
committed
[processing] Fixes for field calculator and field mapper
- respect project distance, area and ellipsoid settings - ensure expression variables are correctly evaluated (cherry-picked from d32c41a)
1 parent 2b72350 commit 3ea7860

3 files changed

Lines changed: 44 additions & 8 deletions

File tree

python/plugins/processing/algs/qgis/FieldsCalculator.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
__revision__ = '$Format:%H$'
2727

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

115-
if not exp.prepare(layer.pendingFields()):
117+
exp_context = QgsExpressionContext()
118+
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
119+
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
120+
exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))
121+
122+
if not exp.prepare(exp_context):
116123
raise GeoAlgorithmExecutionException(
117124
self.tr('Evaluation error: %s' % exp.evalErrorString()))
118125

@@ -129,8 +136,9 @@ def processAlgorithm(self, progress):
129136
rownum = 1
130137
for current, f in enumerate(features):
131138
rownum = current + 1
132-
exp.setCurrentRowNumber(rownum)
133-
value = exp.evaluate(f)
139+
exp_context.setFeature(f)
140+
exp_context.lastScope().setVariable("row_number", rownum)
141+
value = exp.evaluate(exp_context)
134142
if exp.hasEvalError():
135143
calculationSuccess = False
136144
error = exp.evalErrorString()

python/plugins/processing/algs/qgis/FieldsMapper.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
__revision__ = '$Format:%H$'
2727

2828

29-
from qgis.core import QgsField, QgsExpression, QgsFeature
29+
from qgis.core import QgsField, QgsExpression, QgsExpressionContext, QgsExpressionContextUtils, QgsDistanceArea, QgsProject, QgsFeature, GEO_NONE
30+
from qgis.utils import iface
3031
from processing.core.GeoAlgorithm import GeoAlgorithm
3132
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
3233
from processing.core.parameters import ParameterVector
@@ -68,19 +69,36 @@ def processAlgorithm(self, progress):
6869
provider = layer.dataProvider()
6970
fields = []
7071
expressions = []
72+
73+
da = QgsDistanceArea()
74+
da.setSourceCrs(layer.crs().srsid())
75+
da.setEllipsoidalMode(
76+
iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
77+
da.setEllipsoid(QgsProject.instance().readEntry(
78+
'Measure', '/Ellipsoid', GEO_NONE)[0])
79+
80+
exp_context = QgsExpressionContext()
81+
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
82+
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
83+
exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))
84+
7185
for field_def in mapping:
7286
fields.append(QgsField(name=field_def['name'],
7387
type=field_def['type'],
7488
len=field_def['length'],
7589
prec=field_def['precision']))
7690

7791
expression = QgsExpression(field_def['expression'])
92+
expression.setGeomCalculator(da)
93+
expression.setDistanceUnits(QgsProject.instance().distanceUnits())
94+
expression.setAreaUnits(QgsProject.instance().areaUnits())
95+
7896
if expression.hasParserError():
7997
raise GeoAlgorithmExecutionException(
8098
self.tr(u'Parser error in expression "{}": {}')
8199
.format(unicode(field_def['expression']),
82100
unicode(expression.parserErrorString())))
83-
expression.prepare(provider.fields())
101+
expression.prepare(exp_context)
84102
if expression.hasEvalError():
85103
raise GeoAlgorithmExecutionException(
86104
self.tr(u'Evaluation error in expression "{}": {}')
@@ -108,8 +126,9 @@ def processAlgorithm(self, progress):
108126
for i in xrange(0, len(mapping)):
109127
field_def = mapping[i]
110128
expression = expressions[i]
111-
expression.setCurrentRowNumber(rownum)
112-
value = expression.evaluate(inFeat)
129+
exp_context.setFeature(inFeat)
130+
exp_context.lastScope().setVariable("row_number", rownum)
131+
value = expression.evaluate(exp_context)
113132
if expression.hasEvalError():
114133
calculationSuccess = False
115134
error = expression.evalErrorString()

python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from PyQt4 import uic
3232
from PyQt4.QtCore import Qt, QSettings
3333
from PyQt4.QtGui import QDialog, QFileDialog, QApplication, QCursor, QMessageBox
34+
from qgis.core import QgsExpressionContext, QgsExpressionContextUtils
3435
from qgis.gui import QgsEncodingFileDialog
3536

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

99+
exp_context = QgsExpressionContext()
100+
exp_context.appendScope(QgsExpressionContextUtils.globalScope())
101+
exp_context.appendScope(QgsExpressionContextUtils.projectScope())
102+
exp_context.appendScope(QgsExpressionContextUtils.layerScope(self.layer))
103+
exp_context.lastScope().setVariable("row_number", 1)
104+
exp_context.setHighlightedVariables(["row_number"])
105+
self.builder.setExpressionContext(exp_context)
106+
98107
self.populateFields()
99108

100109
def setupSpinboxes(self, index):

0 commit comments

Comments
 (0)