Skip to content

Commit 4f4b831

Browse files
authoredMar 1, 2018
Merge pull request #6504 from m-kuhn/processingParametersRegistry
More processing parameters in modeller
2 parents 9e955ce + b67813b commit 4f4b831

File tree

12 files changed

+347
-165
lines changed

12 files changed

+347
-165
lines changed
 

‎python/core/processing/qgsprocessingprovider.sip.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,17 @@ Returns the matching algorithm by ``name``, or a None if no matching
204204
algorithm is contained by this provider.
205205

206206
.. seealso:: :py:func:`algorithms`
207+
%End
208+
209+
virtual QgsProcessingParameterDefinition *createParameter( const QString &type, const QString &name ) /Factory/;
210+
%Docstring
211+
Returns a new parameter from of the given type and name.
212+
This should be reimplemented by providers that implement custom types.
213+
If the provider does not implement the parameter with ``type``, a None will be returned.
214+
215+
By default, this returns a None.
216+
217+
.. versionadded:: 3.2
207218
%End
208219

209220
signals:

‎python/plugins/processing/algs/qgis/FieldsMapper.py

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -54,49 +54,8 @@ def tags(self):
5454
return self.tr('attributes,table').split(',')
5555

5656
def initParameters(self, config=None):
57-
58-
class ParameterFieldsMapping(QgsProcessingParameterDefinition):
59-
60-
def __init__(self, name, description, parentLayerParameterName='INPUT'):
61-
super().__init__(name, description)
62-
self._parentLayerParameter = parentLayerParameterName
63-
64-
def clone(self):
65-
copy = ParameterFieldsMapping(self.name(), self.description(), self._parentLayerParameter)
66-
return copy
67-
68-
def type(self):
69-
return 'fields_mapping'
70-
71-
def checkValueIsAcceptable(self, value, context=None):
72-
if not isinstance(value, list):
73-
return False
74-
for field_def in value:
75-
if not isinstance(field_def, dict):
76-
return False
77-
if 'name' not in field_def.keys():
78-
return False
79-
if 'type' not in field_def.keys():
80-
return False
81-
if 'expression' not in field_def.keys():
82-
return False
83-
return True
84-
85-
def valueAsPythonString(self, value, context):
86-
return str(value)
87-
88-
def asScriptCode(self):
89-
raise NotImplementedError()
90-
91-
@classmethod
92-
def fromScriptCode(cls, name, description, isOptional, definition):
93-
raise NotImplementedError()
94-
95-
def parentLayerParameter(self):
96-
return self._parentLayerParameter
97-
98-
fields_mapping = ParameterFieldsMapping(self.FIELDS_MAPPING,
99-
description=self.tr('Fields mapping'))
57+
fields_mapping = FieldsMapper.ParameterFieldsMapping(self.FIELDS_MAPPING,
58+
description=self.tr('Fields mapping'))
10059
fields_mapping.setMetadata({
10160
'widget_wrapper': 'processing.algs.qgis.ui.FieldsMappingPanel.FieldsMappingWidgetWrapper'
10261
})
@@ -181,3 +140,47 @@ def processFeature(self, feature, context, feedback):
181140
feature.setAttributes(attributes)
182141
self._row_number += 1
183142
return [feature]
143+
144+
class ParameterFieldsMapping(QgsProcessingParameterDefinition):
145+
146+
def __init__(self, name, description='', parentLayerParameterName='INPUT'):
147+
super().__init__(name, description)
148+
self._parentLayerParameter = parentLayerParameterName
149+
150+
def clone(self):
151+
copy = FieldsMapper.ParameterFieldsMapping(self.name(), self.description(), self._parentLayerParameter)
152+
return copy
153+
154+
def type(self):
155+
return self.typeName()
156+
157+
@staticmethod
158+
def typeName():
159+
return 'fields_mapping'
160+
161+
def checkValueIsAcceptable(self, value, context=None):
162+
if not isinstance(value, list):
163+
return False
164+
for field_def in value:
165+
if not isinstance(field_def, dict):
166+
return False
167+
if 'name' not in field_def.keys():
168+
return False
169+
if 'type' not in field_def.keys():
170+
return False
171+
if 'expression' not in field_def.keys():
172+
return False
173+
return True
174+
175+
def valueAsPythonString(self, value, context):
176+
return str(value)
177+
178+
def asScriptCode(self):
179+
raise NotImplementedError()
180+
181+
@classmethod
182+
def fromScriptCode(cls, name, description, isOptional, definition):
183+
raise NotImplementedError()
184+
185+
def parentLayerParameter(self):
186+
return self._parentLayerParameter

