示例#1
0
    def update_from_layers(self, is_new=False):
        layers = QgsProject.instance().mapLayers()
        n = 0
        for name, layer in layers.items():

            if layer.name() == "Mask":
                continue
            # skip non vector layers
            if not isinstance(layer, QgsVectorLayer):
                continue

            # skip layers without labels
            if layer.labeling() is None:
                continue

            do_limit = False
            did_limit = layer.id() in self.limited
            do_limit = mask_filter.has_mask_filter(layer)

            if do_limit and not did_limit:
                self.limited.append(layer.id())
            if not do_limit and did_limit:
                self.limited.remove(layer.id())

            self.ui.layerTable.insertRow(n)
            name_item = QTableWidgetItem()
            name_item.setData(Qt.DisplayRole, layer.name())
            self.ui.layerTable.setItem(n, 1, name_item)
            w = QCheckBox(self.ui.layerTable)
            w.setEnabled(layer.labeling() is not None)
            w.setChecked(do_limit or is_new)
            self.ui.layerTable.setCellWidget(n, 0, w)
            item = QTableWidgetItem()
            item.setData(Qt.UserRole, layer)
            self.ui.layerTable.setItem(n, 0, item)
            n += 1

        self.ui.selectAllBtn.setEnabled(n != 0)
        self.ui.unselectAllBtn.setEnabled(n != 0)
示例#2
0
    def set_show_matrices(self):
        self.tbl_array_cores.clear()
        if self.chb_use_all_matrices.isChecked():
            self.resize(383, 385)
            self.setMaximumSize(QtCore.QSize(383, 385))
        else:
            self.setMaximumSize(QtCore.QSize(710, 385))
            self.resize(710, 385)
            self.tbl_array_cores.setColumnWidth(0, 200)
            self.tbl_array_cores.setColumnWidth(1, 80)
            self.tbl_array_cores.setHorizontalHeaderLabels(["Matrix", "Use?"])

            if self.matrix is not None:
                table = self.tbl_array_cores
                table.setRowCount(self.matrix.cores)
                for i, mat in enumerate(self.matrix.names):
                    item1 = QTableWidgetItem(mat)
                    item1.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                    table.setItem(i, 0, item1)

                    chb1 = QCheckBox()
                    chb1.setChecked(True)
                    chb1.setEnabled(True)
                    table.setCellWidget(i, 1, self.centers_item(chb1))
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)
示例#4
0
    def initWidgets(self):
        # If there are advanced parameters — show corresponding groupbox
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                self.grpAdvanced.show()
                break

        widget_context = QgsProcessingParameterWidgetContext()
        widget_context.setProject(QgsProject.instance())
        if iface is not None:
            widget_context.setMapCanvas(iface.mapCanvas())
        if isinstance(self.alg, QgsProcessingModelAlgorithm):
            widget_context.setModel(self.alg)

        # Create widgets and put them in layouts
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if param.isDestination():
                continue
            else:
                wrapper = WidgetWrapperFactory.create_wrapper(
                    param, self.parent)
                wrapper.setWidgetContext(widget_context)
                wrapper.registerProcessingContextGenerator(
                    self.context_generator)
                self.wrappers[param.name()] = wrapper

                # For compatibility with 3.x API, we need to check whether the wrapper is
                # the deprecated WidgetWrapper class. If not, it's the newer
                # QgsAbstractProcessingParameterWidgetWrapper class
                # TODO QGIS 4.0 - remove
                is_python_wrapper = issubclass(wrapper.__class__,
                                               WidgetWrapper)
                if not is_python_wrapper:
                    widget = wrapper.createWrappedWidget(
                        self.processing_context)
                else:
                    widget = wrapper.widget

                if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                    # don't show the input/output parameter widgets in in-place mode
                    # we still need to CREATE them, because other wrappers may need to interact
                    # with them (e.g. those parameters which need the input layer for field
                    # selections/crs properties/etc)
                    continue

                if widget is not None:
                    if is_python_wrapper:
                        widget.setToolTip(param.toolTip())

                    if isinstance(param, QgsProcessingParameterFeatureSource):
                        layout = QHBoxLayout()
                        layout.setSpacing(6)
                        layout.setMargin(0)
                        layout.addWidget(widget)
                        button = QToolButton()
                        icon = QIcon(
                            os.path.join(pluginPath, 'images', 'iterate.png'))
                        button.setIcon(icon)
                        button.setSizePolicy(QSizePolicy.Fixed,
                                             QSizePolicy.Expanding)
                        button.setToolTip(
                            self.
                            tr('Iterate over this layer, creating a separate output for every feature in the layer'
                               ))
                        button.setCheckable(True)
                        layout.addWidget(button)
                        layout.setAlignment(button, Qt.AlignTop)
                        self.iterateButtons[param.name()] = button
                        button.toggled.connect(self.buttonToggled)
                        widget = QWidget()
                        widget.setLayout(layout)

                    label = None
                    if not is_python_wrapper:
                        label = wrapper.createWrappedLabel()
                    else:
                        label = wrapper.label

                    if label is not None:
                        if param.flags(
                        ) & QgsProcessingParameterDefinition.FlagAdvanced:
                            self.layoutAdvanced.addWidget(label)
                        else:
                            self.layoutMain.insertWidget(
                                self.layoutMain.count() - 2, label)
                    elif is_python_wrapper:
                        desc = param.description()
                        if isinstance(param, QgsProcessingParameterExtent):
                            desc += self.tr(' (xmin, xmax, ymin, ymax)')
                        if isinstance(param, QgsProcessingParameterPoint):
                            desc += self.tr(' (x, y)')
                        if param.flags(
                        ) & QgsProcessingParameterDefinition.FlagOptional:
                            desc += self.tr(' [optional]')
                        widget.setText(desc)
                    if param.flags(
                    ) & QgsProcessingParameterDefinition.FlagAdvanced:
                        self.layoutAdvanced.addWidget(widget)
                    else:
                        self.layoutMain.insertWidget(
                            self.layoutMain.count() - 2, widget)

        for output in self.alg.destinationParameterDefinitions():
            if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                continue

            label = QLabel(output.description())
            widget = DestinationSelectionPanel(output, self.alg)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
            if isinstance(output, (QgsProcessingParameterRasterDestination,
                                   QgsProcessingParameterFeatureSink,
                                   QgsProcessingParameterVectorDestination)):
                check = QCheckBox()
                check.setText(
                    QCoreApplication.translate(
                        'ParametersPanel',
                        'Open output file after running algorithm'))

                def skipOutputChanged(checkbox, skipped):
                    checkbox.setEnabled(not skipped)
                    if skipped:
                        checkbox.setChecked(False)

                check.setChecked(not widget.outputIsSkipped())
                check.setEnabled(not widget.outputIsSkipped())
                widget.skipOutputChanged.connect(
                    partial(skipOutputChanged, check))
                self.layoutMain.insertWidget(self.layoutMain.count() - 1,
                                             check)
                self.checkBoxes[output.name()] = check

            widget.setToolTip(param.toolTip())
            self.outputWidgets[output.name()] = widget

        for wrapper in list(self.wrappers.values()):
            wrapper.postInitialize(list(self.wrappers.values()))
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)

        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)
