Beispiel #1
0
	def createWidgets(self):

		vlayout = QVBoxLayout()

		lbl = QLabel(
			"A column labeled 'ID' with unique increasing numbers for every row will be "\
			"added to the output table automatically. In addition to this column it is also "\
			"possible to copy one of the columns of the source table to the output table "\
			"(tip: if a row identifying column is copied this can later be used for transferring "\
			"more data from source table to the new table if necessary).")
		lbl.setWordWrap(True);
		vlayout.addWidget(lbl)

		vlayout.addSpacing(20)

		self._copyCheck = WidgetEnableCheckBox("Copy column from source table")
		self.regProp("copy_column_enabled", WizProp(self._copyCheck, False))
		vlayout.addWidget(self._copyCheck)

		glayout = QGridLayout()
		glayout.setColumnMinimumWidth(0, 20)

		lbl = QLabel(
			"The selected column of the source table will be added to the output table "\
			"(possibly with a new name). For every object in the output table the value of "\
			"its source object will be copied to this column.")
		lbl.setWordWrap(True);
		self._copyCheck.addWidget(lbl)
		glayout.addWidget(lbl, 0, 1, 1, 3)

		lbl = QLabel("Column in source table")
		self._copyCheck.addWidget(lbl)
		glayout.addWidget(lbl, 1, 1)
		self._sourceCombo = QComboBox()
		self.regProp("copy_column_in", WizProp(self._sourceCombo, ""))
		self._copyCheck.addWidget(self._sourceCombo)
		glayout.addWidget(self._sourceCombo, 1, 2)

		lbl = QLabel("Column in output table")
		self._copyCheck.addWidget(lbl)
		glayout.addWidget(lbl, 2, 1)
		self._outputEdit = QLineEdit()
		self.regProp("copy_column_out", WizProp(self._outputEdit, ""))
		self._copyCheck.addWidget(self._outputEdit)
		glayout.addWidget(self._outputEdit, 2, 2)

		vlayout.addLayout(glayout)

		vlayout.addStretch(1)

		self.setLayout(vlayout)
Beispiel #2
0
    def createWidgets(self):

        vlayout = QVBoxLayout()

        glayout = QGridLayout()
        glayout.setColumnStretch(3, 1)

        glayout.addWidget(QLabel("Snap points closer than"), 0, 0)
        self._snapEdit = QLineEdit()
        self._snapEdit.setAlignment(Qt.AlignRight)
        self.regProp("trim_snap", WizPropFloat(self._snapEdit, 1, 1))
        glayout.addWidget(self._snapEdit, 0, 1)
        glayout.addWidget(QLabel("meters"), 0, 2)

        glayout.addWidget(QLabel("Remove tail segments shorter than"), 1, 0)
        self._tailEdit = QLineEdit()
        self._tailEdit.setAlignment(Qt.AlignRight)
        self.regProp("trim_tail", WizPropFloat(self._tailEdit, 10, 1))
        glayout.addWidget(self._tailEdit, 1, 1)
        glayout.addWidget(QLabel("meters"), 1, 2)

        glayout.addWidget(
            QLabel("Merge segment-pairs with colinear deviation below"), 2, 0)
        self._mergeEdit = QLineEdit()
        self._mergeEdit.setAlignment(Qt.AlignRight)
        self.regProp("trim_coldev", WizPropFloat(self._mergeEdit, 1, 1))
        glayout.addWidget(self._mergeEdit, 2, 1)
        glayout.addWidget(QLabel("meters"), 2, 2)

        glayout.setRowMinimumHeight(3, 10)

        vlayout.addLayout(glayout)

        vlayout.addSpacing(10)

        hlayout = QHBoxLayout()
        btn = QPushButton("Restore default values")
        btn.clicked.connect(self.resetProps)
        hlayout.addWidget(btn)
        hlayout.addStretch(1)
        vlayout.addLayout(hlayout)

        vlayout.addStretch(1)

        self.setLayout(vlayout)
Beispiel #3
0
    def createWidgets(self):

        vlayout = QVBoxLayout()

        widget = QCheckBox("Calculate number of reached lines")
        vlayout.addWidget(widget)
        self.regProp("calc_count", WizProp(widget, True))

        vlayout.addSpacing(5)

        widget = QCheckBox("Calculate total length of reached lines")
        vlayout.addWidget(widget)
        self.regProp("calc_length", WizProp(widget, True))

        vlayout.addSpacing(5)

        area_unit_combo = QComboBox()
        for item in [('square meter', 'm2'), ('square kilometer', 'km2'),
                     ('hectare', 'ha')]:
            area_unit_combo.addItem(item[0], item[1])
        hlayout = QHBoxLayout()
        hlayout.addSpacing(20)
        unit_label = QLabel("Area unit")
        hlayout.addWidget(unit_label)
        hlayout.addWidget(area_unit_combo)
        hlayout.addStretch(1)
        widget = WidgetEnableCheckBox("Calculate reached area",
                                      [unit_label, area_unit_combo])
        vlayout.addWidget(widget)
        vlayout.addLayout(hlayout)
        self.regProp("calc_area", WizProp(widget, True))
        self.regProp("area_unit", WizPropCombo(area_unit_combo, 'm2'))

        vlayout.addStretch(1)

        self.setLayout(vlayout)
