Sunday, 8 October 2017

qgis - Register custom qgsfunction in pyqgis



I'm using pyqgis within an standalone application. Now I wanted to create a custom expression to to use as filterExpression in rule of ruleBasedRendererV2. (I tried the renderer with existing functions before and everything worked fine!)


Custom qgisfunction (bitwise AND-function - as there is not such a function yet) looks like this:


from qgis.utils import qgsfunction

@qgsfunction(args="auto", group='Python')
def bitwise_and(value1, value2, feature, parent):
return value1 & value2

I also tried to register it, via:


from qgis.core import QgsExpression

QgsExpression.registerFunction(bitwise_and)

Testing the expression via:


expressionString = 'bitwise_and(2, 2) = 2'
exp = QgsExpression(expressionString)
if exp.hasParserError():
print(exp.parserErrorString())

(Giving 2=2 so always True) works after registering function, and fails if not. But still, I can not use the expression within a rule...


Right now, the file containing the function lies on top in my project folder, which is automatically included to PATH, isn't it?! (According to Nathan Woodrow, file can be placed anywhere in PATH - see https://nathanw.net/2012/11/10/user-defined-expression-functions-for-qgis/).



UPDATE: Registering of function works so far, with code from above - now the problem lies in function itself...


UPDATE #2:


Very strange! Simple function do_nothing getting two arguments works fine in my code:


@qgsfunction(args="auto", group='Python')
def do_nothing(value1, value2, feature, parent):
return value1

Using expression expString = 'do_nothing(2, 2) = 2'


UPDATE #3:


Simple change of do_nothing to add_one does not work any longer:



@qgsfunction(args="auto", group='Python')
def add_one(value1, value2, feature, parent):
return value1 + 1

calling it via expString = 'add_one(2, 2) = 3'. That's why I think it has something to do with returning type?!



Answer



I finally solved the problem!


It was really a type-problem, as input values are defined as QVariant inside @qgsfunction. So, to get my code work I had to convert them into integers first. Apparently, QGIS takes care of type conversions itself...


Function looks like this now:


@qgsfunction(args="auto", group='Python')

def bitwise_and(value1, value2, feature, parent):
return value1.toInt()[0] & value2.toInt()[0]

And if you have the function placed in your project folder, don't forget to register it first:


from qgis.core import QgsExpression
QgsExpression.registerFunction(bitwise_and)

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...