2012-10-04 19:33:47 +02:00
# -*- coding: utf-8 -*-
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
FieldPyculator . py
- - - - - - - - - - - - - - - - - - - - -
Date : August 2012
2013-10-01 20:52:22 +03:00
Copyright : ( C ) 2012 by Victor Olaya
2012-10-04 19:33:47 +02:00
Email : volayaf at gmail dot com
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
2016-09-21 18:24:26 +02:00
from builtins import str
2012-10-04 19:33:47 +02:00
2013-09-14 15:52:28 +02:00
__author__ = ' Victor Olaya & NextGIS '
2012-10-04 19:33:47 +02:00
__date__ = ' August 2012 '
2013-09-14 15:52:28 +02:00
__copyright__ = ' (C) 2012, Victor Olaya & NextGIS '
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
# This will get replaced with a git SHA1 when you do a git archive
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
__revision__ = ' $Format: % H$ '
2013-04-11 11:13:45 +04:00
import sys
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
2016-04-22 10:38:48 +02:00
from qgis . PyQt . QtCore import QVariant
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
from qgis . core import QgsFeature , QgsField
2013-08-12 20:44:27 +02:00
from processing . core . GeoAlgorithm import GeoAlgorithm
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
from processing . core . GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
2014-07-14 14:19:09 +02:00
from processing . core . parameters import ParameterVector
from processing . core . parameters import ParameterString
from processing . core . parameters import ParameterNumber
from processing . core . parameters import ParameterSelection
from processing . core . outputs import OutputVector
2013-10-01 20:52:22 +03:00
from processing . tools import dataobjects , vector
2012-09-15 18:25:25 +03:00
class FieldsPyculator ( GeoAlgorithm ) :
2013-10-01 20:52:22 +03:00
INPUT_LAYER = ' INPUT_LAYER '
FIELD_NAME = ' FIELD_NAME '
FIELD_TYPE = ' FIELD_TYPE '
FIELD_LENGTH = ' FIELD_LENGTH '
FIELD_PRECISION = ' FIELD_PRECISION '
GLOBAL = ' GLOBAL '
FORMULA = ' FORMULA '
OUTPUT_LAYER = ' OUTPUT_LAYER '
RESULT_VAR_NAME = ' value '
2013-04-11 11:13:45 +04:00
TYPES = [ QVariant . Int , QVariant . Double , QVariant . String ]
2012-09-15 18:25:25 +03:00
def defineCharacteristics ( self ) :
2015-07-26 03:48:27 +02:00
self . name , self . i18n_name = self . trAlgorithm ( ' Advanced Python field calculator ' )
self . group , self . i18n_group = self . trAlgorithm ( ' Vector table tools ' )
2015-08-31 16:59:11 +02:00
self . type_names = [ self . tr ( ' Integer ' ) ,
self . tr ( ' Float ' ) ,
self . tr ( ' String ' ) ]
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterVector ( self . INPUT_LAYER ,
2016-08-23 19:33:42 +03:00
self . tr ( ' Input layer ' ) ) )
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterString ( self . FIELD_NAME ,
2015-08-22 14:29:41 +02:00
self . tr ( ' Result field name ' ) , ' NewField ' ) )
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterSelection ( self . FIELD_TYPE ,
2015-08-31 16:59:11 +02:00
self . tr ( ' Field type ' ) , self . type_names ) )
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterNumber ( self . FIELD_LENGTH ,
2015-08-22 14:29:41 +02:00
self . tr ( ' Field length ' ) , 1 , 255 , 10 ) )
2013-10-01 20:52:22 +03:00
self . addParameter ( ParameterNumber ( self . FIELD_PRECISION ,
2015-08-22 14:29:41 +02:00
self . tr ( ' Field precision ' ) , 0 , 10 , 0 ) )
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterString ( self . GLOBAL ,
2015-08-22 14:29:41 +02:00
self . tr ( ' Global expression ' ) , multiline = True , optional = True ) )
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterString ( self . FORMULA ,
2015-08-22 14:29:41 +02:00
self . tr ( ' Formula ' ) , ' value = ' , multiline = True ) )
2015-05-22 16:39:20 +02:00
self . addOutput ( OutputVector ( self . OUTPUT_LAYER , self . tr ( ' Calculated ' ) ) )
2012-09-15 18:25:25 +03:00
2017-01-06 20:04:00 +10:00
def processAlgorithm ( self , feedback ) :
2013-04-11 11:13:45 +04:00
fieldName = self . getParameterValue ( self . FIELD_NAME )
fieldType = self . getParameterValue ( self . FIELD_TYPE )
fieldLength = self . getParameterValue ( self . FIELD_LENGTH )
fieldPrecision = self . getParameterValue ( self . FIELD_PRECISION )
2012-09-15 18:25:25 +03:00
code = self . getParameterValue ( self . FORMULA )
2013-01-12 23:36:00 +01:00
globalExpression = self . getParameterValue ( self . GLOBAL )
2012-09-15 18:25:25 +03:00
output = self . getOutputFromName ( self . OUTPUT_LAYER )
2013-04-11 11:13:45 +04:00
2013-10-01 20:52:22 +03:00
layer = dataobjects . getObjectFromUri (
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
self . getParameterValue ( self . INPUT_LAYER ) )
2016-08-04 07:33:49 +10:00
fields = layer . fields ( )
2013-10-01 20:52:22 +03:00
fields . append ( QgsField ( fieldName , self . TYPES [ fieldType ] , ' ' ,
2016-01-30 09:33:24 +11:00
fieldLength , fieldPrecision ) )
2016-08-04 07:33:49 +10:00
writer = output . getVectorWriter ( fields , layer . wkbType ( ) ,
2015-08-22 14:29:41 +02:00
layer . crs ( ) )
2012-12-10 00:12:07 +01:00
outFeat = QgsFeature ( )
2012-09-15 18:25:25 +03:00
new_ns = { }
2013-10-01 20:52:22 +03:00
# Run global code
if globalExpression . strip ( ) != ' ' :
2012-09-15 18:25:25 +03:00
try :
bytecode = compile ( globalExpression , ' <string> ' , ' exec ' )
2015-08-22 14:29:41 +02:00
exec ( bytecode , new_ns )
2012-09-15 18:25:25 +03:00
except :
2013-10-01 20:52:22 +03:00
raise GeoAlgorithmExecutionException (
2017-03-04 16:23:36 +01:00
self . tr ( " FieldPyculator code execute error.Global code block can ' t be executed! \n {0} \n {1} " ) . format ( str ( sys . exc_info ( ) [ 0 ] . __name__ ) , str ( sys . exc_info ( ) [ 1 ] ) ) )
2012-09-15 18:25:25 +03:00
2013-10-01 20:52:22 +03:00
# Replace all fields tags
2016-08-04 07:33:49 +10:00
fields = layer . fields ( )
2013-02-04 00:14:39 +01:00
num = 0
for field in fields :
2016-09-21 18:24:26 +02:00
field_name = str ( field . name ( ) )
replval = ' __attr[ ' + str ( num ) + ' ] '
2013-10-01 20:52:22 +03:00
code = code . replace ( ' < ' + field_name + ' > ' , replval )
2013-02-04 00:14:39 +01:00
num + = 1
2012-09-15 18:25:25 +03:00
2013-10-01 20:52:22 +03:00
# Replace all special vars
2013-04-11 11:13:45 +04:00
code = code . replace ( ' $id ' , ' __id ' )
code = code . replace ( ' $geom ' , ' __geom ' )
2013-10-01 20:52:22 +03:00
need_id = code . find ( ' __id ' ) != - 1
need_geom = code . find ( ' __geom ' ) != - 1
need_attrs = code . find ( ' __attr ' ) != - 1
2012-09-15 18:25:25 +03:00
2013-10-01 20:52:22 +03:00
# Compile
2012-09-15 18:25:25 +03:00
try :
bytecode = compile ( code , ' <string> ' , ' exec ' )
except :
2013-10-01 20:52:22 +03:00
raise GeoAlgorithmExecutionException (
2017-03-04 16:23:36 +01:00
self . tr ( " FieldPyculator code execute error. Field code block can ' t be executed! \n {0} \n {1} " ) . format ( str ( sys . exc_info ( ) [ 0 ] . __name__ ) , str ( sys . exc_info ( ) [ 1 ] ) ) )
2012-09-15 18:25:25 +03:00
2013-10-01 20:52:22 +03:00
# Run
2013-09-12 13:19:00 +02:00
features = vector . features ( layer )
2016-02-17 09:36:59 +02:00
total = 100.0 / len ( features )
for current , feat in enumerate ( features ) :
2017-01-06 20:04:00 +10:00
feedback . setProgress ( int ( current * total ) )
2013-04-11 11:13:45 +04:00
attrs = feat . attributes ( )
2012-12-24 00:03:30 +01:00
feat_id = feat . id ( )
2013-01-12 23:36:00 +01:00
2013-10-01 20:52:22 +03:00
# Add needed vars
2012-12-24 00:03:30 +01:00
if need_id :
new_ns [ ' __id ' ] = feat_id
2013-01-12 23:36:00 +01:00
2012-12-24 00:03:30 +01:00
if need_geom :
geom = feat . geometry ( )
new_ns [ ' __geom ' ] = geom
2013-01-12 23:36:00 +01:00
2012-09-15 18:25:25 +03:00
if need_attrs :
2013-06-03 21:25:22 +02:00
pyattrs = [ a for a in attrs ]
2013-02-04 00:14:39 +01:00
new_ns [ ' __attr ' ] = pyattrs
2013-01-12 23:36:00 +01:00
2013-10-01 20:52:22 +03:00
# Clear old result
if self . RESULT_VAR_NAME in new_ns :
2012-12-24 00:03:30 +01:00
del new_ns [ self . RESULT_VAR_NAME ]
2013-01-12 23:36:00 +01:00
2013-10-01 20:52:22 +03:00
# Exec
2015-08-22 14:29:41 +02:00
exec ( bytecode , new_ns )
2013-01-12 23:36:00 +01:00
2013-10-01 20:52:22 +03:00
# Check result
if self . RESULT_VAR_NAME not in new_ns :
raise GeoAlgorithmExecutionException (
2015-01-15 20:41:15 +02:00
self . tr ( " FieldPyculator code execute error \n "
2017-03-04 16:23:36 +01:00
" Field code block does not return ' {0} ' variable! "
" Please declare this variable in your code! " ) . format ( self . RESULT_VAR_NAME ) )
2013-01-12 23:36:00 +01:00
2013-10-01 20:52:22 +03:00
# Write feature
outFeat . setGeometry ( feat . geometry ( ) )
2013-06-03 21:25:22 +02:00
attrs . append ( new_ns [ self . RESULT_VAR_NAME ] )
2013-04-11 11:13:45 +04:00
outFeat . setAttributes ( attrs )
2012-12-24 00:03:30 +01:00
writer . addFeature ( outFeat )
2013-01-12 23:36:00 +01:00
2012-09-15 18:25:25 +03:00
del writer
def checkParameterValuesBeforeExecuting ( self ) :
2013-10-01 20:52:22 +03:00
# TODO check that formula is correct and fields exist
2012-09-15 18:25:25 +03:00
pass