Beispiel #4
0
class ModelerParameterDefinitionDialog(QDialog):
    PARAMETER_NUMBER = 'Number'
    PARAMETER_RASTER = 'Raster Layer'
    PARAMETER_TABLE = 'Vector Layer'
    PARAMETER_VECTOR = 'Feature Source'
    PARAMETER_STRING = 'String'
    PARAMETER_EXPRESSION = 'Expression'
    PARAMETER_BOOLEAN = 'Boolean'
    PARAMETER_TABLE_FIELD = 'Layer Field'
    PARAMETER_EXTENT = 'Extent'
    PARAMETER_FILE = 'File'
    PARAMETER_POINT = 'Point'
    PARAMETER_CRS = 'CRS'
    PARAMETER_MULTIPLE = 'Multiple Input'
    PARAMETER_BAND = 'Raster Band'
    PARAMETER_MAP_LAYER = 'Map Layer'

    paramTypes = [
        PARAMETER_BOOLEAN, PARAMETER_EXTENT, PARAMETER_FILE, PARAMETER_NUMBER,
        PARAMETER_RASTER, PARAMETER_STRING, PARAMETER_EXPRESSION,
        PARAMETER_MAP_LAYER, PARAMETER_TABLE, PARAMETER_TABLE_FIELD,
        PARAMETER_VECTOR, PARAMETER_POINT, PARAMETER_CRS, PARAMETER_MULTIPLE,
        PARAMETER_BAND
    ]

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(
            settings.value(
                "/Processing/modelParametersDefinitionDialogGeometry",
                QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter Definition'))
        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(20)

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or \
                isinstance(self.param, QgsProcessingParameterBoolean):
            self.state = QCheckBox()
            self.state.setText(self.tr('Checked'))
            self.state.setChecked(False)
            if self.param is not None:
                self.state.setChecked(bool(self.param.defaultValue()))
            self.verticalLayout.addWidget(self.state)
        elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, QgsProcessingParameterField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource,
                                           QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.dataType() is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.dataType() + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.allowMultiple())
            self.verticalLayout.addWidget(self.multipleCheck)

            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setToolTip(
                self.
                tr('Default field name, or ; separated list of field names for multiple field parameters'
                   ))
            if self.param is not None:
                default = self.param.defaultValue()
                if default is not None:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BAND or \
                isinstance(self.param, QgsProcessingParameterBand):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterRasterLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType
              in (ModelerParameterDefinitionDialog.PARAMETER_VECTOR,
                  ModelerParameterDefinitionDialog.PARAMETER_TABLE)
              or isinstance(self.param, (QgsProcessingParameterFeatureSource,
                                         QgsProcessingParameterVectorLayer))):
            self.verticalLayout.addWidget(QLabel(self.tr('Geometry type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Geometry Not Required'),
                                        QgsProcessing.TypeVector)
            self.shapetypeCombo.addItem(self.tr('Point'),
                                        QgsProcessing.TypeVectorPoint)
            self.shapetypeCombo.addItem(self.tr('Line'),
                                        QgsProcessing.TypeVectorLine)
            self.shapetypeCombo.addItem(self.tr('Polygon'),
                                        QgsProcessing.TypeVectorPolygon)
            self.shapetypeCombo.addItem(self.tr('Any Geometry Type'),
                                        QgsProcessing.TypeVectorAnyGeometry)
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(
                    self.shapetypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'),
                                       QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(
                self.tr('Vector (No Geometry Required)'),
                QgsProcessing.TypeVector)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'),
                                       QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'),
                                       QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'),
                                       QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'),
                                       QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'),
                                       QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('File'), QgsProcessing.TypeFile)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(
                    self.datatypeCombo.findData(self.param.layerType()))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_NUMBER
              or isinstance(self.param, QgsProcessingParameterNumber)):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.minimum()))
                self.maxTextBox.setText(str(self.param.maximum()))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.defaultValue()
                if self.param.dataType(
                ) == QgsProcessingParameterNumber.Integer:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION
              or isinstance(self.param, QgsProcessingParameterExpression)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultEdit = QgsExpressionLineEdit()
            if self.param is not None:
                self.defaultEdit.setExpression(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultEdit)

            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            self.parentCombo.addItem(self.tr("None"), None)
            idx = 1
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource,
                                           QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_STRING
              or isinstance(self.param, QgsProcessingParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE
              or isinstance(self.param, QgsProcessingParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(1 if self.param.behavior(
                ) == QgsProcessingParameterFile.Folder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_POINT
              or isinstance(self.param, QgsProcessingParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS
              or isinstance(self.param, QgsProcessingParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.selector = QgsProjectionSelectionWidget()
            if self.param is not None:
                self.selector.setCrs(
                    QgsCoordinateReferenceSystem(self.param.defaultValue()))
            else:
                self.selector.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
            self.verticalLayout.addWidget(self.selector)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(
                not self.param.flags()
                & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.verticalLayout.addStretch()
        self.verticalLayout.addWidget(self.buttonBox)

        self.setLayout(self.verticalLayout)

    def accept(self):
        description = str(self.nameTextBox.text())
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while self.alg.parameterDefinition(name):
                name = safeName.lower() + str(i)
                i += 1
        else:
            name = self.param.name()
        if (self.paramType
                == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN
                or isinstance(self.param, QgsProcessingParameterBoolean)):
            self.param = QgsProcessingParameterBoolean(name, description,
                                                       self.state.isChecked())
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD
              or isinstance(self.param, QgsProcessingParameterField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            default = self.defaultTextBox.text()
            if not default:
                default = None
            self.param = QgsProcessingParameterField(
                name,
                description,
                defaultValue=default,
                parentLayerParameterName=parent,
                type=datatype,
                allowMultiple=self.multipleCheck.isChecked())
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BAND
              or isinstance(self.param, QgsProcessingParameterBand)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterBand(name, description, None,
                                                    parent)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MAP_LAYER
              or isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.param = QgsProcessingParameterMapLayer(name, description)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_RASTER
              or isinstance(self.param, QgsProcessingParameterRasterLayer)):
            self.param = QgsProcessingParameterRasterLayer(name, description)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_TABLE
              or isinstance(self.param, QgsProcessingParameterVectorLayer)):
            self.param = QgsProcessingParameterVectorLayer(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_VECTOR
              or isinstance(self.param, QgsProcessingParameterFeatureSource)):
            self.param = QgsProcessingParameterFeatureSource(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.param = QgsProcessingParameterMultipleLayers(
                name, description, self.datatypeCombo.currentData())
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_NUMBER
              or isinstance(self.param, QgsProcessingParameterNumber)):
            try:
                self.param = QgsProcessingParameterNumber(
                    name, description, QgsProcessingParameterNumber.Double,
                    self.defaultTextBox.text())
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION
              or isinstance(self.param, QgsProcessingParameterExpression)):
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterExpression(
                name, description, str(self.defaultEdit.expression()), parent)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_STRING
              or isinstance(self.param, QgsProcessingParameterString)):
            self.param = QgsProcessingParameterString(
                name, description, str(self.defaultTextBox.text()))
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_EXTENT
              or isinstance(self.param, QgsProcessingParameterExtent)):
            self.param = QgsProcessingParameterExtent(name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE
              or isinstance(self.param, QgsProcessingParameterFile)):
            isFolder = self.fileFolderCombo.currentIndex() == 1
            self.param = QgsProcessingParameterFile(
                name, description, QgsProcessingParameterFile.Folder
                if isFolder else QgsProcessingParameterFile.File)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_POINT
              or isinstance(self.param, QgsProcessingParameterPoint)):
            self.param = QgsProcessingParameterPoint(
                name, description, str(self.defaultTextBox.text()))
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS
              or isinstance(self.param, QgsProcessingParameterCrs)):
            self.param = QgsProcessingParameterCrs(
                name, description,
                self.selector.crs().authid())
        if not self.requiredCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagOptional)

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.reject(self)
class ModelerParameterDefinitionDialog(QDialog):

    PARAMETER_NUMBER = 'Number'
    PARAMETER_RASTER = 'Raster layer'
    PARAMETER_TABLE = 'Table'
    PARAMETER_VECTOR = 'Vector layer'
    PARAMETER_STRING = 'String'
    PARAMETER_EXPRESSION = 'Expression'
    PARAMETER_BOOLEAN = 'Boolean'
    PARAMETER_TABLE_FIELD = 'Table field'
    PARAMETER_EXTENT = 'Extent'
    PARAMETER_FILE = 'File'
    PARAMETER_POINT = 'Point'
    PARAMETER_CRS = 'CRS'
    PARAMETER_MULTIPLE = 'Multiple input'

    paramTypes = [
        PARAMETER_BOOLEAN,
        PARAMETER_EXTENT,
        PARAMETER_FILE,
        PARAMETER_NUMBER,
        PARAMETER_RASTER,
        PARAMETER_STRING,
        PARAMETER_EXPRESSION,
        PARAMETER_TABLE,
        PARAMETER_TABLE_FIELD,
        PARAMETER_VECTOR,
        PARAMETER_POINT,
        PARAMETER_CRS,
        PARAMETER_MULTIPLE
    ]

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()

    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter definition'))
        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(20)

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or \
                isinstance(self.param, ParameterBoolean):
            self.state = QCheckBox()
            self.state.setText(self.tr('Checked'))
            self.state.setChecked(False)
            if self.param is not None:
                self.state.setChecked(bool(self.param.value))
            self.verticalLayout.addWidget(self.state)
        elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, ParameterTableField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.inputs.values()):
                if isinstance(param.param, (ParameterVector, ParameterTable)):
                    self.parentCombo.addItem(param.param.description(), param.param.name())
                    if self.param is not None:
                        if self.param.parent == param.param.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.datatype is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.datatype + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.multiple)
            self.verticalLayout.addWidget(self.multipleCheck)

        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_VECTOR or
                isinstance(self.param, ParameterVector)):
            self.verticalLayout.addWidget(QLabel(self.tr('Shape type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Any'))
            self.shapetypeCombo.addItem(self.tr('Point'))
            self.shapetypeCombo.addItem(self.tr('Line'))
            self.shapetypeCombo.addItem(self.tr('Polygon'))
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(self.param.datatype[0] + 1)
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE or
                isinstance(self.param, ParameterMultipleInput)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Vector (any)'))
            self.datatypeCombo.addItem(self.tr('Vector (point)'))
            self.datatypeCombo.addItem(self.tr('Vector (line)'))
            self.datatypeCombo.addItem(self.tr('Vector (polygon)'))
            self.datatypeCombo.addItem(self.tr('Raster'))
            self.datatypeCombo.addItem(self.tr('File'))
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(self.param.datatype + 1)
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_NUMBER or
                isinstance(self.param, ParameterNumber)):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.min))
                self.maxTextBox.setText(str(self.param.max))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.default
                if self.param.isInteger:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION or
              isinstance(self.param, ParameterExpression)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultEdit = QgsExpressionLineEdit()
            if self.param is not None:
                self.defaultEdit.setExpression(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultEdit)

            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            self.parentCombo.addItem(self.tr("None"), None)
            idx = 1
            for param in list(self.alg.inputs.values()):
                if isinstance(param.param, (ParameterVector, ParameterTable)):
                    self.parentCombo.addItem(param.param.description(), param.param.name())
                    if self.param is not None:
                        if self.param.parent_layer == param.param.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_STRING or
                isinstance(self.param, ParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE or
                isinstance(self.param, ParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(
                    1 if self.param.isFolder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_POINT or
                isinstance(self.param, ParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS or
                isinstance(self.param, ParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.selector = QgsProjectionSelectionWidget()
            if self.param is not None:
                self.selector.setCrs(QgsCoordinateReferenceSystem(self.param.defaultValue()))
            else:
                self.selector.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
            self.verticalLayout.addWidget(self.selector)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(not self.param.flags() & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel |
                                          QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)

        self.verticalLayout.addStretch()
        self.verticalLayout.addWidget(self.buttonBox)

        self.setLayout(self.verticalLayout)

    def okPressed(self):
        description = str(self.nameTextBox.text())
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while name in self.alg.inputs:
                name = safeName.lower() + str(i)
        else:
            name = self.param.name()
        if (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or
                isinstance(self.param, ParameterBoolean)):
            self.param = ParameterBoolean(name, description, self.state.isChecked())
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or
              isinstance(self.param, ParameterTableField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            self.param = ParameterTableField(name, description, parent, datatype, multiple=self.multipleCheck.isChecked())
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_RASTER or
                isinstance(self.param, ParameterRaster)):
            self.param = ParameterRaster(
                name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE or
                isinstance(self.param, ParameterTable)):
            self.param = ParameterTable(
                name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_VECTOR or
                isinstance(self.param, ParameterVector)):
            self.param = ParameterVector(
                name, description,
                [self.shapetypeCombo.currentIndex() - 1])
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE or
                isinstance(self.param, ParameterMultipleInput)):
            self.param = ParameterMultipleInput(
                name, description,
                self.datatypeCombo.currentIndex() - 1)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_NUMBER or
                isinstance(self.param, ParameterNumber)):
            try:
                vmin = self.minTextBox.text().strip()
                if vmin == '':
                    vmin = None
                else:
                    vmin = float(vmin)
                vmax = self.maxTextBox.text().strip()
                if vmax == '':
                    vmax = None
                else:
                    vmax = float(vmax)
                self.param = ParameterNumber(name, description, vmin, vmax,
                                             str(self.defaultTextBox.text()))
            except:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION or
                isinstance(self.param, ParameterExpression)):
            parent = self.parentCombo.currentData()
            self.param = ParameterExpression(name, description,
                                             default=str(self.defaultEdit.expression()),
                                             parent_layer=parent)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_STRING or
                isinstance(self.param, ParameterString)):
            self.param = ParameterString(name, description,
                                         str(self.defaultTextBox.text()))
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_EXTENT or
                isinstance(self.param, ParameterExtent)):
            self.param = ParameterExtent(name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE or
                isinstance(self.param, ParameterFile)):
            isFolder = self.fileFolderCombo.currentIndex() == 1
            self.param = ParameterFile(name, description, isFolder=isFolder)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_POINT or
                isinstance(self.param, ParameterPoint)):
            self.param = ParameterPoint(name, description,
                                        str(self.defaultTextBox.text()))
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS or
                isinstance(self.param, ParameterCrs)):
            self.param = ParameterCrs(name, description, default=self.selector.crs().authid())
        if not self.requiredCheck.isChecked():
            self.param.setFlags(self.param.flags() | QgsProcessingParameterDefinition.FlagOptional)
        self.close()

    def cancelPressed(self):
        self.param = None
        self.close()