‎python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
from qgis.core import (QgsApplication,
3737
QgsProcessingProvider)
3838

39+
from PyQt5.QtCore import QCoreApplication
40+
3941
from processing.script import ScriptUtils
4042

4143
from .QgisAlgorithm import QgisAlgorithm
@@ -154,6 +156,7 @@
154156

155157

156158
class QgisAlgorithmProvider(QgsProcessingProvider):
159+
fieldMappingParameterName = QCoreApplication.translate('Processing', 'Fields Mapper')
157160

158161
def __init__(self):
159162
super().__init__()
@@ -317,5 +320,29 @@ def loadAlgorithms(self):
317320
for a in self.externalAlgs:
318321
self.addAlgorithm(a)
319322

323+
def load(self):
324+
success = super().load()
325+
326+
from processing.core.Processing import Processing
327+
328+
if success:
329+
Processing.registerParameter(
330+
'Fields Mapper',
331+
self.fieldMappingParameterName,
332+
parameter=FieldsMapper.ParameterFieldsMapping,
333+
metadata={'widget_wrapper': 'processing.algs.qgis.ui.FieldsMappingPanel.FieldsMappingWidgetWrapper'}
334+
)
335+
336+
return success
337+
338+
def unload(self):
339+
super().unload()
340+
from processing.core.Processing import Processing
341+
Processing.unregisterParameter(self.fieldMappingParameterName)
342+
343+
def createParameter(self, type, name):
344+
if type == 'fields_mapping':
345+
return FieldsMapper.ParameterFieldsMapping(name)
346+
320347
def supportsNonFileBasedOutput(self):
321348
return True

‎python/plugins/processing/algs/qgis/ui/FieldsMappingPanel.py

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
QVariant,
3737
Qt,
3838
pyqtSlot,
39+
QCoreApplication
3940
)
4041
from qgis.PyQt.QtWidgets import (
4142
QComboBox,
@@ -45,6 +46,8 @@
4546
QMessageBox,
4647
QSpinBox,
4748
QStyledItemDelegate,
49+
QWidget,
50+
QVBoxLayout
4851
)
4952

5053
from qgis.core import (
@@ -58,8 +61,9 @@
5861
)
5962
from qgis.gui import QgsFieldExpressionWidget
6063

61-
from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_MODELER
64+
from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_MODELER, DIALOG_BATCH
6265
from processing.tools import dataobjects
66+
from processing.algs.qgis.FieldsMapper import FieldsMapper
6367

6468

6569
pluginPath = os.path.dirname(__file__)
@@ -141,7 +145,10 @@ def columnCount(self, parent=QModelIndex()):
141145
def rowCount(self, parent=QModelIndex()):
142146
if parent.isValid():
143147
return 0
144-
return self._mapping.__len__()
148+
try:
149+
return len(self._mapping)
150+
except TypeError:
151+
return 0
145152

146153
def headerData(self, section, orientation, role=Qt.DisplayRole):
147154
if role == Qt.DisplayRole:
@@ -473,9 +480,31 @@ def __init__(self, *args, **kwargs):
473480
self._layer = None
474481

