Skip to content

Commit

Permalink
Merge pull request #5729 from nyalldawson/proc_dyanmic
Browse files Browse the repository at this point in the history
[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.
2 changes: 1 addition & 1 deletion python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -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
Expand Down
66 changes: 66 additions & 0 deletions python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -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:


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






};

QFlags<QgsProcessingParameterDefinition::Flag> operator|(QgsProcessingParameterDefinition::Flag f1, QFlags<QgsProcessingParameterDefinition::Flag> f2);
Expand Down
14 changes: 14 additions & 0 deletions python/gui/qgspropertyoverridebutton.sip
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/AddTableField.py
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/DeleteColumn.py
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/DeleteHoles.py
Expand Up @@ -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
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/DensifyGeometries.py
Expand Up @@ -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)
Expand Down
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/ExtendLines.py
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/FieldsMapper.py
Expand Up @@ -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)
Expand Down
Expand Up @@ -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():
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/LinesToPolygons.py
Expand Up @@ -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():
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/OffsetLine.py
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/Orthogonalize.py
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/PointOnSurface.py
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/PolygonsToLines.py
Expand Up @@ -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
Expand Down
Expand Up @@ -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()
Expand Down
22 changes: 18 additions & 4 deletions python/plugins/processing/algs/qgis/SetMValue.py
Expand Up @@ -29,6 +29,8 @@

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


Expand All @@ -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'
Expand All @@ -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))

Expand Down
25 changes: 20 additions & 5 deletions python/plugins/processing/algs/qgis/SetZValue.py
Expand Up @@ -29,7 +29,10 @@

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


from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
Expand All @@ -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'
Expand All @@ -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))

Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/SingleSidedBuffer.py
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/TextToFloat.py
Expand Up @@ -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:
Expand Down

0 comments on commit 389435e

Please sign in to comment.