Beispiel #6
0
class ModelerParameterDefinitionDialog(QDialog):

    PARAMETER_NUMBER = 'Number'
    PARAMETER_RASTER = 'Raster layer'
    PARAMETER_TABLE = 'Table'
    PARAMETER_VECTOR = 'Vector layer'
    PARAMETER_STRING = 'String'
    PARAMETER_EXPRESSION = 'Expression'
    PARAMETER_BOOLEAN = 'Boolean'
    PARAMETER_TABLE_FIELD = 'Table field'
    PARAMETER_EXTENT = 'Extent'
    PARAMETER_FILE = 'File'
    PARAMETER_POINT = 'Point'
    PARAMETER_CRS = 'CRS'
    PARAMETER_MULTIPLE = 'Multiple input'

    paramTypes = [
        PARAMETER_BOOLEAN, PARAMETER_EXTENT, PARAMETER_FILE, PARAMETER_NUMBER,
        PARAMETER_RASTER, PARAMETER_STRING, PARAMETER_EXPRESSION,
        PARAMETER_TABLE, PARAMETER_TABLE_FIELD, PARAMETER_VECTOR,
        PARAMETER_POINT, PARAMETER_CRS, PARAMETER_MULTIPLE
    ]

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()

    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter definition'))
        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(20)

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, Parameter):
            self.nameTextBox.setText(self.param.description)

        if self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or \
                isinstance(self.param, ParameterBoolean):
            self.state = QCheckBox()
            self.state.setText(self.tr('Checked'))
            self.state.setChecked(False)
            if self.param is not None:
                self.state.setChecked(bool(self.param.value))
            self.verticalLayout.addWidget(self.state)
        elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, ParameterTableField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.inputs.values()):
                if isinstance(param.param, (ParameterVector, ParameterTable)):
                    self.parentCombo.addItem(param.param.description,
                                             param.param.name)
                    if self.param is not None:
                        if self.param.parent == param.param.name:
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.datatype is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.datatype + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.multiple)
            self.verticalLayout.addWidget(self.multipleCheck)

        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_VECTOR
              or isinstance(self.param, ParameterVector)):
            self.verticalLayout.addWidget(QLabel(self.tr('Shape type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Any'))
            self.shapetypeCombo.addItem(self.tr('Point'))
            self.shapetypeCombo.addItem(self.tr('Line'))
            self.shapetypeCombo.addItem(self.tr('Polygon'))
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(self.param.datatype[0] + 1)
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE
              or isinstance(self.param, ParameterMultipleInput)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Vector (any)'))
            self.datatypeCombo.addItem(self.tr('Vector (point)'))
            self.datatypeCombo.addItem(self.tr('Vector (line)'))
            self.datatypeCombo.addItem(self.tr('Vector (polygon)'))
            self.datatypeCombo.addItem(self.tr('Raster'))
            self.datatypeCombo.addItem(self.tr('File'))
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(self.param.datatype + 1)
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_NUMBER
              or isinstance(self.param, ParameterNumber)):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.min))
                self.maxTextBox.setText(str(self.param.max))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.default
                if self.param.isInteger:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION
              or isinstance(self.param, ParameterExpression)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultEdit = QgsExpressionLineEdit()
            if self.param is not None:
                self.defaultEdit.setExpression(self.param.default)
            self.verticalLayout.addWidget(self.defaultEdit)

            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            self.parentCombo.addItem(self.tr("None"), None)
            idx = 1
            for param in list(self.alg.inputs.values()):
                if isinstance(param.param, (ParameterVector, ParameterTable)):
                    self.parentCombo.addItem(param.param.description,
                                             param.param.name)
                    if self.param is not None:
                        if self.param.parent_layer == param.param.name:
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_STRING
              or isinstance(self.param, ParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE
              or isinstance(self.param, ParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(
                    1 if self.param.isFolder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_POINT
              or isinstance(self.param, ParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS
              or isinstance(self.param, ParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.selector = QgsProjectionSelectionWidget()
            if self.param is not None:
                self.selector.setCrs(
                    QgsCoordinateReferenceSystem(self.param.default))
            else:
                self.selector.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
            self.verticalLayout.addWidget(self.selector)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(not self.param.optional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)

        self.verticalLayout.addStretch()
        self.verticalLayout.addWidget(self.buttonBox)

        self.setLayout(self.verticalLayout)

    def okPressed(self):
        description = str(self.nameTextBox.text())
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while name in self.alg.inputs:
                name = safeName.lower() + str(i)
        else:
            name = self.param.name
        if (self.paramType
                == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN
                or isinstance(self.param, ParameterBoolean)):
            self.param = ParameterBoolean(name, description,
                                          self.state.isChecked())
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD
              or isinstance(self.param, ParameterTableField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            self.param = ParameterTableField(
                name,
                description,
                parent,
                datatype,
                multiple=self.multipleCheck.isChecked())
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_RASTER
              or isinstance(self.param, ParameterRaster)):
            self.param = ParameterRaster(name, description)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_TABLE
              or isinstance(self.param, ParameterTable)):
            self.param = ParameterTable(name, description)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_VECTOR
              or isinstance(self.param, ParameterVector)):
            self.param = ParameterVector(
                name, description, [self.shapetypeCombo.currentIndex() - 1])
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE
              or isinstance(self.param, ParameterMultipleInput)):
            self.param = ParameterMultipleInput(
                name, description,
                self.datatypeCombo.currentIndex() - 1)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_NUMBER
              or isinstance(self.param, ParameterNumber)):
            try:
                vmin = self.minTextBox.text().strip()
                if vmin == '':
                    vmin = None
                else:
                    vmin = float(vmin)
                vmax = self.maxTextBox.text().strip()
                if vmax == '':
                    vmax = None
                else:
                    vmax = float(vmax)
                self.param = ParameterNumber(name, description, vmin, vmax,
                                             str(self.defaultTextBox.text()))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION
              or isinstance(self.param, ParameterExpression)):
            parent = self.parentCombo.currentData()
            self.param = ParameterExpression(
                name,
                description,
                default=str(self.defaultEdit.expression()),
                parent_layer=parent)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_STRING
              or isinstance(self.param, ParameterString)):
            self.param = ParameterString(name, description,
                                         str(self.defaultTextBox.text()))
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_EXTENT
              or isinstance(self.param, ParameterExtent)):
            self.param = ParameterExtent(name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE
              or isinstance(self.param, ParameterFile)):
            isFolder = self.fileFolderCombo.currentIndex() == 1
            self.param = ParameterFile(name, description, isFolder=isFolder)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_POINT
              or isinstance(self.param, ParameterPoint)):
            self.param = ParameterPoint(name, description,
                                        str(self.defaultTextBox.text()))
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS
              or isinstance(self.param, ParameterCrs)):
            self.param = ParameterCrs(name,
                                      description,
                                      default=self.selector.crs().authid())
        self.param.optional = not self.requiredCheck.isChecked()
        self.close()

    def cancelPressed(self):
        self.param = None
        self.close()