示例#6
0
    def reloadProject(self):
        """
        Load all layers from the map layer registry into the table.
        """
        self.unsupportedLayersList = list()

        self.photoNamingTable = PhotoNamingTableWidget()
        self.photoNamingTab.layout().addWidget(self.photoNamingTable)

        self.layersTable.setRowCount(0)
        self.layersTable.setSortingEnabled(False)
        for layer in self.project.mapLayers().values():
            layer_source = LayerSource(layer)
            count = self.layersTable.rowCount()
            self.layersTable.insertRow(count)
            item = QTableWidgetItem(layer.name())
            item.setData(Qt.UserRole, layer_source)
            item.setData(Qt.EditRole, layer.name())
            self.layersTable.setItem(count, 0, item)

            cmb = QComboBox()
            set_available_actions(cmb, layer_source)
            
            cbx = QCheckBox()
            cbx.setEnabled(layer_source.can_lock_geometry)
            cbx.setChecked(layer_source.is_geometry_locked)
            # it's more UI friendly when the checkbox is centered, an ugly workaround to achieve it
            cbx_widget = QWidget()
            cbx_layout = QHBoxLayout()
            cbx_layout.setAlignment(Qt.AlignCenter)
            cbx_layout.setContentsMargins(0, 0, 0, 0)
            cbx_layout.addWidget(cbx)
            cbx_widget.setLayout(cbx_layout)
            # NOTE the margin is not updated when the table column is resized, so better rely on the code above
            # cbx.setStyleSheet("margin-left:50%; margin-right:50%;")

            self.layersTable.setCellWidget(count, 1, cbx_widget)
            self.layersTable.setCellWidget(count, 2, cmb)

            if not layer_source.is_supported:
                self.unsupportedLayersList.append(layer_source)
                self.layersTable.item(count,0).setFlags(Qt.NoItemFlags)
                self.layersTable.cellWidget(count,1).setEnabled(False)
                self.layersTable.cellWidget(count,2).setEnabled(False)
                cmb.setCurrentIndex(cmb.findData(SyncAction.REMOVE))

            # make sure layer_source is the same instance everywhere
            self.photoNamingTable.addLayerFields(layer_source)

        self.layersTable.resizeColumnsToContents()
        self.layersTable.sortByColumn(0, Qt.AscendingOrder)
        self.layersTable.setSortingEnabled(True)

        # Remove the tab when not yet suported in QGIS
        if Qgis.QGIS_VERSION_INT < 31300:
            self.tabWidget.removeTab(self.tabWidget.count() - 1)

        # Load Map Themes
        for theme in self.project.mapThemeCollection().mapThemes():
            self.mapThemeComboBox.addItem(theme)

        self.layerComboBox.setFilters(QgsMapLayerProxyModel.RasterLayer)

        self.__project_configuration = ProjectConfiguration(self.project)
        self.createBaseMapGroupBox.setChecked(self.__project_configuration.create_base_map)

        if self.__project_configuration.base_map_type == ProjectProperties.BaseMapType.SINGLE_LAYER:
            self.singleLayerRadioButton.setChecked(True)
        else:
            self.mapThemeRadioButton.setChecked(True)

        self.mapThemeComboBox.setCurrentIndex(
            self.mapThemeComboBox.findText(self.__project_configuration.base_map_theme))
        layer = QgsProject.instance().mapLayer(self.__project_configuration.base_map_layer)
        self.layerComboBox.setLayer(layer)
        self.mapUnitsPerPixel.setText(str(self.__project_configuration.base_map_mupp))
        self.tileSize.setText(str(self.__project_configuration.base_map_tile_size))
        self.onlyOfflineCopyFeaturesInAoi.setChecked(self.__project_configuration.offline_copy_only_aoi)

        if self.unsupportedLayersList:
            self.unsupportedLayersLabel.setVisible(True)

            unsupported_layers_text = '<b>{}: </b>'.format(self.tr('Warning'))
            unsupported_layers_text += self.tr("There are unsupported layers in your project which will not be available in QField.")
            unsupported_layers_text += self.tr(" If needed, you can create a Base Map to include those layers in your packaged project.")
            self.unsupportedLayersLabel.setText(unsupported_layers_text)
