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 389435e1a0ba4668a94a3ad2f413bc9a1060e873
Showing with 391 additions and 99 deletions.
  1. +1 −1 python/core/processing/qgsprocessingalgorithm.sip
  2. +66 −0 python/core/processing/qgsprocessingparameters.sip
  3. +14 −0 python/gui/qgspropertyoverridebutton.sip
  4. +1 −1 python/plugins/processing/algs/qgis/AddTableField.py
  5. +1 −1 python/plugins/processing/algs/qgis/DeleteColumn.py
  6. +1 −1 python/plugins/processing/algs/qgis/DeleteHoles.py
  7. +1 −1 python/plugins/processing/algs/qgis/DensifyGeometries.py
  8. +1 −1 python/plugins/processing/algs/qgis/DensifyGeometriesInterval.py
  9. +1 −1 python/plugins/processing/algs/qgis/ExtendLines.py
  10. +1 −1 python/plugins/processing/algs/qgis/FieldsMapper.py
  11. +1 −1 python/plugins/processing/algs/qgis/GeometryByExpression.py
  12. +1 −1 python/plugins/processing/algs/qgis/LinesToPolygons.py
  13. +1 −1 python/plugins/processing/algs/qgis/OffsetLine.py
  14. +1 −1 python/plugins/processing/algs/qgis/Orthogonalize.py
  15. +1 −1 python/plugins/processing/algs/qgis/PointOnSurface.py
  16. +1 −1 python/plugins/processing/algs/qgis/PolygonsToLines.py
  17. +1 −1 python/plugins/processing/algs/qgis/ReverseLineDirection.py
  18. +18 −4 python/plugins/processing/algs/qgis/SetMValue.py
  19. +20 −5 python/plugins/processing/algs/qgis/SetZValue.py
  20. +1 −1 python/plugins/processing/algs/qgis/SingleSidedBuffer.py
  21. +1 −1 python/plugins/processing/algs/qgis/TextToFloat.py
  22. +27 −2 python/plugins/processing/gui/NumberInputPanel.py
  23. +11 −0 python/plugins/processing/gui/wrappers.py
  24. +20 −2 python/plugins/processing/ui/widgetNumberSelector.ui
  25. +1 −1 src/3d/processing/qgsalgorithmtessellate.cpp
  26. +1 −1 src/3d/processing/qgsalgorithmtessellate.h
  27. +1 −1 src/analysis/processing/qgsalgorithmaddincrementalfield.cpp
  28. +1 −1 src/analysis/processing/qgsalgorithmaddincrementalfield.h
  29. +1 −1 src/analysis/processing/qgsalgorithmassignprojection.cpp
  30. +1 −1 src/analysis/processing/qgsalgorithmassignprojection.h
  31. +1 −1 src/analysis/processing/qgsalgorithmboundary.cpp
  32. +1 −1 src/analysis/processing/qgsalgorithmboundary.h
  33. +1 −1 src/analysis/processing/qgsalgorithmboundingbox.cpp
  34. +1 −1 src/analysis/processing/qgsalgorithmboundingbox.h
  35. +16 −5 src/analysis/processing/qgsalgorithmbuffer.cpp
  36. +1 −1 src/analysis/processing/qgsalgorithmcentroid.cpp
  37. +1 −1 src/analysis/processing/qgsalgorithmcentroid.h
  38. +1 −1 src/analysis/processing/qgsalgorithmconvexhull.cpp
  39. +1 −1 src/analysis/processing/qgsalgorithmconvexhull.h
  40. +1 −1 src/analysis/processing/qgsalgorithmdropgeometry.cpp
  41. +1 −1 src/analysis/processing/qgsalgorithmdropgeometry.h
  42. +1 −1 src/analysis/processing/qgsalgorithmdropmzvalues.cpp
  43. +1 −1 src/analysis/processing/qgsalgorithmdropmzvalues.h
  44. +1 −1 src/analysis/processing/qgsalgorithmextractbyattribute.cpp
  45. +1 −1 src/analysis/processing/qgsalgorithmextractbyexpression.cpp
  46. +1 −1 src/analysis/processing/qgsalgorithmfixgeometries.cpp
  47. +1 −1 src/analysis/processing/qgsalgorithmfixgeometries.h
  48. +1 −1 src/analysis/processing/qgsalgorithmmergelines.cpp
  49. +1 −1 src/analysis/processing/qgsalgorithmmergelines.h
  50. +1 −1 src/analysis/processing/qgsalgorithmminimumenclosingcircle.cpp
  51. +1 −1 src/analysis/processing/qgsalgorithmminimumenclosingcircle.h
  52. +1 −1 src/analysis/processing/qgsalgorithmorientedminimumboundingbox.cpp
  53. +1 −1 src/analysis/processing/qgsalgorithmorientedminimumboundingbox.h
  54. +1 −1 src/analysis/processing/qgsalgorithmpromotetomultipart.cpp
  55. +1 −1 src/analysis/processing/qgsalgorithmpromotetomultipart.h
  56. +1 −1 src/analysis/processing/qgsalgorithmsimplify.cpp
  57. +1 −1 src/analysis/processing/qgsalgorithmsimplify.h
  58. +1 −1 src/analysis/processing/qgsalgorithmsmooth.cpp
  59. +1 −1 src/analysis/processing/qgsalgorithmsmooth.h
  60. +1 −1 src/analysis/processing/qgsalgorithmsnaptogrid.cpp
  61. +1 −1 src/analysis/processing/qgsalgorithmsnaptogrid.h
  62. +1 −1 src/analysis/processing/qgsalgorithmsubdivide.cpp
  63. +1 −1 src/analysis/processing/qgsalgorithmsubdivide.h
  64. +1 −1 src/analysis/processing/qgsalgorithmtransform.cpp
  65. +1 −1 src/analysis/processing/qgsalgorithmtransform.h
  66. +1 −1 src/analysis/processing/qgsalgorithmtranslate.cpp
  67. +1 −1 src/analysis/processing/qgsalgorithmtranslate.h
  68. +12 −1 src/core/processing/qgsprocessingalgorithm.cpp
  69. +1 −1 src/core/processing/qgsprocessingalgorithm.h
  70. +69 −0 src/core/processing/qgsprocessingparameters.h
  71. +3 −4 src/core/qgsproperty.cpp
  72. +27 −15 src/gui/qgsmaptoolidentify.cpp
  73. +6 −1 src/gui/qgspropertyoverridebutton.cpp
  74. +14 −0 src/gui/qgspropertyoverridebutton.h
  75. +8 −0 tests/src/analysis/testqgsprocessing.cpp
@@ -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.
You can’t perform that action at this time.