class ModelerParameterDefinitionDialog(QDialog):
    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(
            settings.value(
                "/Processing/modelParametersDefinitionDialogGeometry",
                QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter Definition'))
        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(20)

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == parameters.PARAMETER_BOOLEAN or \
                isinstance(self.param, QgsProcessingParameterBoolean):
            self.state = QCheckBox()
            self.state.setText(self.tr('Checked'))
            self.state.setChecked(False)
            if self.param is not None:
                self.state.setChecked(bool(self.param.defaultValue()))
            self.verticalLayout.addWidget(self.state)
        elif self.paramType == parameters.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, QgsProcessingParameterField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource,
                                           QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.dataType() is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.dataType() + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.allowMultiple())
            self.verticalLayout.addWidget(self.multipleCheck)

            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setToolTip(
                self.
                tr('Default field name, or ; separated list of field names for multiple field parameters'
                   ))
            if self.param is not None:
                default = self.param.defaultValue()
                if default is not None:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif self.paramType == parameters.PARAMETER_BAND or \
                isinstance(self.param, QgsProcessingParameterBand):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterRasterLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType
              in (parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE)
              or isinstance(self.param, (QgsProcessingParameterFeatureSource,
                                         QgsProcessingParameterVectorLayer))):
            self.verticalLayout.addWidget(QLabel(self.tr('Geometry type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Geometry Not Required'),
                                        QgsProcessing.TypeVector)
            self.shapetypeCombo.addItem(self.tr('Point'),
                                        QgsProcessing.TypeVectorPoint)
            self.shapetypeCombo.addItem(self.tr('Line'),
                                        QgsProcessing.TypeVectorLine)
            self.shapetypeCombo.addItem(self.tr('Polygon'),
                                        QgsProcessing.TypeVectorPolygon)
            self.shapetypeCombo.addItem(self.tr('Any Geometry Type'),
                                        QgsProcessing.TypeVectorAnyGeometry)
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(
                    self.shapetypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType == parameters.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'),
                                       QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(
                self.tr('Vector (No Geometry Required)'),
                QgsProcessing.TypeVector)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'),
                                       QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'),
                                       QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'),
                                       QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'),
                                       QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'),
                                       QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('File'), QgsProcessing.TypeFile)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(
                    self.datatypeCombo.findData(self.param.layerType()))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType == parameters.PARAMETER_NUMBER
              or self.paramType == parameters.PARAMETER_DISTANCE
              or isinstance(self.param, (QgsProcessingParameterNumber,
                                         QgsProcessingParameterDistance))):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.minimum()))
                self.maxTextBox.setText(str(self.param.maximum()))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.defaultValue()
                if self.param.dataType(
                ) == QgsProcessingParameterNumber.Integer:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == parameters.PARAMETER_EXPRESSION
              or isinstance(self.param, QgsProcessingParameterExpression)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultEdit = QgsExpressionLineEdit()
            if self.param is not None:
                self.defaultEdit.setExpression(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultEdit)

            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            self.parentCombo.addItem(self.tr("None"), None)
            idx = 1
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource,
                                           QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType == parameters.PARAMETER_STRING
              or isinstance(self.param, QgsProcessingParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == parameters.PARAMETER_FILE
              or isinstance(self.param, QgsProcessingParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(1 if self.param.behavior(
                ) == QgsProcessingParameterFile.Folder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType == parameters.PARAMETER_POINT
              or isinstance(self.param, QgsProcessingParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == parameters.PARAMETER_CRS
              or isinstance(self.param, QgsProcessingParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.selector = QgsProjectionSelectionWidget()
            if self.param is not None:
                self.selector.setCrs(
                    QgsCoordinateReferenceSystem(self.param.defaultValue()))
            else:
                self.selector.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
            self.verticalLayout.addWidget(self.selector)
        elif self.paramType == parameters.PARAMETER_ENUM or \
                isinstance(self.param, QgsProcessingParameterEnum):
            self.widget = EnumModelerWidget(self)
            if self.param is not None:
                self.widget.setAllowMultiple(bool(self.param.allowMultiple()))
                self.widget.setOptions(self.param.options())
                self.widget.setDefault(self.param.defaultValue())
            self.verticalLayout.addWidget(self.widget)
        elif self.paramType == parameters.PARAMETER_MATRIX or \
                isinstance(self.param, QgsProcessingParameterMatrix):
            self.widget = MatrixModelerWidget(self)
            if self.param is not None:
                self.widget.setValue(self.param.headers(),
                                     self.param.defaultValue())
                self.widget.setFixedRows(self.param.hasFixedNumberRows())
            self.verticalLayout.addWidget(self.widget)

        elif isinstance(self.param, QgsProcessingDestinationParameter):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultWidget = DestinationSelectionPanel(
                self.param, self.alg, default_selection=True)
            self.verticalLayout.addWidget(self.defaultWidget)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(
                not self.param.flags()
                & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        # If child algorithm output is mandatory, disable checkbox
        if isinstance(self.param, QgsProcessingDestinationParameter):
            provider_name, child_name, output_name = self.param.name().split(
                ':')
            child = self.alg.childAlgorithms()['{}:{}'.format(
                provider_name, child_name)]
            model_output = child.modelOutput(output_name)
            param_def = child.algorithm().parameterDefinition(
                model_output.childOutputName())
            if not (param_def.flags()
                    & QgsProcessingParameterDefinition.FlagOptional):
                self.requiredCheck.setEnabled(False)
                self.requiredCheck.setChecked(True)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.verticalLayout.addStretch()
        self.verticalLayout.addWidget(self.buttonBox)

        self.setLayout(self.verticalLayout)

    def accept(self):
        description = self.nameTextBox.text()
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while self.alg.parameterDefinition(name):
                name = safeName.lower() + str(i)
                i += 1
        else:
            name = self.param.name()
        if (self.paramType == parameters.PARAMETER_BOOLEAN
                or isinstance(self.param, QgsProcessingParameterBoolean)):
            self.param = QgsProcessingParameterBoolean(name, description,
                                                       self.state.isChecked())
        elif (self.paramType == parameters.PARAMETER_TABLE_FIELD
              or isinstance(self.param, QgsProcessingParameterField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            default = self.defaultTextBox.text()
            if not default:
                default = None
            self.param = QgsProcessingParameterField(
                name,
                description,
                defaultValue=default,
                parentLayerParameterName=parent,
                type=datatype,
                allowMultiple=self.multipleCheck.isChecked())
        elif (self.paramType == parameters.PARAMETER_BAND
              or isinstance(self.param, QgsProcessingParameterBand)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterBand(name, description, None,
                                                    parent)
        elif (self.paramType == parameters.PARAMETER_MAP_LAYER
              or isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.param = QgsProcessingParameterMapLayer(name, description)
        elif (self.paramType == parameters.PARAMETER_RASTER
              or isinstance(self.param, QgsProcessingParameterRasterLayer)):
            self.param = QgsProcessingParameterRasterLayer(name, description)
        elif (self.paramType == parameters.PARAMETER_TABLE
              or isinstance(self.param, QgsProcessingParameterVectorLayer)):
            self.param = QgsProcessingParameterVectorLayer(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_VECTOR
              or isinstance(self.param, QgsProcessingParameterFeatureSource)):
            self.param = QgsProcessingParameterFeatureSource(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.param = QgsProcessingParameterMultipleLayers(
                name, description, self.datatypeCombo.currentData())
        elif (self.paramType == parameters.PARAMETER_NUMBER or isinstance(
                self.param,
            (QgsProcessingParameterNumber, QgsProcessingParameterDistance))):
            try:
                self.param = QgsProcessingParameterNumber(
                    name, description, QgsProcessingParameterNumber.Double,
                    self.defaultTextBox.text())
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
        elif (self.paramType == parameters.PARAMETER_EXPRESSION
              or isinstance(self.param, QgsProcessingParameterExpression)):
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterExpression(
                name, description, str(self.defaultEdit.expression()), parent)
        elif (self.paramType == parameters.PARAMETER_STRING
              or isinstance(self.param, QgsProcessingParameterString)):
            self.param = QgsProcessingParameterString(
                name, description, str(self.defaultTextBox.text()))
        elif (self.paramType == parameters.PARAMETER_EXTENT
              or isinstance(self.param, QgsProcessingParameterExtent)):
            self.param = QgsProcessingParameterExtent(name, description)
        elif (self.paramType == parameters.PARAMETER_FILE
              or isinstance(self.param, QgsProcessingParameterFile)):
            isFolder = self.fileFolderCombo.currentIndex() == 1
            self.param = QgsProcessingParameterFile(
                name, description, QgsProcessingParameterFile.Folder
                if isFolder else QgsProcessingParameterFile.File)
        elif (self.paramType == parameters.PARAMETER_POINT
              or isinstance(self.param, QgsProcessingParameterPoint)):
            self.param = QgsProcessingParameterPoint(
                name, description, str(self.defaultTextBox.text()))
        elif (self.paramType == parameters.PARAMETER_CRS
              or isinstance(self.param, QgsProcessingParameterCrs)):
            self.param = QgsProcessingParameterCrs(
                name, description,
                self.selector.crs().authid())
        elif (self.paramType == parameters.PARAMETER_ENUM
              or isinstance(self.param, QgsProcessingParameterEnum)):
            self.param = QgsProcessingParameterEnum(
                name, description, self.widget.options(),
                self.widget.allowMultiple(), self.widget.defaultOptions())
        elif (self.paramType == parameters.PARAMETER_MATRIX
              or isinstance(self.param, QgsProcessingParameterMatrix)):
            self.param = QgsProcessingParameterMatrix(
                name,
                description,
                hasFixedNumberRows=self.widget.fixedRows(),
                headers=self.widget.headers(),
                defaultValue=self.widget.value())

        # Destination parameter
        elif (isinstance(self.param, QgsProcessingParameterFeatureSink)):
            self.param = QgsProcessingParameterFeatureSink(
                name=name,
                description=self.param.description(),
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.getValue())
        elif (isinstance(self.param, QgsProcessingParameterFileDestination)):
            self.param = QgsProcessingParameterFileDestination(
                name=name,
                description=self.param.description(),
                fileFilter=self.param.fileFilter(),
                defaultValue=self.defaultWidget.getValue())
        elif (isinstance(self.param, QgsProcessingParameterFolderDestination)):
            self.param = QgsProcessingParameterFolderDestination(
                name=name,
                description=self.param.description(),
                defaultValue=self.defaultWidget.getValue())
        elif (isinstance(self.param, QgsProcessingParameterRasterDestination)):
            self.param = QgsProcessingParameterRasterDestination(
                name=name,
                description=self.param.description(),
                defaultValue=self.defaultWidget.getValue())
        elif (isinstance(self.param, QgsProcessingParameterVectorDestination)):
            self.param = QgsProcessingParameterVectorDestination(
                name=name,
                description=self.param.description(),
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.getValue())

        else:
            if self.paramType:
                typeId = self.paramType
            else:
                typeId = self.param.type()

            paramTypeDef = QgsApplication.instance().processingRegistry(
            ).parameterType(typeId)
            if not paramTypeDef:
                msg = self.tr(
                    'The parameter `{}` is not registered, are you missing a required plugin?'
                    .format(typeId))
                raise UndefinedParameterException(msg)
            self.param = paramTypeDef.create(name)
            self.param.setDescription(description)
            self.param.setMetadata(paramTypeDef.metadata())

        if not self.requiredCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagOptional)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagOptional)

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.reject(self)
class ModelerParameterDefinitionDialog(QDialog):

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(settings.value("/Processing/modelParametersDefinitionDialogGeometry", QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter Definition'))
        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(20)

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == parameters.PARAMETER_BOOLEAN or \
                isinstance(self.param, QgsProcessingParameterBoolean):
            self.state = QCheckBox()
            self.state.setText(self.tr('Checked'))
            self.state.setChecked(False)
            if self.param is not None:
                self.state.setChecked(bool(self.param.defaultValue()))
            self.verticalLayout.addWidget(self.state)
        elif self.paramType == parameters.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, QgsProcessingParameterField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(), definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName() == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.dataType() is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.dataType() + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.allowMultiple())
            self.verticalLayout.addWidget(self.multipleCheck)

            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setToolTip(
                self.tr('Default field name, or ; separated list of field names for multiple field parameters'))
            if self.param is not None:
                default = self.param.defaultValue()
                if default is not None:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif self.paramType == parameters.PARAMETER_BAND or \
                isinstance(self.param, QgsProcessingParameterBand):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(param.parameterName())
                if isinstance(definition, (QgsProcessingParameterRasterLayer)):
                    self.parentCombo.addItem(definition.description(), definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName() == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType in (
                parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE) or
                isinstance(self.param, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer))):
            self.verticalLayout.addWidget(QLabel(self.tr('Geometry type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Geometry Not Required'), QgsProcessing.TypeVector)
            self.shapetypeCombo.addItem(self.tr('Point'), QgsProcessing.TypeVectorPoint)
            self.shapetypeCombo.addItem(self.tr('Line'), QgsProcessing.TypeVectorLine)
            self.shapetypeCombo.addItem(self.tr('Polygon'), QgsProcessing.TypeVectorPolygon)
            self.shapetypeCombo.addItem(self.tr('Any Geometry Type'), QgsProcessing.TypeVectorAnyGeometry)
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(self.shapetypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType == parameters.PARAMETER_MULTIPLE or
              isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'), QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(self.tr('Vector (No Geometry Required)'), QgsProcessing.TypeVector)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'), QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'), QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'), QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'), QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'), QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('File'), QgsProcessing.TypeFile)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(self.datatypeCombo.findData(self.param.layerType()))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType == parameters.PARAMETER_NUMBER or self.paramType == parameters.PARAMETER_DISTANCE or
              isinstance(self.param, (QgsProcessingParameterNumber, QgsProcessingParameterDistance))):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.minimum()))
                self.maxTextBox.setText(str(self.param.maximum()))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.defaultValue()
                if self.param.dataType() == QgsProcessingParameterNumber.Integer:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == parameters.PARAMETER_EXPRESSION or
              isinstance(self.param, QgsProcessingParameterExpression)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultEdit = QgsExpressionLineEdit()
            if self.param is not None:
                self.defaultEdit.setExpression(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultEdit)

            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            self.parentCombo.addItem(self.tr("None"), None)
            idx = 1
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(), definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName() == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType == parameters.PARAMETER_STRING or
              isinstance(self.param, QgsProcessingParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == parameters.PARAMETER_FILE or
              isinstance(self.param, QgsProcessingParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(
                    1 if self.param.behavior() == QgsProcessingParameterFile.Folder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType == parameters.PARAMETER_POINT or
              isinstance(self.param, QgsProcessingParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == parameters.PARAMETER_CRS or
              isinstance(self.param, QgsProcessingParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.selector = QgsProjectionSelectionWidget()
            if self.param is not None:
                self.selector.setCrs(QgsCoordinateReferenceSystem(self.param.defaultValue()))
            else:
                self.selector.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
            self.verticalLayout.addWidget(self.selector)
        elif self.paramType == parameters.PARAMETER_ENUM or \
                isinstance(self.param, QgsProcessingParameterEnum):
            self.widget = EnumModelerWidget(self)
            if self.param is not None:
                self.widget.setAllowMultiple(bool(self.param.allowMultiple()))
                self.widget.setOptions(self.param.options())
                self.widget.setDefault(self.param.defaultValue())
            self.verticalLayout.addWidget(self.widget)
        elif self.paramType == parameters.PARAMETER_MATRIX or \
                isinstance(self.param, QgsProcessingParameterMatrix):
            self.widget = MatrixModelerWidget(self)
            if self.param is not None:
                self.widget.setValue(self.param.defaultValue())
                self.widget.setHeaders(self.param.headers())
                self.widget.setFixedRows(self.param.hasFixedNumberRows())
            self.verticalLayout.addWidget(self.widget)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(not self.param.flags() & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel |
                                          QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.verticalLayout.addStretch()
        self.verticalLayout.addWidget(self.buttonBox)

        self.setLayout(self.verticalLayout)

    def accept(self):
        description = self.nameTextBox.text()
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while self.alg.parameterDefinition(name):
                name = safeName.lower() + str(i)
                i += 1
        else:
            name = self.param.name()
        if (self.paramType == parameters.PARAMETER_BOOLEAN or
                isinstance(self.param, QgsProcessingParameterBoolean)):
            self.param = QgsProcessingParameterBoolean(name, description, self.state.isChecked())
        elif (self.paramType == parameters.PARAMETER_TABLE_FIELD or
              isinstance(self.param, QgsProcessingParameterField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            default = self.defaultTextBox.text()
            if not default:
                default = None
            self.param = QgsProcessingParameterField(name, description, defaultValue=default,
                                                     parentLayerParameterName=parent, type=datatype,
                                                     allowMultiple=self.multipleCheck.isChecked())
        elif (self.paramType == parameters.PARAMETER_BAND or
              isinstance(self.param, QgsProcessingParameterBand)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterBand(name, description, None, parent)
        elif (self.paramType == parameters.PARAMETER_MAP_LAYER or
              isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.param = QgsProcessingParameterMapLayer(
                name, description)
        elif (self.paramType == parameters.PARAMETER_RASTER or
              isinstance(self.param, QgsProcessingParameterRasterLayer)):
            self.param = QgsProcessingParameterRasterLayer(
                name, description)
        elif (self.paramType == parameters.PARAMETER_TABLE or
              isinstance(self.param, QgsProcessingParameterVectorLayer)):
            self.param = QgsProcessingParameterVectorLayer(
                name, description,
                [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_VECTOR or
              isinstance(self.param, QgsProcessingParameterFeatureSource)):
            self.param = QgsProcessingParameterFeatureSource(
                name, description,
                [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_MULTIPLE or
              isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.param = QgsProcessingParameterMultipleLayers(
                name, description,
                self.datatypeCombo.currentData())
        elif (self.paramType == parameters.PARAMETER_NUMBER or
              isinstance(self.param, (QgsProcessingParameterNumber, QgsProcessingParameterDistance))):
            try:
                self.param = QgsProcessingParameterNumber(name, description, QgsProcessingParameterNumber.Double,
                                                          self.defaultTextBox.text())
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
        elif (self.paramType == parameters.PARAMETER_EXPRESSION or
              isinstance(self.param, QgsProcessingParameterExpression)):
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterExpression(name, description,
                                                          str(self.defaultEdit.expression()),
                                                          parent)
        elif (self.paramType == parameters.PARAMETER_STRING or
              isinstance(self.param, QgsProcessingParameterString)):
            self.param = QgsProcessingParameterString(name, description,
                                                      str(self.defaultTextBox.text()))
        elif (self.paramType == parameters.PARAMETER_EXTENT or
              isinstance(self.param, QgsProcessingParameterExtent)):
            self.param = QgsProcessingParameterExtent(name, description)
        elif (self.paramType == parameters.PARAMETER_FILE or
              isinstance(self.param, QgsProcessingParameterFile)):
            isFolder = self.fileFolderCombo.currentIndex() == 1
            self.param = QgsProcessingParameterFile(name, description,
                                                    QgsProcessingParameterFile.Folder if isFolder else QgsProcessingParameterFile.File)
        elif (self.paramType == parameters.PARAMETER_POINT or
              isinstance(self.param, QgsProcessingParameterPoint)):
            self.param = QgsProcessingParameterPoint(name, description,
                                                     str(self.defaultTextBox.text()))
        elif (self.paramType == parameters.PARAMETER_CRS or
              isinstance(self.param, QgsProcessingParameterCrs)):
            self.param = QgsProcessingParameterCrs(name, description, self.selector.crs().authid())
        elif (self.paramType == parameters.PARAMETER_ENUM or
                isinstance(self.param, QgsProcessingParameterEnum)):
            self.param = QgsProcessingParameterEnum(name, description, self.widget.options(), self.widget.allowMultiple(), self.widget.defaultOptions())
        elif (self.paramType == parameters.PARAMETER_MATRIX or
                isinstance(self.param, QgsProcessingParameterMatrix)):
            self.param = QgsProcessingParameterMatrix(name, description, hasFixedNumberRows=self.widget.fixedRows(), headers=self.widget.headers(), defaultValue=self.widget.value())
        else:
            if self.paramType:
                typeId = self.paramType
            else:
                typeId = self.param.type()

            paramTypeDef = QgsApplication.instance().processingRegistry().parameterType(typeId)
            if not paramTypeDef:
                msg = self.tr('The parameter `{}` is not registered, are you missing a required plugin?'.format(typeId))
                raise UndefinedParameterException(msg)
            self.param = paramTypeDef.create(name)
            self.param.setDescription(description)
            self.param.setMetadata(paramTypeDef.metadata())

        if not self.requiredCheck.isChecked():
            self.param.setFlags(self.param.flags() | QgsProcessingParameterDefinition.FlagOptional)

        settings = QgsSettings()
        settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry())

        QDialog.reject(self)
class ModelerParameterDefinitionDialog(QDialog):
    @staticmethod
    def use_legacy_dialog(param=None, paramType=None):
        if isinstance(param, QgsProcessingDestinationParameter):
            return True

        # yay, use new API!
        return False

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(
            settings.value(
                "/Processing/modelParametersDefinitionDialogGeometry",
                QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def switchToCommentTab(self):
        self.tab.setCurrentIndex(1)
        self.commentEdit.setFocus()
        self.commentEdit.selectAll()

    def setupUi(self):
        type_metadata = QgsApplication.processingRegistry().parameterType(
            self.param.type() if self.param else self.paramType)
        self.setWindowTitle(
            self.tr('{} Parameter Definition').format(type_metadata.name()))

        self.mainLayout = QVBoxLayout()
        self.tab = QTabWidget()
        self.mainLayout.addWidget(self.tab)

        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout()

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if isinstance(self.param, QgsProcessingDestinationParameter):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultWidget = QgsProcessingLayerOutputDestinationWidget(
                self.param, defaultSelection=True)
            self.verticalLayout.addWidget(self.defaultWidget)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(
                not self.param.flags()
                & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.advancedCheck = QCheckBox()
        self.advancedCheck.setText(self.tr('Advanced'))
        self.advancedCheck.setChecked(False)
        if self.param is not None:
            self.advancedCheck.setChecked(
                self.param.flags()
                & QgsProcessingParameterDefinition.FlagAdvanced)
        self.verticalLayout.addWidget(self.advancedCheck)

        # If child algorithm output is mandatory, disable checkbox
        if isinstance(self.param, QgsProcessingDestinationParameter):
            child = self.alg.childAlgorithms()[self.param.metadata()
                                               ['_modelChildId']]
            model_output = child.modelOutput(
                self.param.metadata()['_modelChildOutputName'])
            param_def = child.algorithm().parameterDefinition(
                model_output.childOutputName())
            if not (param_def.flags()
                    & QgsProcessingParameterDefinition.FlagOptional):
                self.requiredCheck.setEnabled(False)
                self.requiredCheck.setChecked(True)

            self.advancedCheck.setEnabled(False)
            self.advancedCheck.setChecked(False)

        self.verticalLayout.addStretch()

        w = QWidget()
        w.setLayout(self.verticalLayout)
        self.tab.addTab(w, self.tr('Properties'))

        self.commentLayout = QVBoxLayout()
        self.commentEdit = QTextEdit()
        self.commentEdit.setAcceptRichText(False)
        self.commentLayout.addWidget(self.commentEdit, 1)

        hl = QHBoxLayout()
        hl.setContentsMargins(0, 0, 0, 0)
        hl.addWidget(QLabel(self.tr('Color')))
        self.comment_color_button = QgsColorButton()
        self.comment_color_button.setAllowOpacity(True)
        self.comment_color_button.setWindowTitle(self.tr('Comment Color'))
        self.comment_color_button.setShowNull(True, self.tr('Default'))
        hl.addWidget(self.comment_color_button)
        self.commentLayout.addLayout(hl)

        w2 = QWidget()
        w2.setLayout(self.commentLayout)
        self.tab.addTab(w2, self.tr('Comments'))

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.mainLayout.addWidget(self.buttonBox)

        self.setLayout(self.mainLayout)

    def setComments(self, text):
        self.commentEdit.setPlainText(text)

    def comments(self):
        return self.commentEdit.toPlainText()

    def setCommentColor(self, color):
        if color.isValid():
            self.comment_color_button.setColor(color)
        else:
            self.comment_color_button.setToNull()

    def commentColor(self):
        return self.comment_color_button.color(
        ) if not self.comment_color_button.isNull() else QColor()

    def accept(self):
        description = self.nameTextBox.text()
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return

        validChars = \
            'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
        safeName = ''.join(c for c in description if c in validChars)
        name = safeName.lower()

        # Destination parameter
        if (isinstance(self.param, QgsProcessingParameterFeatureSink)):
            self.param = QgsProcessingParameterFeatureSink(
                name=name,
                description=description,
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFileDestination)):
            self.param = QgsProcessingParameterFileDestination(
                name=name,
                description=description,
                fileFilter=self.param.fileFilter(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFolderDestination)):
            self.param = QgsProcessingParameterFolderDestination(
                name=name,
                description=description,
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterRasterDestination)):
            self.param = QgsProcessingParameterRasterDestination(
                name=name,
                description=description,
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterVectorDestination)):
            self.param = QgsProcessingParameterVectorDestination(
                name=name,
                description=description,
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())

        else:
            if self.paramType:
                typeId = self.paramType
            else:
                typeId = self.param.type()

            paramTypeDef = QgsApplication.instance().processingRegistry(
            ).parameterType(typeId)
            if not paramTypeDef:
                msg = self.tr(
                    'The parameter `{}` is not registered, are you missing a required plugin?'
                    .format(typeId))
                raise UndefinedParameterException(msg)
            self.param = paramTypeDef.create(name)
            self.param.setDescription(description)
            self.param.setMetadata(paramTypeDef.metadata())

        if not self.requiredCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagOptional)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagOptional)

        if self.advancedCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagAdvanced)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagAdvanced)

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.reject(self)
class ModelerParameterDefinitionDialog(QDialog):
    PARAMETER_NUMBER = 'Number'
    PARAMETER_RASTER = 'Raster Layer'
    PARAMETER_TABLE = 'Vector Layer'
    PARAMETER_VECTOR = 'Vector Features'
    PARAMETER_STRING = 'String'
    PARAMETER_EXPRESSION = 'Expression'
    PARAMETER_BOOLEAN = 'Boolean'
    PARAMETER_TABLE_FIELD = 'Vector Field'
    PARAMETER_EXTENT = 'Extent'
    PARAMETER_FILE = 'File'
    PARAMETER_POINT = 'Point'
    PARAMETER_CRS = 'CRS'
    PARAMETER_MULTIPLE = 'Multiple Input'
    PARAMETER_BAND = 'Raster Band'
    PARAMETER_MAP_LAYER = 'Map Layer'

    paramTypes = [
        PARAMETER_BOOLEAN,
        PARAMETER_EXTENT,
        PARAMETER_FILE,
        PARAMETER_NUMBER,
        PARAMETER_RASTER,
        PARAMETER_STRING,
        PARAMETER_EXPRESSION,
        PARAMETER_MAP_LAYER,
        PARAMETER_TABLE,
        PARAMETER_TABLE_FIELD,
        PARAMETER_VECTOR,
        PARAMETER_POINT,
        PARAMETER_CRS,
        PARAMETER_MULTIPLE,
        PARAMETER_BAND
    ]

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(settings.value("/Processing/modelParametersDefinitionDialogGeometry", QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter Definition'))
        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setMargin(20)

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or \
                isinstance(self.param, QgsProcessingParameterBoolean):
            self.state = QCheckBox()
            self.state.setText(self.tr('Checked'))
            self.state.setChecked(False)
            if self.param is not None:
                self.state.setChecked(bool(self.param.defaultValue()))
            self.verticalLayout.addWidget(self.state)
        elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, QgsProcessingParameterField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(), definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName() == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.dataType() is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.dataType() + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.allowMultiple())
            self.verticalLayout.addWidget(self.multipleCheck)

            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setToolTip(
                self.tr('Default field name, or ; separated list of field names for multiple field parameters'))
            if self.param is not None:
                default = self.param.defaultValue()
                if default is not None:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BAND or \
                isinstance(self.param, QgsProcessingParameterBand):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(param.parameterName())
                if isinstance(definition, (QgsProcessingParameterRasterLayer)):
                    self.parentCombo.addItem(definition.description(), definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName() == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType in (
                ModelerParameterDefinitionDialog.PARAMETER_VECTOR, ModelerParameterDefinitionDialog.PARAMETER_TABLE) or
                isinstance(self.param, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer))):
            self.verticalLayout.addWidget(QLabel(self.tr('Geometry type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Geometry Not Required'), QgsProcessing.TypeVector)
            self.shapetypeCombo.addItem(self.tr('Point'), QgsProcessing.TypeVectorPoint)
            self.shapetypeCombo.addItem(self.tr('Line'), QgsProcessing.TypeVectorLine)
            self.shapetypeCombo.addItem(self.tr('Polygon'), QgsProcessing.TypeVectorPolygon)
            self.shapetypeCombo.addItem(self.tr('Any Geometry Type'), QgsProcessing.TypeVectorAnyGeometry)
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(self.shapetypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE or
              isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'), QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(self.tr('Vector (No Geometry Required)'), QgsProcessing.TypeVector)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'), QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'), QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'), QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'), QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'), QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('File'), QgsProcessing.TypeFile)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(self.datatypeCombo.findData(self.param.layerType()))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_NUMBER or
              isinstance(self.param, QgsProcessingParameterNumber)):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.minimum()))
                self.maxTextBox.setText(str(self.param.maximum()))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.defaultValue()
                if self.param.dataType() == QgsProcessingParameterNumber.Integer:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION or
              isinstance(self.param, QgsProcessingParameterExpression)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultEdit = QgsExpressionLineEdit()
            if self.param is not None:
                self.defaultEdit.setExpression(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultEdit)

            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            self.parentCombo.addItem(self.tr("None"), None)
            idx = 1
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(), definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName() == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_STRING or
              isinstance(self.param, QgsProcessingParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE or
              isinstance(self.param, QgsProcessingParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(
                    1 if self.param.behavior() == QgsProcessingParameterFile.Folder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_POINT or
              isinstance(self.param, QgsProcessingParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.defaultValue())
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS or
              isinstance(self.param, QgsProcessingParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.selector = QgsProjectionSelectionWidget()
            if self.param is not None:
                self.selector.setCrs(QgsCoordinateReferenceSystem(self.param.defaultValue()))
            else:
                self.selector.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
            self.verticalLayout.addWidget(self.selector)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(not self.param.flags() & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel |
                                          QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.verticalLayout.addStretch()
        self.verticalLayout.addWidget(self.buttonBox)

        self.setLayout(self.verticalLayout)

    def accept(self):
        description = str(self.nameTextBox.text())
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while self.alg.parameterDefinition(name):
                name = safeName.lower() + str(i)
                i += 1
        else:
            name = self.param.name()
        if (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN or
                isinstance(self.param, QgsProcessingParameterBoolean)):
            self.param = QgsProcessingParameterBoolean(name, description, self.state.isChecked())
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD or
              isinstance(self.param, QgsProcessingParameterField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            default = self.defaultTextBox.text()
            if not default:
                default = None
            self.param = QgsProcessingParameterField(name, description, defaultValue=default,
                                                     parentLayerParameterName=parent, type=datatype,
                                                     allowMultiple=self.multipleCheck.isChecked())
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_BAND or
              isinstance(self.param, QgsProcessingParameterBand)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterBand(name, description, None, parent)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_MAP_LAYER or
              isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.param = QgsProcessingParameterMapLayer(
                name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_RASTER or
              isinstance(self.param, QgsProcessingParameterRasterLayer)):
            self.param = QgsProcessingParameterRasterLayer(
                name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_TABLE or
              isinstance(self.param, QgsProcessingParameterVectorLayer)):
            self.param = QgsProcessingParameterVectorLayer(
                name, description,
                [self.shapetypeCombo.currentData()])
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_VECTOR or
              isinstance(self.param, QgsProcessingParameterFeatureSource)):
            self.param = QgsProcessingParameterFeatureSource(
                name, description,
                [self.shapetypeCombo.currentData()])
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE or
              isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.param = QgsProcessingParameterMultipleLayers(
                name, description,
                self.datatypeCombo.currentData())
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_NUMBER or
              isinstance(self.param, QgsProcessingParameterNumber)):
            try:
                self.param = QgsProcessingParameterNumber(name, description, QgsProcessingParameterNumber.Double,
                                                          self.defaultTextBox.text())
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                    self.tr('Wrong or missing parameter values'))
                return
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION or
              isinstance(self.param, QgsProcessingParameterExpression)):
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterExpression(name, description,
                                                          str(self.defaultEdit.expression()),
                                                          parent)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_STRING or
              isinstance(self.param, QgsProcessingParameterString)):
            self.param = QgsProcessingParameterString(name, description,
                                                      str(self.defaultTextBox.text()))
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_EXTENT or
              isinstance(self.param, QgsProcessingParameterExtent)):
            self.param = QgsProcessingParameterExtent(name, description)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE or
              isinstance(self.param, QgsProcessingParameterFile)):
            isFolder = self.fileFolderCombo.currentIndex() == 1
            self.param = QgsProcessingParameterFile(name, description,
                                                    QgsProcessingParameterFile.Folder if isFolder else QgsProcessingParameterFile.File)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_POINT or
              isinstance(self.param, QgsProcessingParameterPoint)):
            self.param = QgsProcessingParameterPoint(name, description,
                                                     str(self.defaultTextBox.text()))
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS or
              isinstance(self.param, QgsProcessingParameterCrs)):
            self.param = QgsProcessingParameterCrs(name, description, self.selector.crs().authid())
        if not self.requiredCheck.isChecked():
            self.param.setFlags(self.param.flags() | QgsProcessingParameterDefinition.FlagOptional)

        settings = QgsSettings()
        settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry())

        QDialog.reject(self)

    @staticmethod
    def inputTooltip(input_type):
        tooltips = {
            ModelerParameterDefinitionDialog.PARAMETER_NUMBER: QCoreApplication.translate('Processing', 'A numeric parameter, including float or integer values.'),
            ModelerParameterDefinitionDialog.PARAMETER_RASTER: QCoreApplication.translate('Processing', 'A raster layer parameter.'),
            ModelerParameterDefinitionDialog.PARAMETER_TABLE: QCoreApplication.translate('Processing', 'A vector layer parameter, e.g. for algorithms which change layer styles, edit layers in place, or other operations which affect an entire layer.'),
            ModelerParameterDefinitionDialog.PARAMETER_VECTOR: QCoreApplication.translate('Processing', 'A vector feature parameter, e.g. for algorithms which operate on the features within a layer.'),
            ModelerParameterDefinitionDialog.PARAMETER_STRING: QCoreApplication.translate('Processing', 'A freeform string parameter.'),
            ModelerParameterDefinitionDialog.PARAMETER_EXPRESSION: QCoreApplication.translate('Processing', 'A QGIS expression parameter, which presents an expression builder widget to users.'),
            ModelerParameterDefinitionDialog.PARAMETER_BOOLEAN: QCoreApplication.translate('Processing', 'A boolean parameter, for true/false values.'),
            ModelerParameterDefinitionDialog.PARAMETER_TABLE_FIELD: QCoreApplication.translate('Processing', 'A vector field parameter, for selecting an existing field from a vector source.'),
            ModelerParameterDefinitionDialog.PARAMETER_EXTENT: QCoreApplication.translate('Processing', 'A map extent parameter.'),
            ModelerParameterDefinitionDialog.PARAMETER_FILE: QCoreApplication.translate('Processing', 'A file parameter, for use with non-map layer file sources.'),
            ModelerParameterDefinitionDialog.PARAMETER_POINT: QCoreApplication.translate('Processing', 'A geographic point parameter.'),
            ModelerParameterDefinitionDialog.PARAMETER_CRS: QCoreApplication.translate('Processing', 'A coordinate reference system (CRS) input parameter.'),
            ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE: QCoreApplication.translate('Processing', 'An input allowing selection of multiple sources, including multiple map layers or file sources.'),
            ModelerParameterDefinitionDialog.PARAMETER_BAND: QCoreApplication.translate('Processing', 'A raster band parameter, for selecting an existing band from a raster source.'),
            ModelerParameterDefinitionDialog.PARAMETER_MAP_LAYER: QCoreApplication.translate('Processing', 'A generic map layer parameter, which accepts either vector or raster layers.')
        }
        return tooltips[input_type]
class ModelerParameterDefinitionDialog(QDialog):
    @staticmethod
    def use_legacy_dialog(param=None, paramType=None):
        if paramType in (parameters.PARAMETER_TABLE_FIELD,
                         parameters.PARAMETER_BAND,
                         parameters.PARAMETER_VECTOR,
                         parameters.PARAMETER_TABLE,
                         parameters.PARAMETER_MULTIPLE,
                         parameters.PARAMETER_NUMBER,
                         parameters.PARAMETER_DISTANCE,
                         parameters.PARAMETER_SCALE,
                         parameters.PARAMETER_MAP_LAYER):
            return True
        elif isinstance(
                param,
            (QgsProcessingParameterField, QgsProcessingParameterBand,
             QgsProcessingParameterFeatureSource,
             QgsProcessingParameterVectorLayer,
             QgsProcessingParameterMultipleLayers,
             QgsProcessingParameterNumber, QgsProcessingParameterDistance,
             QgsProcessingParameterScale, QgsProcessingParameterMapLayer,
             QgsProcessingDestinationParameter)):
            return True

        # yay, use new API!
        return False

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(
            settings.value(
                "/Processing/modelParametersDefinitionDialogGeometry",
                QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def switchToCommentTab(self):
        self.tab.setCurrentIndex(1)
        self.commentEdit.setFocus()
        self.commentEdit.selectAll()

    def setupUi(self):
        type_metadata = QgsApplication.processingRegistry().parameterType(
            self.param.type() if self.param else self.paramType)
        self.setWindowTitle(
            self.tr('{} Parameter Definition').format(type_metadata.name()))

        self.mainLayout = QVBoxLayout()
        self.tab = QTabWidget()
        self.mainLayout.addWidget(self.tab)

        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout()

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == parameters.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, QgsProcessingParameterField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource,
                                           QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.dataType() is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.dataType() + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.allowMultiple())
            self.verticalLayout.addWidget(self.multipleCheck)

            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setToolTip(
                self.
                tr('Default field name, or ; separated list of field names for multiple field parameters'
                   ))
            if self.param is not None:
                default = self.param.defaultValue()
                if default is not None:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif self.paramType == parameters.PARAMETER_BAND or \
                isinstance(self.param, QgsProcessingParameterBand):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterRasterLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType
              in (parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE)
              or isinstance(self.param, (QgsProcessingParameterFeatureSource,
                                         QgsProcessingParameterVectorLayer))):
            self.verticalLayout.addWidget(QLabel(self.tr('Geometry type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Geometry Not Required'),
                                        QgsProcessing.TypeVector)
            self.shapetypeCombo.addItem(self.tr('Point'),
                                        QgsProcessing.TypeVectorPoint)
            self.shapetypeCombo.addItem(self.tr('Line'),
                                        QgsProcessing.TypeVectorLine)
            self.shapetypeCombo.addItem(self.tr('Polygon'),
                                        QgsProcessing.TypeVectorPolygon)
            self.shapetypeCombo.addItem(self.tr('Any Geometry Type'),
                                        QgsProcessing.TypeVectorAnyGeometry)
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(
                    self.shapetypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType == parameters.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'),
                                       QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(
                self.tr('Vector (No Geometry Required)'),
                QgsProcessing.TypeVector)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'),
                                       QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'),
                                       QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'),
                                       QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'),
                                       QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'),
                                       QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('File'), QgsProcessing.TypeFile)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(
                    self.datatypeCombo.findData(self.param.layerType()))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType == parameters.PARAMETER_MAP_LAYER
              or isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'),
                                       QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'),
                                       QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'),
                                       QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'),
                                       QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'),
                                       QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'),
                                       QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('Mesh'), QgsProcessing.TypeMesh)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(
                    self.datatypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType
              in (parameters.PARAMETER_NUMBER, parameters.PARAMETER_DISTANCE,
                  parameters.PARAMETER_SCALE)
              or isinstance(self.param, (QgsProcessingParameterNumber,
                                         QgsProcessingParameterDistance,
                                         QgsProcessingParameterScale))):

            if (self.paramType == parameters.PARAMETER_DISTANCE
                    or isinstance(self.param, QgsProcessingParameterDistance)):
                self.verticalLayout.addWidget(QLabel(self.tr('Linked input')))
                self.parentCombo = QComboBox()
                self.parentCombo.addItem('', '')
                idx = 1
                for param in list(self.alg.parameterComponents().values()):
                    definition = self.alg.parameterDefinition(
                        param.parameterName())
                    if isinstance(definition,
                                  (QgsProcessingParameterFeatureSource,
                                   QgsProcessingParameterVectorLayer,
                                   QgsProcessingParameterMapLayer,
                                   QgsProcessingParameterCrs)):
                        self.parentCombo.addItem(definition.description(),
                                                 definition.name())
                        if self.param is not None:
                            if self.param.parentParameterName(
                            ) == definition.name():
                                self.parentCombo.setCurrentIndex(idx)
                        idx += 1
                self.verticalLayout.addWidget(self.parentCombo)
            elif (self.paramType != parameters.PARAMETER_SCALE
                  and not isinstance(self.param, QgsProcessingParameterScale)):
                self.verticalLayout.addWidget(QLabel(self.tr('Number type')))
                self.type_combo = QComboBox()
                self.type_combo.addItem(self.tr('Float'),
                                        QgsProcessingParameterNumber.Double)
                self.type_combo.addItem(self.tr('Integer'),
                                        QgsProcessingParameterNumber.Integer)
                if self.param:
                    self.type_combo.setCurrentIndex(
                        self.type_combo.findData(self.param.dataType()))
                self.verticalLayout.addWidget(self.type_combo)

            if (self.paramType != parameters.PARAMETER_SCALE and
                    not isinstance(self.param, QgsProcessingParameterScale)):
                self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
                self.minTextBox = QLineEdit()
                self.verticalLayout.addWidget(self.minTextBox)
                self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
                self.maxTextBox = QLineEdit()
                self.verticalLayout.addWidget(self.maxTextBox)
                if self.param is not None:
                    self.minTextBox.setText(str(self.param.minimum()))
                    self.maxTextBox.setText(str(self.param.maximum()))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.defaultValue()
                if self.param.dataType(
                ) == QgsProcessingParameterNumber.Integer:
                    default = int(math.floor(float(default)))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif isinstance(self.param, QgsProcessingDestinationParameter):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultWidget = QgsProcessingLayerOutputDestinationWidget(
                self.param, defaultSelection=True)
            self.verticalLayout.addWidget(self.defaultWidget)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(
                not self.param.flags()
                & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.advancedCheck = QCheckBox()
        self.advancedCheck.setText(self.tr('Advanced'))
        self.advancedCheck.setChecked(False)
        if self.param is not None:
            self.advancedCheck.setChecked(
                self.param.flags()
                & QgsProcessingParameterDefinition.FlagAdvanced)
        self.verticalLayout.addWidget(self.advancedCheck)

        # If child algorithm output is mandatory, disable checkbox
        if isinstance(self.param, QgsProcessingDestinationParameter):
            provider_name, child_name, output_name = self.param.name().split(
                ':')
            child = self.alg.childAlgorithms()['{}:{}'.format(
                provider_name, child_name)]
            model_output = child.modelOutput(output_name)
            param_def = child.algorithm().parameterDefinition(
                model_output.childOutputName())
            if not (param_def.flags()
                    & QgsProcessingParameterDefinition.FlagOptional):
                self.requiredCheck.setEnabled(False)
                self.requiredCheck.setChecked(True)

            self.advancedCheck.setEnabled(False)
            self.advancedCheck.setChecked(False)

        self.verticalLayout.addStretch()

        w = QWidget()
        w.setLayout(self.verticalLayout)
        self.tab.addTab(w, self.tr('Properties'))

        self.commentLayout = QVBoxLayout()
        self.commentEdit = QTextEdit()
        self.commentEdit.setAcceptRichText(False)
        self.commentLayout.addWidget(self.commentEdit, 1)

        hl = QHBoxLayout()
        hl.setContentsMargins(0, 0, 0, 0)
        hl.addWidget(QLabel(self.tr('Color')))
        self.comment_color_button = QgsColorButton()
        self.comment_color_button.setAllowOpacity(True)
        self.comment_color_button.setWindowTitle(self.tr('Comment Color'))
        self.comment_color_button.setShowNull(True, self.tr('Default'))
        hl.addWidget(self.comment_color_button)
        self.commentLayout.addLayout(hl)

        w2 = QWidget()
        w2.setLayout(self.commentLayout)
        self.tab.addTab(w2, self.tr('Comments'))

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.mainLayout.addWidget(self.buttonBox)

        self.setLayout(self.mainLayout)

    def setComments(self, text):
        self.commentEdit.setPlainText(text)

    def comments(self):
        return self.commentEdit.toPlainText()

    def setCommentColor(self, color):
        if color.isValid():
            self.comment_color_button.setColor(color)
        else:
            self.comment_color_button.setToNull()

    def commentColor(self):
        return self.comment_color_button.color(
        ) if not self.comment_color_button.isNull() else QColor()

    def accept(self):
        description = self.nameTextBox.text()
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while self.alg.parameterDefinition(name):
                name = safeName.lower() + str(i)
                i += 1
        else:
            name = self.param.name()
        if (self.paramType == parameters.PARAMETER_TABLE_FIELD
                or isinstance(self.param, QgsProcessingParameterField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            default = self.defaultTextBox.text()
            if not default:
                default = None
            self.param = QgsProcessingParameterField(
                name,
                description,
                defaultValue=default,
                parentLayerParameterName=parent,
                type=datatype,
                allowMultiple=self.multipleCheck.isChecked())
        elif (self.paramType == parameters.PARAMETER_BAND
              or isinstance(self.param, QgsProcessingParameterBand)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterBand(name, description, None,
                                                    parent)
        elif (self.paramType == parameters.PARAMETER_MAP_LAYER
              or isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.param = QgsProcessingParameterMapLayer(
                name, description, types=[self.datatypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_RASTER
              or isinstance(self.param, QgsProcessingParameterRasterLayer)):
            self.param = QgsProcessingParameterRasterLayer(name, description)
        elif (self.paramType == parameters.PARAMETER_TABLE
              or isinstance(self.param, QgsProcessingParameterVectorLayer)):
            self.param = QgsProcessingParameterVectorLayer(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_VECTOR
              or isinstance(self.param, QgsProcessingParameterFeatureSource)):
            self.param = QgsProcessingParameterFeatureSource(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.param = QgsProcessingParameterMultipleLayers(
                name, description, self.datatypeCombo.currentData())
        elif (self.paramType == parameters.PARAMETER_DISTANCE
              or isinstance(self.param, QgsProcessingParameterDistance)):
            self.param = QgsProcessingParameterDistance(
                name, description, self.defaultTextBox.text())
            try:
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return

            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            if parent:
                self.param.setParentParameterName(parent)
        elif (self.paramType == parameters.PARAMETER_SCALE
              or isinstance(self.param, QgsProcessingParameterScale)):
            self.param = QgsProcessingParameterScale(
                name, description, self.defaultTextBox.text())
        elif (self.paramType == parameters.PARAMETER_NUMBER
              or isinstance(self.param, QgsProcessingParameterNumber)):

            type = self.type_combo.currentData()
            self.param = QgsProcessingParameterNumber(
                name, description, type, self.defaultTextBox.text())
            try:
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return

        # Destination parameter
        elif (isinstance(self.param, QgsProcessingParameterFeatureSink)):
            self.param = QgsProcessingParameterFeatureSink(
                name=name,
                description=self.param.description(),
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFileDestination)):
            self.param = QgsProcessingParameterFileDestination(
                name=name,
                description=self.param.description(),
                fileFilter=self.param.fileFilter(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFolderDestination)):
            self.param = QgsProcessingParameterFolderDestination(
                name=name,
                description=self.param.description(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterRasterDestination)):
            self.param = QgsProcessingParameterRasterDestination(
                name=name,
                description=self.param.description(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterVectorDestination)):
            self.param = QgsProcessingParameterVectorDestination(
                name=name,
                description=self.param.description(),
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())

        else:
            if self.paramType:
                typeId = self.paramType
            else:
                typeId = self.param.type()

            paramTypeDef = QgsApplication.instance().processingRegistry(
            ).parameterType(typeId)
            if not paramTypeDef:
                msg = self.tr(
                    'The parameter `{}` is not registered, are you missing a required plugin?'
                    .format(typeId))
                raise UndefinedParameterException(msg)
            self.param = paramTypeDef.create(name)
            self.param.setDescription(description)
            self.param.setMetadata(paramTypeDef.metadata())

        if not self.requiredCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagOptional)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagOptional)

        if self.advancedCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagAdvanced)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagAdvanced)

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.reject(self)