示例#7
0
    def initWidgets(self):
        # If there are advanced parameters — show corresponding groupbox
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                self.grpAdvanced.show()
                break
        # Create widgets and put them in layouts
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if param.isDestination():
                continue
            else:
                wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent)
                self.wrappers[param.name()] = wrapper
                widget = wrapper.widget

                if widget is not None:
                    if isinstance(param, QgsProcessingParameterFeatureSource):
                        layout = QHBoxLayout()
                        layout.setSpacing(6)
                        layout.setMargin(0)
                        layout.addWidget(widget)
                        button = QToolButton()
                        icon = QIcon(os.path.join(pluginPath, 'images', 'iterate.png'))
                        button.setIcon(icon)
                        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
                        button.setToolTip(self.tr('Iterate over this layer, creating a separate output for every feature in the layer'))
                        button.setCheckable(True)
                        layout.addWidget(button)
                        layout.setAlignment(button, Qt.AlignTop)
                        self.iterateButtons[param.name()] = button
                        button.toggled.connect(self.buttonToggled)
                        widget = QWidget()
                        widget.setLayout(layout)

                    widget.setToolTip(param.toolTip())

                    if wrapper.label is not None:
                        if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                            self.layoutAdvanced.addWidget(wrapper.label)
                        else:
                            self.layoutMain.insertWidget(
                                self.layoutMain.count() - 2, wrapper.label)
                    else:
                        desc = param.description()
                        if isinstance(param, QgsProcessingParameterExtent):
                            desc += self.tr(' (xmin, xmax, ymin, ymax)')
                        if isinstance(param, QgsProcessingParameterPoint):
                            desc += self.tr(' (x, y)')
                        if param.flags() & QgsProcessingParameterDefinition.FlagOptional:
                            desc += self.tr(' [optional]')
                        widget.setText(desc)
                    if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                        self.layoutAdvanced.addWidget(widget)
                    else:
                        self.layoutMain.insertWidget(
                            self.layoutMain.count() - 2, widget)

        for output in self.alg.destinationParameterDefinitions():
            if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            label = QLabel(output.description())
            widget = DestinationSelectionPanel(output, self.alg)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
            if isinstance(output, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)):
                check = QCheckBox()
                check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file after running algorithm'))

                def skipOutputChanged(checkbox, skipped):
                    checkbox.setEnabled(not skipped)
                    if skipped:
                        checkbox.setChecked(False)
                check.setChecked(not widget.outputIsSkipped())
                check.setEnabled(not widget.outputIsSkipped())
                widget.skipOutputChanged.connect(partial(skipOutputChanged, check))
                self.layoutMain.insertWidget(self.layoutMain.count() - 1, check)
                self.checkBoxes[output.name()] = check

            widget.setToolTip(param.toolTip())
            self.outputWidgets[output.name()] = widget

        for wrapper in list(self.wrappers.values()):
            wrapper.postInitialize(list(self.wrappers.values()))
    def initWidgets(self): # Heavy overload
        # If there are advanced parameters — show corresponding groupbox
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                self.grpAdvanced.show()
                break

        #widget_context = QgsProcessingParameterWidgetContext()
        #if iface is not None:
        #    widget_context.setMapCanvas(iface.mapCanvas())

        # Create widgets and put them in layouts
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            print('initWidgets - param.name(): {}'.format(param.name()))
            if param.isDestination(): # and param.name() != 'OUTPUT_ASC':
                continue
            else:
                wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent)
                self.wrappers[param.name()] = wrapper

                #widget = wrapper.widget    

                # For compatibility with 3.x API, we need to check whether the wrapper is
                # the deprecated WidgetWrapper class. If not, it's the newer
                # QgsAbstractProcessingParameterWidgetWrapper class
                # TODO QGIS 4.0 - remove
                is_python_wrapper = issubclass(wrapper.__class__, WidgetWrapper)
                if not is_python_wrapper:
                    from qgis.gui import (QgsProcessingContextGenerator, QgsProcessingParameterWidgetContext)
                    widget_context = QgsProcessingParameterWidgetContext()
                    if iface is not None:
                        widget_context.setMapCanvas(iface.mapCanvas())
                    wrapper.setWidgetContext(widget_context)
                    widget = wrapper.createWrappedWidget(self.processing_context)
                    wrapper.registerProcessingContextGenerator(self.context_generator)
                else:
                    widget = wrapper.widget

                #if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                    # don't show the input/output parameter widgets in in-place mode
                    # we still need to CREATE them, because other wrappers may need to interact
                    # with them (e.g. those parameters which need the input layer for field
                    # selections/crs properties/etc)
                #    continue

                if widget is not None:
                    if is_python_wrapper:
                        widget.setToolTip(param.toolTip())

                    if isinstance(param, QgsProcessingParameterFeatureSource):
                        layout = QHBoxLayout()
                        layout.setSpacing(6)
                        layout.setMargin(0)
                        layout.addWidget(widget)
                        button = QToolButton()
                        icon = QIcon(os.path.join(pluginPath, 'images', 'iterate.png'))
                        button.setIcon(icon)
                        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
                        button.setToolTip(self.tr('Iterate over this layer, creating a separate output for every feature in the layer'))
                        button.setCheckable(True)
                        layout.addWidget(button)
                        layout.setAlignment(button, Qt.AlignTop)
                        self.iterateButtons[param.name()] = button
                        button.toggled.connect(self.buttonToggled)
                        widget = QWidget()
                        widget.setLayout(layout)

                    label = None
                    if not is_python_wrapper:
                        label = wrapper.createWrappedLabel()
                    else:
                        label = wrapper.label

                    if label is not None:
                        if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                            self.layoutAdvanced.addWidget(label)
                        else:
                            self.layoutMain.insertWidget(
                                self.layoutMain.count() - 2, label)
                    elif is_python_wrapper:
                        desc = param.description()
                        if isinstance(param, QgsProcessingParameterExtent):
                            desc += self.tr(' (xmin, xmax, ymin, ymax)')
                        if isinstance(param, QgsProcessingParameterPoint):
                            desc += self.tr(' (x, y)')
                        if param.flags() & QgsProcessingParameterDefinition.FlagOptional:
                            desc += self.tr(' [optional]')
                        widget.setText(desc)
                    if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                        self.layoutAdvanced.addWidget(widget)
                    else:
                        self.layoutMain.insertWidget(
                            self.layoutMain.count() - 2, widget)

        for output in self.alg.destinationParameterDefinitions():
            if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            #if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
            #    continue

            label = QLabel(output.description())
            #print('initWidgets 2 - param.name(): {}'.format(param.name()))
            widget = DestinationSelectionPanel(output, self.alg) # TODO, overload
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
            if isinstance(output, (QgsProcessingParameterRasterDestination, 
                                   QgsProcessingParameterFeatureSink, 
                                   QgsProcessingParameterVectorDestination
                                   # alk: checkboxes for Chloe handling  
                                   ,ChloeCSVParameterFileDestination,
                                   ChloeASCParameterFileDestination,
                                   ChloeParameterFolderDestination)
                                   ):
                check = QCheckBox()
                check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file(s) after running algorithm'))

                def skipOutputChanged(checkbox, skipped):
                    checkbox.setEnabled(not skipped)
                    if skipped:
                        checkbox.setChecked(False)
                check.setChecked(not widget.outputIsSkipped())
                check.setEnabled(not widget.outputIsSkipped())
                widget.skipOutputChanged.connect(partial(skipOutputChanged, check))
                self.layoutMain.insertWidget(self.layoutMain.count() - 1, check)
                self.checkBoxes[output.name()] = check
                # initial state
                if hasattr(output,'addToMapDefaultState'):
                    check.setChecked(output.addToMapDefaultState)


            widget.setToolTip(param.toolTip())
            self.outputWidgets[output.name()] = widget

        for wrapper in list(self.wrappers.values()):
            wrapper.postInitialize(list(self.wrappers.values()))
        
        
        # # alk: checkboxes for Chloe handling  
        # for output in self.alg.destinationParameterDefinitions():
        #     if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
        #         continue

        #     if isinstance(output, (ChloeCSVParameterFileDestination)) or isinstance(output, (ChloeASCParameterFileDestination)):
        #         check = QCheckBox()
        #         check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file(s) after running algorithm'))

        #         def skipOutputChanged(checkbox, skipped):
        #             checkbox.setEnabled(not skipped)
        #             if skipped:
        #                 checkbox.setChecked(False)
        #         check.setChecked(not widget.outputIsSkipped())
        #         check.setEnabled(not widget.outputIsSkipped())
        #         widget.skipOutputChanged.connect(partial(skipOutputChanged, check))
        #         print(str(self.layoutMain)+1)
        #         self.layoutMain.insertWidget(self.layoutMain.count() - 1, check)
        #         self.checkBoxes[output.name()] = check
                
                # # connecting alg outputLoading info with checkbox state
                # self.alg.outputLoading[output.name()] = check.isChecked()
                # def updateOutputLoadingState(alg, outputName, checkbox, state):
                #     self.alg.outputLoading[outputName] = checkbox.isChecked()
                #     print( outputName + " " + str(checkbox.isChecked()) + " " + str(self.alg.outputLoading) + " " + str(self.alg))
                #     #print(str(self.alg.parameters))
                # check.stateChanged.connect(partial(updateOutputLoadingState, self, output.name(), check))
        
        # alk: addition of wrapper special config handling
        # for dependancy between wrapper, i.e. changing the value 
        # of a FileSelectionPanel entails the update of another widget
        for k in self.wrappers:
            w = self.wrappers[k]
            if hasattr(w,'getParentWidgetConfig'):
                print(str(w) + " "  + "getParentWidgetConfig")
                config = w.getParentWidgetConfig()
                if config != None:
                    p = self.wrappers[config['paramName']]
                    m = getattr(w, config['refreshMethod'])
                    if m!=None:
                        print(str(p) + " " + str(p.widget))
                        # todo generalize valueChanged handling 
                        # to any type of widget componant
                        if isinstance(p.widget, FileSelectionPanel):
                            p.widget.leText.textChanged.connect(m)
                        elif isinstance(p, RasterWidgetWrapper):
                            try:
                                p.combo.valueChanged.connect(m) # QGIS 3.8 version
                            except:
                                p.combo.currentIndexChanged.connect(m) # QGIS LTR 3.4
