Skip to content
Permalink
Browse files
Merge pull request #5729 from nyalldawson/proc_dyanmic
[processing] Expose dynamic ("data defined") numeric parameters to gui
  • Loading branch information
nyalldawson committed Dec 2, 2017
2 parents 65a0c06 + 9378f39 commit 389435e
Show file tree
Hide file tree
Showing 75 changed files with 391 additions and 99 deletions.
@@ -872,7 +872,7 @@ class QgsProcessingFeatureBasedAlgorithm : QgsProcessingAlgorithm
:rtype: QgsCoordinateReferenceSystem
%End

virtual QgsFeature processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback ) = 0;
virtual QgsFeature processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0;
%Docstring
Processes an individual input ``feature`` from the source. Algorithms should implement their
logic in this method for performing the algorithm's operation (e.g. replacing the feature's
@@ -376,6 +376,69 @@ class QgsProcessingParameterDefinition
:rtype: str
%End

bool isDynamic() const;
%Docstring
Returns true if the parameter supports is dynamic, and can support data-defined values
(i.e. QgsProperty based values).
.. seealso:: setIsDynamic()
.. seealso:: dynamicPropertyDefinition()
.. seealso:: dynamicLayerParameterName()
:rtype: bool
%End

void setIsDynamic( bool dynamic );
%Docstring
Sets whether the parameter is ``dynamic``, and can support data-defined values
(i.e. QgsProperty based values).
.. seealso:: isDynamic()
.. seealso:: setDynamicPropertyDefinition()
.. seealso:: setDynamicLayerParameterName()
%End

QgsPropertyDefinition dynamicPropertyDefinition() const;
%Docstring
Returns the property definition for dynamic properties.
.. seealso:: isDynamic()
.. seealso:: setDynamicPropertyDefinition()
.. seealso:: dynamicLayerParameterName()
:rtype: QgsPropertyDefinition
%End

void setDynamicPropertyDefinition( const QgsPropertyDefinition &definition );
%Docstring
Sets the property ``definition`` for dynamic properties.
.. seealso:: isDynamic()
.. seealso:: dynamicPropertyDefinition()
.. seealso:: setDynamicLayerParameterName()
%End

QString dynamicLayerParameterName() const;
%Docstring
Returns the name of the parameter for a layer linked to a dynamic parameter, or an empty string if this is not set.

Dynamic parameters (see isDynamic()) can have an optional vector layer parameter linked to them,
which indicates which layer the fields and values will be available from when evaluating
the dynamic parameter.

.. seealso:: setDynamicLayerParameterName()
.. seealso:: isDynamic()
.. seealso:: dynamicPropertyDefinition()
:rtype: str
%End

void setDynamicLayerParameterName( const QString &name );
%Docstring
Sets the ``name`` for the parameter for a layer linked to a dynamic parameter, or an empty string if this is not set.

Dynamic parameters (see isDynamic()) can have an optional vector layer parameter linked to them,
which indicates which layer the fields and values will be available from when evaluating
the dynamic parameter.

.. seealso:: dynamicLayerParameterName()
.. seealso:: isDynamic()
.. seealso:: setDynamicPropertyDefinition()
%End

protected:


@@ -385,6 +448,9 @@ class QgsProcessingParameterDefinition






};

QFlags<QgsProcessingParameterDefinition::Flag> operator|(QgsProcessingParameterDefinition::Flag f1, QFlags<QgsProcessingParameterDefinition::Flag> f2);
@@ -53,6 +53,20 @@ class QgsPropertyOverrideButton: QToolButton
\param auxiliaryStorageEnabled If true, activate the button to store data defined in auxiliary storage
%End

void init( int propertyKey,
const QgsProperty &property,
const QgsPropertyDefinition &definition,
const QgsVectorLayer *layer = 0,
bool auxiliaryStorageEnabled = false );
%Docstring
Initialize a newly constructed property button (useful if button was included in a UI layout).
\param propertyKey key for corresponding property
\param property initial value of associated property to show in widget
\param definition properties definition for button
\param layer associated vector layer
\param auxiliaryStorageEnabled If true, activate the button to store data defined in auxiliary storage
%End

