We use our own validation in QGIS, which can be called from different areas of the plugin. In addition, reports can be generated from the results.
Now we have switched to our own attribute forms in QGIS and wanted to integrate our validation there as well. That works fine, but sometimes the QGIS validation gets in the way. Therefore, we wanted to integrate the QGIS validation into our process.
We've written a wrapper that converts the QgsExpressions and constraints of a field into our rules and calls them to process the result.
Here is a small example of how we want to use the QgsExpression:
def validateImpl(self) -> bool: utils = QgsExpressionContextUtils() scope = utils.formScope(self.feature) context = QgsExpressionContext() context.appendScope(scope) # scope.setFeature(self.feature) self.expression = QgsExpression(self.expressionStr) value = self.expression.evaluate(context) return bool(value)
Unfortunately, it does not work self.expression.evaluate always returns 0 as a result, even though the validation would definitely fail.
I think that's because when we change a TextField in the attribute form and call validation on the signal textChanged (), then the actual attribute value in the feature has not been set, in other words, a change of the attribute does not seem to be noticed by QgsExpression.
If I set the attribute in the feature for every textChanged (), then the validation works:
self.feature.setAttribute (attribute, value)
So if the rule says that the attribute 'name' must contain the value 'QGIS', and setAttribute was called with (name = 'QGIS'), the rule would evaluate positively.
If you now close the attribute dialog with 'Ok' and save the layer, the value will not be saved. For example, if the value 'Test' was entered as 'name' and has now been changed to 'QGIS', then after saving and reopening the attribute dialog, 'Test' will still be displayed.
If I remove the code (setAttribute), the validation will not work anymore, but the value will be saved back to the feature.
At the moment I do not understand what the problem is, how can I use a QgsExpression which checks the currently entered value in the attribute form?
I've seen that there's a function "current_value" in the scope I get from utils.formScope (self.feature), but I have no idea how to use it.