示例#9
0
    def __update_available_error_data(self):
        self.tbw_errors.setUpdatesEnabled(
            False)  # Don't render until we're ready

        # Save selection before clearing table to restate it later (if needed)
        self.__update_selected_item()

        self.tbw_errors.blockSignals(
            True)  # We don't want to get itemSelectionChanged here
        self.tbw_errors.clear()
        self.tbw_errors.blockSignals(False)

        self.tbw_errors.setHorizontalHeaderLabels(self.__column_labels)

        # Filter by search text
        list_errors = self.__filter_by_search_text(self.txt_search.text())
        self.tbw_errors.setRowCount(len(list_errors))
        row = 0

        for feature in list_errors:
            # 1) Fixed error checkbox
            widget = QWidget()
            checkbox = QCheckBox()
            checkbox.setCheckState(Qt.Checked if self.__controller.
                                   is_fixed_error(feature) else Qt.Unchecked)
            checkbox.setStyleSheet('background: white;')
            checkbox.setEnabled(not self.__controller.is_exception(feature)
                                )  # Exceptions cannot be fixed
            checkbox.setToolTip(
                QCoreApplication.translate(
                    "QualityRulesErrorResultsPanelWidget",
                    "Is the error fixed?"))
            layout = QHBoxLayout(widget)
            layout.addWidget(checkbox)
            layout.setAlignment(Qt.AlignCenter)
            layout.setContentsMargins(0, 0, 0, 0)
            checkbox.stateChanged.connect(
                partial(self.__error_state_changed, row))
            self.tbw_errors.setCellWidget(row, CHECK_COLUMN, widget)

            # 2) Object UUIDs
            uuids = self.__controller.uuid_objs(feature)
            uuid_item = QTableWidgetItem(uuids)
            uuid_item.setData(Qt.UserRole,
                              self.__controller.error_t_id(feature))
            ili_name = self.__controller.ili_obj_name(feature)
            uuid_item.setData(
                Qt.ToolTipRole, "UUIDs ({}):\n{}".format(ili_name, uuids)
                if ili_name else "UUIDs:\n{}".format(uuids))
            self.tbw_errors.setItem(row, UUIDS_COLUMN, uuid_item)

            # 3) Error type code
            error_type_code, error_type_display = self.__controller.error_type_code_and_display(
                feature)
            error_type_item = QTableWidgetItem(error_type_code)
            error_type_item.setData(
                Qt.ToolTipRole, "{}\n({})".format(error_type_display,
                                                  error_type_code))
            self.tbw_errors.setItem(row, QRE_COLUMN, error_type_item)

            # 4) Details + Values
            details = self.__controller.error_details_and_values(feature)
            error_details_item = QTableWidgetItem(details)
            error_details_item.setData(Qt.ToolTipRole, details)
            self.tbw_errors.setItem(row, DETAILS_COLUMN, error_details_item)

            self.__set_row_color_by_state(
                row, self.__controller.error_state(feature))

            row += 1

        # Set selection
        self.tbw_errors.blockSignals(
            True)  # We don't want to get itemSelectionChanged here
        item = self.__get_item_by_t_id(self.__selected_item)
        if item:
            item.setSelected(True)
        self.tbw_errors.blockSignals(False)

        self.tbw_errors.setUpdatesEnabled(True)  # Now render!