void init( int propertyKey,
const QgsAbstractPropertyCollection &collection,
const QgsPropertiesDefinition &definitions,
@@ -90,7 +90,7 @@ def outputFields(self, inputFields):
inputFields.append(self.field)
return inputFields

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
attributes = feature.attributes()
attributes.append(None)
feature.setAttributes(attributes)
@@ -80,7 +80,7 @@ def outputFields(self, input_fields):
input_fields.remove(index)
return input_fields

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
attributes = feature.attributes()
for index in self.field_indices:
del attributes[index]
@@ -66,7 +66,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.min_area = -1.0
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
if feature.hasGeometry():
feature.setGeometry(feature.geometry().removeInteriorRings(self.min_area))
return feature
@@ -68,7 +68,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.vertices = self.parameterAsInt(parameters, self.VERTICES, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
if feature.hasGeometry():
new_geometry = feature.geometry().densifyByCount(self.vertices)
feature.setGeometry(new_geometry)
@@ -64,7 +64,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
if feature.hasGeometry():
new_geometry = feature.geometry().densifyByDistance(float(interval))
feature.setGeometry(new_geometry)
@@ -67,7 +67,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.end_distance = self.parameterAsDouble(parameters, self.END_DISTANCE, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry.extendLine(self.start_distance, self.end_distance)
@@ -151,7 +151,7 @@ def processAlgorithm(self, parameters, context, feeback):
self._row_number = 0
return super().processAlgorithm(parameters, context, feeback)

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
attributes = []
for expression in self.expressions:
self.expr_context.setFeature(feature)
@@ -101,7 +101,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
def outputWkbType(self, input_wkb_type):
return self.wkb_type

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
self.expression_context.setFeature(feature)
value = self.expression.evaluate(self.expression_context)
if self.expression.hasEvalError():
@@ -80,7 +80,7 @@ def inputLayerTypes(self):
def outputWkbType(self, input_wkb_type):
return self.convertWkbToPolygons(input_wkb_type)

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
if feature.hasGeometry():
feature.setGeometry(QgsGeometry(self.convertToPolygons(feature.geometry())))
if feature.geometry().isEmpty():
@@ -100,7 +100,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.miter_limit = self.parameterAsDouble(parameters, self.MITER_LIMIT, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry.offsetCurve(self.distance, self.segments, self.join_style, self.miter_limit)
@@ -79,7 +79,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.angle_tolerance = self.parameterAsDouble(parameters, self.ANGLE_TOLERANCE, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry.orthogonalize(1.0e-8, self.max_iterations, self.angle_tolerance)
@@ -64,7 +64,7 @@ def outputType(self):
def outputWkbType(self, input_wkb_type):
return QgsWkbTypes.Point

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry.pointOnSurface()
@@ -73,7 +73,7 @@ def inputLayerTypes(self):
def outputWkbType(self, input_wkb_type):
return self.convertWkbToLines(input_wkb_type)

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
if feature.hasGeometry():
feature.setGeometry(QgsGeometry(self.convertToLines(feature.geometry())))
return feature
@@ -54,7 +54,7 @@ def outputType(self):
def inputLayerTypes(self):
return [QgsProcessing.TypeVectorLine]

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
if feature.geometry():
inGeom = feature.geometry()
reversedLine = inGeom.constGet().reversed()
@@ -29,6 +29,8 @@

from qgis.core import (QgsGeometry,
QgsWkbTypes,
QgsPropertyDefinition,
QgsProcessingParameters,
QgsProcessingParameterNumber)


@@ -47,6 +49,8 @@ def group(self):
def __init__(self):
super().__init__()
self.m_value = 0
self.dynamic_m = False
self.m_property = None

def name(self):
return 'setmvalue'
@@ -61,25 +65,35 @@ def tags(self):
return self.tr('set,add,m,measure,values').split(',')

def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterNumber(self.M_VALUE,
self.tr('M Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0))
m_param = QgsProcessingParameterNumber(self.M_VALUE,
self.tr('M Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0)
m_param.setIsDynamic(True)
m_param.setDynamicLayerParameterName('INPUT')
m_param.setDynamicPropertyDefinition(QgsPropertyDefinition(self.M_VALUE, self.tr("M Value"), QgsPropertyDefinition.Double))
self.addParameter(m_param)

def outputWkbType(self, inputWkb):
return QgsWkbTypes.addM(inputWkb)

def prepareAlgorithm(self, parameters, context, feedback):
self.m_value = self.parameterAsDouble(parameters, self.M_VALUE, context)
self.dynamic_m = QgsProcessingParameters.isDynamic(parameters, self.M_VALUE)
if self.dynamic_m:
self.m_property = parameters[self.M_VALUE]
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
new_geom = input_geometry.constGet().clone()
if QgsWkbTypes.hasM(new_geom.wkbType()):
# addMValue won't alter existing M values, so drop them first
new_geom.dropMValue()

new_geom.addMValue(self.m_value)
m = self.m_value
if self.dynamic_m:
m, ok = self.m_property.valueAsDouble(context.expressionContext(), m)
new_geom.addMValue(m)

feature.setGeometry(QgsGeometry(new_geom))

@@ -29,7 +29,10 @@

from qgis.core import (QgsGeometry,
QgsWkbTypes,
QgsProcessingParameterNumber)
QgsPropertyDefinition,
QgsProcessingParameters,
QgsProcessingParameterNumber,
QgsProcessingFeatureSource)


from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
@@ -47,6 +50,8 @@ def group(self):
def __init__(self):
super().__init__()
self.z_value = 0
self.dynamic_z = False
self.z_property = None

def name(self):
return 'setzvalue'
@@ -61,25 +66,35 @@ def tags(self):
return self.tr('set,add,z,25d,3d,values').split(',')

def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterNumber(self.Z_VALUE,
self.tr('Z Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0))
z_param = QgsProcessingParameterNumber(self.Z_VALUE,
self.tr('Z Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0)
z_param.setIsDynamic(True)
z_param.setDynamicLayerParameterName('INPUT')
z_param.setDynamicPropertyDefinition(QgsPropertyDefinition(self.Z_VALUE, self.tr("Z Value"), QgsPropertyDefinition.Double))
self.addParameter(z_param)

def outputWkbType(self, inputWkb):
return QgsWkbTypes.addZ(inputWkb)

def prepareAlgorithm(self, parameters, context, feedback):
self.z_value = self.parameterAsDouble(parameters, self.Z_VALUE, context)
self.dynamic_z = QgsProcessingParameters.isDynamic(parameters, self.Z_VALUE)
if self.dynamic_z:
self.z_property = parameters[self.Z_VALUE]
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
new_geom = input_geometry.constGet().clone()
if QgsWkbTypes.hasZ(new_geom.wkbType()):
# addZValue won't alter existing Z values, so drop them first
new_geom.dropZValue()

new_geom.addZValue(self.z_value)
z = self.z_value
if self.dynamic_z:
z, ok = self.z_property.valueAsDouble(context.expressionContext(), z)
new_geom.addZValue(z)

feature.setGeometry(QgsGeometry(new_geom))

@@ -108,7 +108,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.miter_limit = self.parameterAsDouble(parameters, self.MITER_LIMIT, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry.singleSidedBuffer(self.distance, self.segments,
@@ -73,7 +73,7 @@ def prepareAlgorithm(self, parameters, context, feedback):
self.field_name = self.parameterAsString(parameters, self.FIELD, context)
return True

def processFeature(self, feature, feedback):
def processFeature(self, feature, context, feedback):
value = feature[self.field_idx]
try:
if '%' in value:

0 comments on commit 389435e

Please sign in to comment.