475482
def createWidget(self):
476-
panel = FieldsMappingPanel()
477-
panel.dialogType = self.dialogType
478-
return panel
483+
self.panel = FieldsMappingPanel()
484+
self.panel.dialogType = self.dialogType
485+
486+
if self.dialogType == DIALOG_MODELER:
487+
self.combobox = QComboBox()
488+
self.combobox.addItem(QCoreApplication.translate('Processing', '[Preconfigure]'), None)
489+
fieldsMappingInputs = self.dialog.getAvailableValuesOfType(FieldsMapper.ParameterFieldsMapping)
490+
for input in fieldsMappingInputs:
491+
self.combobox.addItem(self.dialog.resolveValueDescription(input), input)
492+
493+
def updatePanelEnabledState():
494+
if self.combobox.currentData() is None:
495+
self.panel.setEnabled(True)
496+
else:
497+
self.panel.setEnabled(False)
498+
499+
self.combobox.currentIndexChanged.connect(updatePanelEnabledState)
500+
501+
widget = QWidget()
502+
widget.setLayout(QVBoxLayout())
503+
widget.layout().addWidget(self.combobox)
504+
widget.layout().addWidget(self.panel)
505+
return widget
506+
else:
507+
return self.panel
479508

480509
def postInitialize(self, wrappers):
481510
for wrapper in wrappers:
@@ -506,10 +535,16 @@ def setLayer(self, layer):
506535
if not isinstance(layer, QgsVectorLayer):
507536
layer = None
508537
self._layer = layer
509-
self.widget.setLayer(self._layer)
538+
self.panel.setLayer(self._layer)
510539

511540
def setValue(self, value):
512-
self.widget.setValue(value)
541+
self.panel.setValue(value)
513542

514543
def value(self):
515-
return self.widget.value()
544+
if self.dialogType == DIALOG_MODELER:
545+
if self.combobox.currentData() is None:
546+
return self.panel.value()
547+
else:
548+
return self.comboValue(combobox=self.combobox)
549+
else:
550+
return self.panel.value()

‎python/plugins/processing/core/Processing.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
QgsProcessingOutputMapLayer,
4646
QgsProcessingOutputMultipleLayers)
4747

48+
from .parameters import initializeParameters
49+
4850
import processing
4951
from processing.core.ProcessingConfig import ProcessingConfig
5052
from processing.gui.MessageBarProgress import MessageBarProgress
@@ -67,6 +69,7 @@
6769

6870
class Processing(object):
6971
BASIC_PROVIDERS = []
72+
REGISTERED_PARAMETERS = dict()
7073

7174
@staticmethod
7275
def activateProvider(providerOrName, activate=True):
@@ -97,6 +100,7 @@ def initialize():
97100
if QgsApplication.processingRegistry().addProvider(p):
98101
Processing.BASIC_PROVIDERS.append(p)
99102
# And initialize
103+
initializeParameters()
100104
ProcessingConfig.initialize()
101105
ProcessingConfig.readSettings()
102106
RenderingStyles.loadStyles()
@@ -107,6 +111,40 @@ def deinitialize():
107111
QgsApplication.processingRegistry().removeProvider(p)
108112

109113
Processing.BASIC_PROVIDERS = []
114+
Processing.REGISTERED_PARAMETERS = dict()
115+
116+
@staticmethod
117+
def registerParameter(id, name, parameter, metadata=dict(), description=None, exposeToModeller=True):
118+
"""Register a new parameter.
119+
The ``name`` is a human readable translated string, the ``parameter`` is a class type with the base class ``qgis.core.QgsProcessingParameterDefinition``,
120+
the ``metadata`` is a dictionary with additional metadata, mainly used for widget wrappers.
121+
"""
122+
Processing.REGISTERED_PARAMETERS[id] = {
123+
'name': name,
124+
'parameter': parameter,
125+
'metadata': metadata,
126+
'description': description,
127+
'exposeToModeller': exposeToModeller
128+
}
129+
130+
@staticmethod
131+
def unregisterParameter(name):
132+
"""Unregister a registered parameter with the given name.
133+
"""
134+
del Processing.REGISTERED_PARAMETERS[name]
135+
136+
@staticmethod
137+
def registeredParameters():
138+
"""Returns a dict of registered parameters. The key of the dict is the id of the parameter.
139+
Each entry is itself a dict with the keys
140+
141+
- name: The human readable name of the parameter
142+
- parameter: The class of the parameter
143+
- metadata: Additional metadata for the parameter, mainly used for widget wrappers
144+
- description: A longer description for the parameter, suitable for tooltips etc
145+
- exposeToModeller: A boolean indicating if the parameter is available as model parameter input
146+
"""
147+
return Processing.REGISTERED_PARAMETERS
110148