示例#10
0
    def initWidgets(self):
        super().initWidgets()

        widget_context = QgsProcessingParameterWidgetContext()
        widget_context.setProject(QgsProject.instance())
        if iface is not None:
            widget_context.setMapCanvas(iface.mapCanvas())
            widget_context.setBrowserModel(iface.browserModel())
        widget_context.setMessageBar(self.parent().messageBar())
        if isinstance(self.algorithm(), QgsProcessingModelAlgorithm):
            widget_context.setModel(self.algorithm())

        # Create widgets and put them in layouts
        for param in self.algorithm().parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if param.isDestination():
                continue
            else:
                wrapper = WidgetWrapperFactory.create_wrapper(
                    param, self.parent())
                wrapper.setWidgetContext(widget_context)
                wrapper.registerProcessingContextGenerator(
                    self.context_generator)
                self.wrappers[param.name()] = wrapper

                # For compatibility with 3.x API, we need to check whether the wrapper is
                # the deprecated WidgetWrapper class. If not, it's the newer
                # QgsAbstractProcessingParameterWidgetWrapper class
                # TODO QGIS 4.0 - remove
                is_python_wrapper = issubclass(wrapper.__class__,
                                               WidgetWrapper)
                if not is_python_wrapper:
                    widget = wrapper.createWrappedWidget(
                        self.processing_context)
                else:
                    widget = wrapper.widget

                if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                    # don't show the input/output parameter widgets in in-place mode
                    # we still need to CREATE them, because other wrappers may need to interact
                    # with them (e.g. those parameters which need the input layer for field
                    # selections/crs properties/etc)
                    continue

                if widget is not None:
                    if is_python_wrapper:
                        widget.setToolTip(param.toolTip())

                    label = None
                    if not is_python_wrapper:
                        label = wrapper.createWrappedLabel()
                    else:
                        label = wrapper.label

                    if label is not None:
                        self.addParameterLabel(param, label)
                    elif is_python_wrapper:
                        desc = param.description()
                        if isinstance(param, QgsProcessingParameterExtent):
                            desc += self.tr(' (xmin, xmax, ymin, ymax)')
                        if param.flags(
                        ) & QgsProcessingParameterDefinition.FlagOptional:
                            desc += self.tr(' [optional]')
                        widget.setText(desc)

                    self.addParameterWidget(param, widget)

        for output in self.algorithm().destinationParameterDefinitions():
            if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                continue

            label = QLabel(output.description())
            widget = QgsProcessingLayerOutputDestinationWidget(output, False)
            widget.setWidgetContext(widget_context)

            self.addOutputLabel(label)
            self.addOutputWidget(widget)
            if isinstance(output, (QgsProcessingParameterRasterDestination,
                                   QgsProcessingParameterFeatureSink,
                                   QgsProcessingParameterVectorDestination)):
                check = QCheckBox()
                check.setText(
                    QCoreApplication.translate(
                        'ParametersPanel',
                        'Open output file after running algorithm'))

                def skipOutputChanged(widget, checkbox, skipped):

                    enabled = not skipped

                    # Do not try to open formats that are write-only.
                    value = widget.value()
                    if value and isinstance(
                            value,
                            QgsProcessingOutputLayerDefinition) and isinstance(
                                output,
                                (QgsProcessingParameterFeatureSink,
                                 QgsProcessingParameterVectorDestination)):
                        filename = value.sink.staticValue()
                        if filename not in ('memory:', ''):
                            path, ext = os.path.splitext(filename)
                            format = QgsVectorFileWriter.driverForExtension(
                                ext)
                            drv = gdal.GetDriverByName(format)
                            if drv:
                                if drv.GetMetadataItem(gdal.DCAP_OPEN) is None:
                                    enabled = False

                    checkbox.setEnabled(enabled)
                    checkbox.setChecked(enabled)

                check.setChecked(not widget.outputIsSkipped())
                check.setEnabled(not widget.outputIsSkipped())
                widget.skipOutputChanged.connect(
                    partial(skipOutputChanged, widget, check))
                self.addOutputWidget(check)
                self.checkBoxes[output.name()] = check

            self.outputWidgets[output.name()] = widget

        for wrapper in list(self.wrappers.values()):
            wrapper.postInitialize(list(self.wrappers.values()))
示例#11
0
class QDrawLayerDialog(QDialog):
    def __init__(self, iface, gtype):
        QDialog.__init__(self)

        self.setWindowTitle(self.tr('Drawing'))

        self.name = QLineEdit()

        if gtype == 'point' or gtype == 'XYpoint':
            gtype = 'Point'
        elif gtype == 'line':
            gtype = 'LineString'
        else:
            gtype = 'Polygon'

        # change here by QgsMapLayerComboBox()
        self.layerBox = QComboBox()
        self.layers = []
        for layer in QgsProject.instance().mapLayers().values():
            if layer.providerType() == "memory":
                # ligne suivante à remplacer par if layer.geometryType() == :
                if gtype in layer.dataProvider().dataSourceUri()[:26]: #  must be of the same type of the draw
                    if 'field='+self.tr('Drawings')+':string(255,0)' in layer.dataProvider().dataSourceUri()[-28:]: # must have its first field named Drawings, string type
                        self.layers.append(layer)
                        self.layerBox.addItem(layer.name())

        self.addLayer = QCheckBox(self.tr('Add to an existing layer'))
        self.addLayer.toggled.connect(self.addLayerChecked)

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel(self.tr("Give a name to the feature:")))
        vbox.addWidget(self.name)
        vbox.addWidget(self.addLayer)
        vbox.addWidget(self.layerBox)
        if len(self.layers) == 0:
            self.addLayer.setEnabled(False)
            self.layerBox.setEnabled(False)
        vbox.addWidget(buttons)
        self.setLayout(vbox)

        self.layerBox.setEnabled(False)
        self.name.setFocus()

    def tr(self, message):
        return QCoreApplication.translate('Qdraw', message)

    def addLayerChecked(self):
        if self.addLayer.checkState() == Qt.Checked:
            self.layerBox.setEnabled(True)
        else:
            self.layerBox.setEnabled(False)

    def getName(self, iface, gtype):
        dialog = QDrawLayerDialog(iface, gtype)
        result = dialog.exec_()
        return (
            dialog.name.text(),
            dialog.addLayer.checkState() == Qt.Checked,
            dialog.layerBox.currentIndex(),
            dialog.layers,
            result == QDialog.Accepted)
