mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	[processing] Fixes for field calculator and field mapper
- respect project distance, area and ellipsoid settings - ensure expression variables are correctly evaluated
This commit is contained in:
		
							parent
							
								
									b2235938e6
								
							
						
					
					
						commit
						d32c41a60e
					
				@ -26,7 +26,7 @@ __copyright__ = '(C) 2012, Victor Olaya'
 | 
			
		||||
__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 @@ class FieldsCalculator(GeoAlgorithm):
 | 
			
		||||
        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 @@ class FieldsCalculator(GeoAlgorithm):
 | 
			
		||||
        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 @@ __copyright__ = '(C) 2014, Arnaud Morvan'
 | 
			
		||||
__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,6 +69,19 @@ class FieldsMapper(GeoAlgorithm):
 | 
			
		||||
        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'],
 | 
			
		||||
@ -75,12 +89,16 @@ class FieldsMapper(GeoAlgorithm):
 | 
			
		||||
                                   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 @@ class FieldsMapper(GeoAlgorithm):
 | 
			
		||||
            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 @@ import re
 | 
			
		||||
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 @@ class FieldsCalculatorDialog(BASE, WIDGET):
 | 
			
		||||
        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):
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user