111149
@staticmethod
112150
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None):

‎python/plugins/processing/core/parameters.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@
4141
QgsProcessingParameterDefinition,
4242
QgsProcessingParameterRasterLayer,
4343
QgsProcessingParameterVectorLayer,
44+
QgsProcessingParameterBand,
4445
QgsProcessingParameterBoolean,
4546
QgsProcessingParameterCrs,
4647
QgsProcessingParameterRange,
4748
QgsProcessingParameterPoint,
4849
QgsProcessingParameterEnum,
4950
QgsProcessingParameterExtent,
51+
QgsProcessingParameterExpression,
5052
QgsProcessingParameterMatrix,
5153
QgsProcessingParameterFile,
5254
QgsProcessingParameterField,
@@ -55,10 +57,36 @@
5557
QgsProcessingParameterFolderDestination,
5658
QgsProcessingParameterRasterDestination,
5759
QgsProcessingParameterString,
60+
QgsProcessingParameterMapLayer,
5861
QgsProcessingParameterMultipleLayers,
5962
QgsProcessingParameterFeatureSource,
6063
QgsProcessingParameterNumber)
6164

65+
from PyQt5.QtCore import QCoreApplication
66+
67+
PARAMETER_NUMBER = 'Number'
68+
PARAMETER_RASTER = 'Raster Layer'
69+
PARAMETER_TABLE = 'Vector Layer'
70+
PARAMETER_VECTOR = 'Vector Features'
71+
PARAMETER_STRING = 'String'
72+
PARAMETER_EXPRESSION = 'Expression'
73+
PARAMETER_BOOLEAN = 'Boolean'
74+
PARAMETER_TABLE_FIELD = 'Vector Field'
75+
PARAMETER_EXTENT = 'Extent'
76+
PARAMETER_FILE = 'File'
77+
PARAMETER_POINT = 'Point'
78+
PARAMETER_CRS = 'CRS'
79+
PARAMETER_MULTIPLE = 'Multiple Input'
80+
PARAMETER_BAND = 'Raster Band'
81+
PARAMETER_MAP_LAYER = 'Map Layer'
82+
PARAMETER_RANGE = 'Range'
83+
PARAMETER_ENUM = 'Enum'
84+
PARAMETER_MATRIX = 'Matrix'
85+
PARAMETER_VECTOR_DESTINATION = 'Vector Destination'
86+
PARAMETER_FILE_DESTINATION = 'File Destination'
87+
PARAMETER_FOLDER_DESTINATION = 'Folder Destination'
88+
PARAMETER_RASTER_DESTINATION = 'Raster Destination'
89+
6290