示例#12
0
class QDrawLayerDialog(QDialog):
    def __init__(self, iface, gtype):
        QDialog.__init__(self)

        self.setWindowTitle(self.tr('Drawing'))

        self.name = QLineEdit()

        if gtype == 'point' or gtype == 'XYpoint':
            gtype = 'Point'
        elif gtype == 'line':
            gtype = 'LineString'
        else:
            gtype = 'Polygon'

        # change here by QgsMapLayerComboBox()
        self.layerBox = QComboBox()
        self.layers = []
        for layer in QgsProject.instance().mapLayers().values():
            if layer.providerType() == "memory":
                # ligne suivante à remplacer par if layer.geometryType() == :
                if gtype in layer.dataProvider().dataSourceUri(
                )[:26]:  #  must be of the same type of the draw
                    if 'field=' + self.tr(
                            'Drawings'
                    ) + ':string(255,0)' in layer.dataProvider().dataSourceUri(
                    )[-28:]:  # must have its first field named Drawings, string type
                        self.layers.append(layer)
                        self.layerBox.addItem(layer.name())

        self.addLayer = QCheckBox(self.tr('Add to an existing layer'))
        self.addLayer.toggled.connect(self.addLayerChecked)

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel(self.tr("Give a name to the feature:")))
        vbox.addWidget(self.name)
        vbox.addWidget(self.addLayer)
        vbox.addWidget(self.layerBox)
        if len(self.layers) == 0:
            self.addLayer.setEnabled(False)
            self.layerBox.setEnabled(False)
        vbox.addWidget(buttons)
        self.setLayout(vbox)

        self.layerBox.setEnabled(False)
        self.name.setFocus()

    def tr(self, message):
        return QCoreApplication.translate('Qdraw', message)

    def addLayerChecked(self):
        if self.addLayer.checkState() == Qt.Checked:
            self.layerBox.setEnabled(True)
        else:
            self.layerBox.setEnabled(False)

    def getName(self, iface, gtype):
        dialog = QDrawLayerDialog(iface, gtype)
        result = dialog.exec_()
        return (dialog.name.text(), dialog.addLayer.checkState() == Qt.Checked,
                dialog.layerBox.currentIndex(), dialog.layers,
                result == QDialog.Accepted)
class LinearBarcodeLayoutItemWidget(QgsLayoutItemBaseWidget):  # pylint: disable=too-few-public-methods
    """Widget for configuring a LinearBarcodeLayoutItem."""
    def __init__(self, parent, layout_object):
        super().__init__(parent, layout_object)
        self._barcode_item = layout_object
        self.message_bar = None

        self.setPanelTitle(self.tr('Linear Barcode Properties'))
        self._init_widgets(layout_object)
        self._current_meta = self._barcode_cbo.current_metadata()
        self._update_gui_values()

    def _init_widgets(self, layout_object):
        """Initialize widgets"""
        lbl_title = QLabel()
        lbl_title.setStyleSheet(
            'padding: 2px; font-weight: bold; background-color: '
            'rgb(200, 200, 200);')
        lbl_title.setText(self.tr('Linear Barcode'))
        self._cd_value_widget = CodeValueWidget(self)
        self._cd_value_widget.value_changed.connect(
            self._on_code_value_changed)
        value_groupbox = QgsCollapsibleGroupBoxBasic(self.tr('Data'))
        gp_layout = QVBoxLayout()
        gp_layout.setContentsMargins(0, 0, 0, 0)
        gp_layout.addWidget(self._cd_value_widget)
        value_groupbox.setLayout(gp_layout)

        # Barcode properties
        barcode_props_groupbox = QgsCollapsibleGroupBoxBasic(
            self.tr('Properties'))
        barcode_props_layout = QGridLayout()

        lbl_barcode_type = QLabel(self.tr('Linear barcode type'))
        self._barcode_cbo = LinearMetadataCombobox()
        self._barcode_cbo.metadata_changed.connect(
            self._on_linear_type_changed)
        barcode_props_layout.addWidget(lbl_barcode_type, 0, 0)
        barcode_props_layout.addWidget(self._barcode_cbo, 0, 1)
        self._chk_checksum = QCheckBox(self.tr('Add checksum'))
        self._chk_checksum.stateChanged.connect(self._on_add_checksum)
        barcode_props_layout.addWidget(self._chk_checksum, 1, 0, 1, 2)
        self._chk_render_txt = QCheckBox(self.tr('Render barcode text'))
        self._chk_render_txt.stateChanged.connect(self._on_render_text_changed)
        barcode_props_layout.addWidget(self._chk_render_txt, 2, 0, 1, 2)
        barcode_props_layout.setColumnStretch(1, 1)

        barcode_props_groupbox.setLayout(barcode_props_layout)

        # Properties widget
        self._prop_widget = QgsLayoutItemPropertiesWidget(self, layout_object)
        self._prop_widget.showBackgroundGroup(False)

        # Add widgets to layout
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(lbl_title)
        layout.addWidget(barcode_props_groupbox)
        layout.addWidget(value_groupbox)
        layout.addWidget(self._prop_widget)

        # Set layout
        self.setLayout(layout)

    def setDesignerInterface(self, iface):
        """
        Use layout iface to set the message_bar.
        """
        super().setDesignerInterface(iface)
        self.message_bar = iface.messageBar()

    def metadata(self, metadata_id):
        """
        Gets the metadata object that corresponds to the given id.
        :param metadata_id: Metadata id.
        :type metadata_id: str
        :return: Returns the metadata object corresponding to the
        given id.
        :rtype: AbstractLinearBarcodeMetadata
        """
        reg = LinearBarcodeMetadataRegistry.instance()

        return reg.metadata_by_typeid(metadata_id)

    def setNewItem(self, item):
        """
        Set widget properties to sync with item properties.
        """
        if item.type() != LINEAR_BARCODE_TYPE:
            return False

        self._barcode_item = item
        self._prop_widget.setItem(self._barcode_item)
        self._update_gui_values()

        return True

    def _on_linear_type_changed(self, metadata_id):
        """
        Slot raised when the linear barcode type has been changed.
        """
        meta = self.metadata(metadata_id)
        if meta is None:
            return

        self._current_meta = meta
        self._adapt_ui_item_checksum_properties()
        self.set_barcode_data()

    def _adapt_ui_item_checksum_properties(self):
        """
        Update UI and barcode item properties based on the properties of the
        current metadata object.
        """
        if self._current_meta is None:
            return

        if self._current_meta.supports_manual_checksum():
            self._barcode_item.supports_manual_checksum = True
            self._chk_checksum.setEnabled(True)
            # Set check status based on barcode properties
            if self._barcode_item.add_checksum:
                self._chk_checksum.setCheckState(Qt.Checked)
            else:
                self._chk_checksum.setCheckState(Qt.Unchecked)
        else:
            self._barcode_item.supports_manual_checksum = False
            self._chk_checksum.setEnabled(False)
            self._barcode_item.add_checksum = False
            if self._current_meta.is_checksum_automatic():
                self._chk_checksum.setCheckState(Qt.Checked)
            else:
                self._chk_checksum.setCheckState(Qt.Unchecked)

    def _on_add_checksum(self, state):
        """
        Slot raised to add checksum to the barcode data.
        """
        add_checksum = False
        if state == Qt.Checked:
            add_checksum = True

        self._barcode_item.beginCommand(self.tr('Change add checksum'),
                                        QgsLayoutItem.UndoCustomCommand)
        self._barcode_item.blockSignals(True)
        self._barcode_item.add_checksum = add_checksum
        self._barcode_item.blockSignals(False)
        self._barcode_item.endCommand()

    def _on_code_value_changed(self, value):
        """
        Slot raised when the barcode value changes.
        """
        self.set_barcode_data()

    def set_barcode_data(self):
        """
        Assert if characters (computed from the expression) are valid. If
        not, remove invalid characters then check if the maximum number of
        characters are within the maximum set for the given linear barcode
        type.
        """
        # Flag for the validity of barcode data
        is_invalid = False
        if self._current_meta is None:
            return

        user_value = self._cd_value_widget.code_value
        cd_val = self._barcode_item.evaluate_expression(user_value)

        if not cd_val:
            return

        # Check valid characters
        valid_chars = []
        for ch in cd_val:
            if self._current_meta.is_character_allowed(ch):
                valid_chars.append(ch)

        sanitized_txt = ''.join(valid_chars)

        # Notify user if there were invalid chars
        if len(sanitized_txt) != len(cd_val):
            self.add_warning_message(
                self.tr('Barcode data contains invalid characters.'))
            is_invalid = True

        cd_val = sanitized_txt
        # Check max length
        max_length = self._current_meta.max_input_length()
        if max_length != -1 and len(cd_val) > max_length:
            self.add_warning_message(
                self.tr('Barcode data cannot exceed the maximum length of '
                        '{0} characters for {1} linear barcode type.'.format(
                            max_length, self._current_meta.display_name())))
            is_invalid = True

        # Highlight barcode data based on validity of the input
        self._cd_value_widget.highlight_invalid_data(is_invalid)

        if is_invalid:  # pylint: disable=no-else-return
            return
        else:
            # Remove any warning items if still visible
            # Check if message_bar has already been initialized
            if self.message_bar is not None:
                self.message_bar.clearWidgets()

        # Set barcode value
        self._barcode_item.beginCommand(self.tr('Change code value'),
                                        QgsLayoutItem.UndoLabelText)
        self._barcode_item.blockSignals(True)
        try:
            self._barcode_item.barcode_type = self._current_meta.type_id()
            self._barcode_item.code_value = user_value
        except BarcodeException as bc_ex:
            self.add_warning_message(str(bc_ex))
            is_invalid = True
        self._barcode_item.blockSignals(False)
        self._barcode_item.endCommand()

    def _on_render_text_changed(self, state):
        """
        Slot raised when render_text has been checked/unchecked.
        """
        render_text = False
        if state == Qt.Checked:
            render_text = True

        self._barcode_item.beginCommand(self.tr('Change render text'),
                                        QgsLayoutItem.UndoCustomCommand)
        self._barcode_item.blockSignals(True)
        self._barcode_item.render_text = render_text
        self._barcode_item.blockSignals(False)
        self._barcode_item.endCommand()

    def _update_gui_values(self):
        """
        Update gui items based on the item properties.
        """
        self._current_meta = self.metadata(self._barcode_item.barcode_type)

        # Barcode type in combobox
        self._barcode_cbo.blockSignals(True)
        self._barcode_cbo.set_current_metadata(self._barcode_item.barcode_type)
        self._barcode_cbo.blockSignals(False)

        # Checksum property
        self._adapt_ui_item_checksum_properties()

        # Render text property
        self._chk_render_txt.blockSignals(True)
        if self._barcode_item.render_text:
            self._chk_render_txt.setCheckState(Qt.Checked)
        else:
            self._chk_render_txt.setCheckState(Qt.Unchecked)
        self._chk_render_txt.blockSignals(False)

        # Barcode value (which could also be an expression)
        self._cd_value_widget.block_value_widget_signals(True)
        self._cd_value_widget.code_value = self._barcode_item.code_value
        self._cd_value_widget.value_text_edit.moveCursor(
            QTextCursor.End, QTextCursor.MoveAnchor)
        self._cd_value_widget.block_value_widget_signals(False)

        # Now set barcode data
        self.set_barcode_data()

    def add_warning_message(self, msg):
        """
        Add warning message to the layout interface.
        :param msg: Warning message.
        :type msg: str
        """
        self.message_bar.pushWarning(self.tr('Linear Barcode'), msg)