6391
def getParameterFromString(s):
6492
# Try the parameter definitions used in description files
@@ -209,3 +237,48 @@ def getParameterFromString(s):
209237
param = QgsProcessingParameters.parameterFromScriptCode(s)
210238
if param:
211239
return param
240+
241+
242+
def initializeParameters():
243+
from processing.core.Processing import Processing
244+
245+
Processing.registerParameter(PARAMETER_MAP_LAYER, QCoreApplication.translate('Processing', 'Map Layer'),
246+
QgsProcessingParameterMapLayer,
247+
description=QCoreApplication.translate('Processing', 'A generic map layer parameter, which accepts either vector or raster layers.'))
248+
Processing.registerParameter(PARAMETER_BAND, QCoreApplication.translate('Processing', 'Raster Band'),
249+
QgsProcessingParameterBand,
250+
description=QCoreApplication.translate('Processing', 'A raster band parameter, for selecting an existing band from a raster source.'))
251+
Processing.registerParameter(PARAMETER_EXPRESSION, QCoreApplication.translate('Processing', 'Expression'),
252+
QgsProcessingParameterExpression,
253+
description=QCoreApplication.translate('Processing', 'A QGIS expression parameter, which presents an expression builder widget to users.'))
254+
Processing.registerParameter(PARAMETER_RASTER, QCoreApplication.translate('Processing', 'Raster Layer'), QgsProcessingParameterRasterLayer,
255+
description=QCoreApplication.translate('Processing', 'A raster layer parameter.'))
256+
Processing.registerParameter(PARAMETER_TABLE, QCoreApplication.translate('Processing', 'Vector Layer'), QgsProcessingParameterVectorLayer,
257+
description=QCoreApplication.translate('Processing', 'A vector feature parameter, e.g. for algorithms which operate on the features within a layer.'))
258+
Processing.registerParameter(PARAMETER_BOOLEAN, QCoreApplication.translate('Processing', 'Boolean'), QgsProcessingParameterBoolean,
259+
description=QCoreApplication.translate('Processing', 'A boolean parameter, for true/false values.'))
260+
Processing.registerParameter(PARAMETER_CRS, QCoreApplication.translate('Processing', 'CRS'), QgsProcessingParameterCrs,
261+
description=QCoreApplication.translate('Processing', 'A coordinate reference system (CRS) input parameter.'))
262+
Processing.registerParameter(PARAMETER_RANGE, QCoreApplication.translate('Processing', 'Range'), QgsProcessingParameterRange)
263+
Processing.registerParameter(PARAMETER_POINT, QCoreApplication.translate('Processing', 'Point'), QgsProcessingParameterPoint,
264+
description=QCoreApplication.translate('Processing', 'A geographic point parameter.'))
265+
Processing.registerParameter(PARAMETER_ENUM, QCoreApplication.translate('Processing', 'Enum'), QgsProcessingParameterEnum, exposeToModeller=False)
266+
Processing.registerParameter(PARAMETER_EXTENT, QCoreApplication.translate('Processing', 'Extent'), QgsProcessingParameterExtent,
267+
description=QCoreApplication.translate('Processing', 'A map extent parameter.'))
268+
Processing.registerParameter(PARAMETER_MATRIX, QCoreApplication.translate('Processing', 'Matrix'), QgsProcessingParameterMatrix)
269+
Processing.registerParameter(PARAMETER_FILE, QCoreApplication.translate('Processing', 'File'), QgsProcessingParameterFile,
270+
description=QCoreApplication.translate('Processing', 'A file parameter, for use with non-map layer file sources.'))
271+
Processing.registerParameter(PARAMETER_TABLE_FIELD, QCoreApplication.translate('Processing', 'Field'), QgsProcessingParameterField,
272+
description=QCoreApplication.translate('Processing', 'A vector field parameter, for selecting an existing field from a vector source.'))
273+
Processing.registerParameter(PARAMETER_VECTOR_DESTINATION, QCoreApplication.translate('Processing', 'Vector Destination'), QgsProcessingParameterVectorDestination, exposeToModeller=False)
274+
Processing.registerParameter(PARAMETER_FILE_DESTINATION, QCoreApplication.translate('Processing', 'File Destination'), QgsProcessingParameterFileDestination, exposeToModeller=False)
275+
Processing.registerParameter(PARAMETER_FOLDER_DESTINATION, QCoreApplication.translate('Processing', 'Folder Destination'), QgsProcessingParameterFolderDestination, exposeToModeller=False)
276+
Processing.registerParameter(PARAMETER_RASTER_DESTINATION, QCoreApplication.translate('Processing', 'Raster Destination'), QgsProcessingParameterRasterDestination, exposeToModeller=False)
277+
Processing.registerParameter(PARAMETER_STRING, QCoreApplication.translate('Processing', 'String'), QgsProcessingParameterString,
278+
description=QCoreApplication.translate('Processing', 'A freeform string parameter.'))
279+
Processing.registerParameter(PARAMETER_MULTIPLE, QCoreApplication.translate('Processing', 'Multiple Layers'), QgsProcessingParameterMultipleLayers,
280+
description=QCoreApplication.translate('Processing', 'An input allowing selection of multiple sources, including multiple map layers or file sources.'))
281+
Processing.registerParameter(PARAMETER_VECTOR, QCoreApplication.translate('Processing', 'Feature Source'), QgsProcessingParameterFeatureSource)
282+
Processing.registerParameter(PARAMETER_NUMBER, QCoreApplication.translate('Processing', 'Number'), QgsProcessingParameterNumber,
283+
description=QCoreApplication.translate('Processing', 'A numeric parameter, including float or integer values.'))
284+
Processing.registeredParameters()