示例#14
0
    def initWidgets(self):
        # If there are advanced parameters — show corresponding groupbox
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                self.grpAdvanced.show()
                break

        widget_context = QgsProcessingParameterWidgetContext()
        if iface is not None:
            widget_context.setMapCanvas(iface.mapCanvas())

        # Create widgets and put them in layouts
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if param.isDestination():
                continue
            else:
                wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent)
                self.wrappers[param.name()] = wrapper

                # For compatibility with 3.x API, we need to check whether the wrapper is
                # the deprecated WidgetWrapper class. If not, it's the newer
                # QgsAbstractProcessingParameterWidgetWrapper class
                # TODO QGIS 4.0 - remove
                is_python_wrapper = issubclass(wrapper.__class__, WidgetWrapper)
                if not is_python_wrapper:
                    wrapper.setWidgetContext(widget_context)
                    widget = wrapper.createWrappedWidget(self.processing_context)
                    wrapper.registerProcessingContextGenerator(self.context_generator)
                else:
                    widget = wrapper.widget

                if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                    # don't show the input/output parameter widgets in in-place mode
                    # we still need to CREATE them, because other wrappers may need to interact
                    # with them (e.g. those parameters which need the input layer for field
                    # selections/crs properties/etc)
                    continue

                if widget is not None:
                    if is_python_wrapper:
                        widget.setToolTip(param.toolTip())

                    if isinstance(param, QgsProcessingParameterFeatureSource):
                        layout = QHBoxLayout()
                        layout.setSpacing(6)
                        layout.setMargin(0)
                        layout.addWidget(widget)
                        button = QToolButton()
                        icon = QIcon(os.path.join(pluginPath, 'images', 'iterate.png'))
                        button.setIcon(icon)
                        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
                        button.setToolTip(self.tr('Iterate over this layer, creating a separate output for every feature in the layer'))
                        button.setCheckable(True)
                        layout.addWidget(button)
                        layout.setAlignment(button, Qt.AlignTop)
                        self.iterateButtons[param.name()] = button
                        button.toggled.connect(self.buttonToggled)
                        widget = QWidget()
                        widget.setLayout(layout)

                    label = None
                    if not is_python_wrapper:
                        label = wrapper.createWrappedLabel()
                    else:
                        label = wrapper.label

                    if label is not None:
                        if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                            self.layoutAdvanced.addWidget(label)
                        else:
                            self.layoutMain.insertWidget(
                                self.layoutMain.count() - 2, label)
                    elif is_python_wrapper:
                        desc = param.description()
                        if isinstance(param, QgsProcessingParameterExtent):
                            desc += self.tr(' (xmin, xmax, ymin, ymax)')
                        if isinstance(param, QgsProcessingParameterPoint):
                            desc += self.tr(' (x, y)')
                        if param.flags() & QgsProcessingParameterDefinition.FlagOptional:
                            desc += self.tr(' [optional]')
                        widget.setText(desc)
                    if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                        self.layoutAdvanced.addWidget(widget)
                    else:
                        self.layoutMain.insertWidget(
                            self.layoutMain.count() - 2, widget)

        for output in self.alg.destinationParameterDefinitions():
            if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
                continue

            label = QLabel(output.description())
            widget = DestinationSelectionPanel(output, self.alg)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
            if isinstance(output, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)):
                check = QCheckBox()
                check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file after running algorithm'))

                def skipOutputChanged(checkbox, skipped):
                    checkbox.setEnabled(not skipped)
                    if skipped:
                        checkbox.setChecked(False)
                check.setChecked(not widget.outputIsSkipped())
                check.setEnabled(not widget.outputIsSkipped())
                widget.skipOutputChanged.connect(partial(skipOutputChanged, check))
                self.layoutMain.insertWidget(self.layoutMain.count() - 1, check)
                self.checkBoxes[output.name()] = check

            widget.setToolTip(param.toolTip())
            self.outputWidgets[output.name()] = widget

        for wrapper in list(self.wrappers.values()):
            wrapper.postInitialize(list(self.wrappers.values()))
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)
示例#16
0
    def initWidgets(self):
        # If there are advanced parameters — show corresponding groupbox
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
                self.grpAdvanced.show()
                break
        # Create widgets and put them in layouts
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            if param.isDestination():
                continue
            else:
                wrapper = WidgetWrapperFactory.create_wrapper(
                    param, self.parent)
                self.wrappers[param.name()] = wrapper
                widget = wrapper.widget

                if widget is not None:
                    if isinstance(param, QgsProcessingParameterFeatureSource):
                        layout = QHBoxLayout()
                        layout.setSpacing(6)
                        layout.setMargin(0)
                        layout.addWidget(widget)
                        button = QToolButton()
                        icon = QIcon(
                            os.path.join(pluginPath, 'images', 'iterate.png'))
                        button.setIcon(icon)
                        button.setSizePolicy(QSizePolicy.Fixed,
                                             QSizePolicy.Expanding)
                        button.setToolTip(
                            self.
                            tr('Iterate over this layer, creating a separate output for every feature in the layer'
                               ))
                        button.setCheckable(True)
                        layout.addWidget(button)
                        layout.setAlignment(button, Qt.AlignTop)
                        self.iterateButtons[param.name()] = button
                        button.toggled.connect(self.buttonToggled)
                        widget = QWidget()
                        widget.setLayout(layout)

                    widget.setToolTip(param.toolTip())

                    if wrapper.label is not None:
                        if param.flags(
                        ) & QgsProcessingParameterDefinition.FlagAdvanced:
                            self.layoutAdvanced.addWidget(wrapper.label)
                        else:
                            self.layoutMain.insertWidget(
                                self.layoutMain.count() - 2, wrapper.label)
                    else:
                        desc = param.description()
                        if isinstance(param, QgsProcessingParameterExtent):
                            desc += self.tr(' (xmin, xmax, ymin, ymax)')
                        if isinstance(param, QgsProcessingParameterPoint):
                            desc += self.tr(' (x, y)')
                        if param.flags(
                        ) & QgsProcessingParameterDefinition.FlagOptional:
                            desc += self.tr(' [optional]')
                        widget.setText(desc)
                    if param.flags(
                    ) & QgsProcessingParameterDefinition.FlagAdvanced:
                        self.layoutAdvanced.addWidget(widget)
                    else:
                        self.layoutMain.insertWidget(
                            self.layoutMain.count() - 2, widget)

        for output in self.alg.destinationParameterDefinitions():
            if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
                continue

            label = QLabel(output.description())
            widget = DestinationSelectionPanel(output, self.alg)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
            self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
            if isinstance(output, (QgsProcessingParameterRasterDestination,
                                   QgsProcessingParameterFeatureSink,
                                   QgsProcessingParameterVectorDestination)):
                check = QCheckBox()
                check.setText(
                    QCoreApplication.translate(
                        'ParametersPanel',
                        'Open output file after running algorithm'))

                def skipOutputChanged(checkbox, skipped):
                    checkbox.setEnabled(not skipped)
                    if skipped:
                        checkbox.setChecked(False)

                check.setChecked(not widget.outputIsSkipped())
                check.setEnabled(not widget.outputIsSkipped())
                widget.skipOutputChanged.connect(
                    partial(skipOutputChanged, check))
                self.layoutMain.insertWidget(self.layoutMain.count() - 1,
                                             check)
                self.checkBoxes[output.name()] = check

            widget.setToolTip(param.toolTip())
            self.outputWidgets[output.name()] = widget

        for wrapper in list(self.wrappers.values()):
            wrapper.postInitialize(list(self.wrappers.values()))
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)