‎python/plugins/processing/modeler/ModelerDialog.py

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,14 @@ def _dragEnterEvent(event):
154154
event.ignore()
155155

156156
def _dropEvent(event):
157+
from processing.core.Processing import Processing
158+
157159
if event.mimeData().hasText():
158-
text = event.mimeData().text()
159-
if text in ModelerParameterDefinitionDialog.paramTypes:
160-
self.addInputOfType(text, event.pos())
160+
itemId = event.mimeData().text()
161+
if itemId in Processing.registeredParameters():
162+
self.addInputOfType(itemId, event.pos())
161163
else:
162-
alg = QgsApplication.processingRegistry().createAlgorithmById(text)
164+
alg = QgsApplication.processingRegistry().createAlgorithmById(itemId)
163165
if alg is not None:
164166
self._addAlgorithm(alg, event.pos())
165167
event.accept()
@@ -225,7 +227,7 @@ def _mouseMoveEvent(e):
225227

226228
def _mimeDataInput(items):
227229
mimeData = QMimeData()
228-
text = items[0].text(0)
230+
text = items[0].data(0, Qt.UserRole)
229231
mimeData.setText(text)
230232
return mimeData
231233

@@ -545,25 +547,24 @@ def repaintModel(self, controls=True):
545547

546548
def addInput(self):
547549
item = self.inputsTree.currentItem()
548-
paramType = str(item.text(0))
549-
self.addInputOfType(paramType)
550+
param = item.data(0, Qt.UserRole)
551+
self.addInputOfType(param)
550552

551553
def addInputOfType(self, paramType, pos=None):
552-
if paramType in ModelerParameterDefinitionDialog.paramTypes:
553-
dlg = ModelerParameterDefinitionDialog(self.model, paramType)
554-
dlg.exec_()
555-
if dlg.param is not None:
556-
if pos is None:
557-
pos = self.getPositionForParameterItem()
558-
if isinstance(pos, QPoint):
559-
pos = QPointF(pos)
560-
component = QgsProcessingModelParameter(dlg.param.name())
561-
component.setDescription(dlg.param.name())
562-
component.setPosition(pos)
563-
self.model.addModelParameter(dlg.param, component)
564-
self.repaintModel()
565-
# self.view.ensureVisible(self.scene.getLastParameterItem())
566-
self.hasChanged = True
554+
dlg = ModelerParameterDefinitionDialog(self.model, paramType)
555+
dlg.exec_()
556+
if dlg.param is not None:
557+
if pos is None:
558+
pos = self.getPositionForParameterItem()
559+
if isinstance(pos, QPoint):
560+
pos = QPointF(pos)
561+
component = QgsProcessingModelParameter(dlg.param.name())
562+
component.setDescription(dlg.param.name())
563+
component.setPosition(pos)
564+
self.model.addModelParameter(dlg.param, component)
565+
self.repaintModel()
566+
# self.view.ensureVisible(self.scene.getLastParameterItem())
567+
self.hasChanged = True
567568

568569
def getPositionForParameterItem(self):
569570
MARGIN = 20
@@ -620,16 +621,21 @@ def _filterItem(self, item, text):
620621
return False
621622

622623
def fillInputsTree(self):
624+
from processing.core.Processing import Processing
625+
623626
icon = QIcon(os.path.join(pluginPath, 'images', 'input.svg'))
624627
parametersItem = QTreeWidgetItem()
625628
parametersItem.setText(0, self.tr('Parameters'))
626-
for paramType in sorted(ModelerParameterDefinitionDialog.paramTypes):
627-
paramItem = QTreeWidgetItem()
628-
paramItem.setText(0, paramType)
629-
paramItem.setIcon(0, icon)
630-
paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled)
631-
paramItem.setToolTip(0, ModelerParameterDefinitionDialog.inputTooltip(paramType))
632-
parametersItem.addChild(paramItem)
629+
sortedParams = sorted(Processing.registeredParameters().items())
630+
for param in sortedParams:
631+
if param[1]['exposeToModeller']:
632+
paramItem = QTreeWidgetItem()
633+
paramItem.setText(0, param[1]['name'])
634+
paramItem.setData(0, Qt.UserRole, param[0])
635+
paramItem.setIcon(0, icon)
636+
paramItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled)
637+
paramItem.setToolTip(0, param[1]['description'])
638+
parametersItem.addChild(paramItem)
633639
self.inputsTree.addTopLevelItem(parametersItem)
634640
parametersItem.setExpanded(True)
635641

‎python/plugins/processing/modeler/ModelerGraphicItem.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,11 @@ def editElement(self):
204204
self.scene.dialog.repaintModel()
205205
elif isinstance(self.element, QgsProcessingModelChildAlgorithm):
206206
dlg = None
207-
try:
208-
dlg = self.element.algorithm().getCustomModelerParametersDialog(self.model, self.element.childId())
209-
except:
210-
pass
207+
elemAlg = self.element.algorithm()
208+
if hasattr(elemAlg, 'getCustomModelerParametersDialog'):
209+
dlg = elemAlg.getCustomModelerParametersDialog(self.model, self.element.childId())
211210
if not dlg:
212-
dlg = ModelerParametersDialog(self.element.algorithm(), self.model, self.element.childId())
211+
dlg = ModelerParametersDialog(elemAlg, self.model, self.element.childId())
213212
if dlg.exec_():
214213
alg = dlg.createAlgorithm()
215214
alg.setChildId(self.element.childId())

‎python/plugins/processing/modeler/ModelerParameterDefinitionDialog.py

Lines changed: 36 additions & 80 deletions
Large diffs are not rendered by default.

‎src/core/processing/qgsprocessingparameters.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgssettings.h"
2626
#include "qgsvectorfilewriter.h"
2727
#include "qgsreferencedgeometry.h"
28+
#include "qgsprocessingregistry.h"
2829
#include <functional>
2930

3031
bool QgsProcessingParameters::isDynamic( const QVariantMap &parameters, const QString &name )
@@ -1079,6 +1080,21 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantM
10791080
def.reset( new QgsProcessingParameterFolderDestination( name ) );
10801081
else if ( type == QgsProcessingParameterBand::typeName() )
10811082
def.reset( new QgsProcessingParameterBand( name ) );
1083+
else
1084+
{
1085+
const QList<QgsProcessingProvider *> providers = QgsApplication::instance()->processingRegistry()->providers();
1086+
1087+
for ( QgsProcessingProvider *provider : providers )
1088+
{
1089+
QgsProcessingParameterDefinition *param = provider->createParameter( type, name );
1090+
1091+
if ( param )
1092+
{
1093+
def.reset( param );
1094+
break;
1095+
}
1096+
}
1097+
}
10821098

10831099
if ( !def )
10841100
return nullptr;

‎src/core/processing/qgsprocessingprovider.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ const QgsProcessingAlgorithm *QgsProcessingProvider::algorithm( const QString &n
7474
return mAlgorithms.value( name );
7575
}
7676

77+
QgsProcessingParameterDefinition *QgsProcessingProvider::createParameter( const QString &type, const QString &name )
78+
{
79+
Q_UNUSED( type )
80+
Q_UNUSED( name )
81+
return nullptr;
82+
}
83+
7784
bool QgsProcessingProvider::addAlgorithm( QgsProcessingAlgorithm *algorithm )
7885
{
7986
if ( !algorithm )

‎src/core/processing/qgsprocessingprovider.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ class CORE_EXPORT QgsProcessingProvider : public QObject
203203
*/
204204
const QgsProcessingAlgorithm *algorithm( const QString &name ) const;
205205

206+
/**
207+
* Returns a new parameter from of the given type and name.
208+
* This should be reimplemented by providers that implement custom types.
209+
* If the provider does not implement the parameter with \a type, a nullptr will be returned.
210+
*
211+
* By default, this returns a nullptr.
212+
*
213+
* \since QGIS 3.2
214+
*/
215+
virtual QgsProcessingParameterDefinition *createParameter( const QString &type, const QString &name ) SIP_FACTORY;
216+
206217
signals:
207218

208219
/**

0 commit comments

Comments
 (0)
Please sign in to comment.