def update_data_sources_table_names(self):
        
        schema_list = []
        schema_list = self.fetch_schemas(self.ui.cbUploadDatabase.currentText())
            
        if self.local_data_sources.count() == 0:
            self.data_sources_table_names.clear()
        else:
            # remove table names without data sources
            keys_to_remove = []
            for key in list(self.data_sources_table_names.keys()):
                if self.local_data_sources.layers(key) is None:
                    keys_to_remove.append(key)

            for key in keys_to_remove:
                del self.data_sources_table_names[key]

            # update table names
            if schema_list != None:
                for row in range(0, self.ui.tblLocalLayers.rowCount()):
                    data_source = self.ui.tblLocalLayers.item(row, self.COLUMN_DATA_SOURCE).text()
                    cmb_schema = QComboBox()
                    cmb_schema.setEditable(True)
                    cmb_schema.addItems(schema_list)
                    self.ui.tblLocalLayers.setCellWidget(row, self.COLUMN_SCHEMA_NAME, cmb_schema)                
                    table_name = self.ui.tblLocalLayers.item(row, self.COLUMN_TABLE_NAME).text()
                    self.data_sources_table_names[data_source] = table_name
Exemple #2
0
 def createEditor(self, parent, options, index):
     setting = index.model().data(index, Qt.UserRole)
     if setting.valuetype == Setting.FOLDER:
         return FileDirectorySelector(parent)
     elif setting.valuetype == Setting.FILE:
         return FileDirectorySelector(parent, True)
     elif setting.valuetype == Setting.SELECTION:
         combo = QComboBox(parent)
         combo.addItems(setting.options)
         return combo
     elif setting.valuetype == Setting.MULTIPLE_FOLDERS:
         return MultipleDirectorySelector(parent)
     else:
         value = self.convertValue(index.model().data(index, Qt.EditRole))
         if isinstance(value, int):
             spnBox = QgsSpinBox(parent)
             spnBox.setRange(-999999999, 999999999)
             return spnBox
         elif isinstance(value, float):
             spnBox = QgsDoubleSpinBox(parent)
             spnBox.setRange(-999999999.999999, 999999999.999999)
             spnBox.setDecimals(6)
             return spnBox
         elif isinstance(value, str):
             return QLineEdit(parent)
Exemple #3
0
class ConnectionWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin):
    """
    WidgetWrapper for ParameterString that create and manage a combobox widget
    with existing postgis connections.
    """

    def createWidget(self):
        self._combo = QComboBox()
        for group in self.items():
            self._combo.addItem(*group)
        self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
        return self.wrapWithExpressionButton(self._combo)

    def items(self):
        settings = QgsSettings()
        settings.beginGroup('/PostgreSQL/connections/')
        items = [(group, group) for group in settings.childGroups()]

        if self.dialogType == DIALOG_MODELER:
            strings = self.dialog.getAvailableValuesOfType(
                [QgsProcessingParameterString, QgsProcessingParameterNumber, QgsProcessingParameterFile,
                 QgsProcessingParameterField, QgsProcessingParameterExpression], QgsProcessingOutputString)
            items = items + [(self.dialog.resolveValueDescription(s), s) for s in strings]

        return items

    def setValue(self, value):
        self.setComboValue(value, self._combo)

    def value(self):
        return self.comboValue(combobox=self._combo)
Exemple #4
0
 def createWidget(self):
     if self.param.multiple:
         return MultipleInputPanel(options=self.param.options)
     else:
         widget = QComboBox()
         widget.addItems(self.param.options)
         if self.param.default:
             widget.setCurrentIndex(self.param.default)
         return widget
Exemple #5
0
 def createWidget(self):
     if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
         return FileSelectionPanel(self.param.isFolder, self.param.ext)
     else:
         widget = QComboBox()
         widget.setEditable(True)
         files = self.dialog.getAvailableValuesOfType(ParameterFile, OutputFile)
         for f in files:
             widget.addItem(self.dialog.resolveValueDescription(f), f)
         return widget
Exemple #6
0
    def createWidget(self):
        if self.dialogType == DIALOG_STANDARD:
            widget = QWidget()
            layout = QHBoxLayout()
            layout.setMargin(0)
            layout.setContentsMargins(0, 0, 0, 0)
            layout.setSpacing(2)
            self.combo = QgsMapLayerComboBox()
            layout.addWidget(self.combo)
            btn = QToolButton()
            btn.setText('...')
            btn.setToolTip(self.tr("Select file"))
            btn.clicked.connect(self.selectFile)
            layout.addWidget(btn)

            widget.setLayout(layout)

            if self.param.optional:
                self.combo.setAllowEmptyLayer(True)

            self.combo.setFilters(QgsMapLayerProxyModel.VectorLayer)
            self.combo.setExcludedProviders(['grass'])

            self.combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
            self.combo.currentTextChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
            return widget

        elif self.dialogType == DIALOG_BATCH:
            return BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
        else:
            self.combo = QComboBox()
            layers = self.dialog.getAvailableValuesOfType(ParameterRaster, OutputRaster)
            self.combo.setEditable(True)
            tables = self.dialog.getAvailableValuesOfType(ParameterTable, OutputTable)
            layers = self.dialog.getAvailableValuesOfType(ParameterVector, OutputVector)
            if self.param.optional:
                self.combo.addItem(self.NOT_SELECTED, None)
            for table in tables:
                self.combo.addItem(self.dialog.resolveValueDescription(table), table)
            for layer in layers:
                self.combo.addItem(self.dialog.resolveValueDescription(layer), layer)

            widget = QWidget()
            layout = QHBoxLayout()
            layout.setMargin(0)
            layout.setContentsMargins(0, 0, 0, 0)
            layout.setSpacing(2)
            layout.addWidget(self.combo)
            btn = QToolButton()
            btn.setText('...')
            btn.setToolTip(self.tr("Select file"))
            btn.clicked.connect(self.selectFile)
            layout.addWidget(btn)
            widget.setLayout(layout)
            return widget
Exemple #7
0
 def createEditor(self, parent, option, index):
     # special combobox for field type
     if index.column() == 1:
         cbo = QComboBox(parent)
         cbo.setEditable(True)
         cbo.setAutoCompletion(True)
         cbo.setFrame(False)
         for item in self.fieldTypes:
             cbo.addItem(item)
         return cbo
     return QItemDelegate.createEditor(self, parent, option, index)
    def initGui(self):
        self.setWindowTitle('Import to GeoGig')
        verticalLayout = QVBoxLayout()

        if self.repo is None:
            repos = repository.repos
            layerLabel = QLabel('Repository')
            verticalLayout.addWidget(layerLabel)
            self.repoCombo = QComboBox()
            self.repoCombo.addItems(["%s - %s" % (r.group, r.title) for r in repos])
            self.repoCombo.currentIndexChanged.connect(self.updateBranches)
            verticalLayout.addWidget(self.repoCombo)
        if self.layer is None:
            layerLabel = QLabel('Layer')
            verticalLayout.addWidget(layerLabel)
            self.layerCombo = QComboBox()
            layerNames = [layer.name() for layer in vectorLayers()
                          if layer.source().lower().split("|")[0].split(".")[-1] in["gpkg", "geopkg"]
                          and not isRepoLayer(layer)]
            self.layerCombo.addItems(layerNames)
            verticalLayout.addWidget(self.layerCombo)

        self.branchLabel = QLabel("Branch")
        verticalLayout.addWidget(self.branchLabel)

        self.branchCombo = QComboBox()
        self.branches = self.repo.branches() if self.repo is not None else repos[0].branches()
        self.branchCombo.addItems(self.branches)
        verticalLayout.addWidget(self.branchCombo)

        messageLabel = QLabel('Message to describe this update')
        verticalLayout.addWidget(messageLabel)

        self.messageBox = QPlainTextEdit()
        verticalLayout.addWidget(self.messageBox)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Cancel)
        self.importButton = QPushButton("Add layer")
        self.importButton.clicked.connect(self.importClicked)
        self.buttonBox.addButton(self.importButton, QDialogButtonBox.ApplyRole)
        self.buttonBox.rejected.connect(self.cancelPressed)
        verticalLayout.addWidget(self.buttonBox)

        self.setLayout(verticalLayout)

        self.resize(600, 300)

        self.messageBox.setFocus()
Exemple #9
0
    def addLayerData(self, layerName, attribute):
        item = QTreeWidgetItem()
        item.setText(0, layerName)
        item.setText(1, attribute)
        self.layersTree.addTopLevelItem(item)

        comboBox = QComboBox()
        comboBox.addItem(self.tr('Points'))
        comboBox.addItem(self.tr('Structure lines'))
        comboBox.addItem(self.tr('Break lines'))
        comboBox.setCurrentIndex(0)
        self.layersTree.setItemWidget(item, 2, comboBox)
Exemple #10
0
    def __init__(self, param):
        super().__init__(param)

        self.label = QLabel('')

        self.units_combo = QComboBox()
        self.base_units = QgsUnitTypes.DistanceUnknownUnit
        for u in (QgsUnitTypes.DistanceMeters,
                  QgsUnitTypes.DistanceKilometers,
                  QgsUnitTypes.DistanceFeet,
                  QgsUnitTypes.DistanceMiles,
                  QgsUnitTypes.DistanceYards):
            self.units_combo.addItem(QgsUnitTypes.toString(u), u)

        label_margin = self.fontMetrics().width('X')
        self.layout().insertSpacing(1, label_margin / 2)
        self.layout().insertWidget(2, self.label)
        self.layout().insertWidget(3, self.units_combo)
        self.layout().insertSpacing(4, label_margin / 2)
        self.warning_label = QLabel()
        icon = QgsApplication.getThemeIcon('mIconWarning.svg')
        size = max(24, self.spnValue.height() * 0.5)
        self.warning_label.setPixmap(icon.pixmap(icon.actualSize(QSize(size, size))))
        self.warning_label.setToolTip(self.tr('Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results.'))
        self.layout().insertWidget(4, self.warning_label)
        self.layout().insertSpacing(5, label_margin)

        self.setUnits(QgsUnitTypes.DistanceUnknownUnit)
    def createWidget(self):
        self.panel = self.createPanel()
        self.panel.dialogType = self.dialogType

        if self.dialogType == DIALOG_MODELER:
            self.combobox = QComboBox()
            self.combobox.addItem(QCoreApplication.translate('Processing', '[Preconfigure]'), None)
            fieldsMappingInputs = self.dialog.getAvailableValuesOfType(FieldsMapper.ParameterFieldsMapping)
            for input in fieldsMappingInputs:
                self.combobox.addItem(self.dialog.resolveValueDescription(input), input)

            def updatePanelEnabledState():
                if self.combobox.currentData() is None:
                    self.panel.setEnabled(True)
                else:
                    self.panel.setEnabled(False)

            self.combobox.currentIndexChanged.connect(updatePanelEnabledState)

            widget = QWidget()
            widget.setLayout(QVBoxLayout())
            widget.layout().addWidget(self.combobox)
            widget.layout().addWidget(self.panel)
            return widget
        else:
            return self.panel
Exemple #12
0
 def createWidget(self):
     if self.dialogType == DIALOG_MODELER:
         widget = QComboBox()
         widget.setEditable(True)
         strings = self.dialog.getAvailableValuesOfType(QgsProcessingParameterString, QgsProcessingOutputString)
         options = [(self.dialog.resolveValueDescription(s), s) for s in strings]
         for desc, val in options:
             widget.addItem(desc, val)
         widget.setEditText(self.param.defaultValue() or '')
         return widget
     elif self.dialogType == DIALOG_BATCH:
         widget = QLineEdit()
         if self.param.defaultValue():
             widget.setText(self.param.defaultValue())
     else:
         return QgsRasterFormatSaveOptionsWidget()
 def createWidget(self):
     self._combo = QComboBox()
     self._combo.addItem('', '')
     for item in self.items():
         self._combo.addItem(item, item)
     self._combo.currentIndexChanged.connect(lambda:
                                             self.widgetValueHasChanged.emit(self))
     return self._combo
Exemple #14
0
    def addRow(self):
        self.wrappers.append([None] * self.tblParameters.columnCount())
        self.tblParameters.setRowCount(self.tblParameters.rowCount() + 1)

        wrappers = {}
        row = self.tblParameters.rowCount() - 1
        column = 0
        for param in self.alg.parameters:
            if param.hidden:
                continue

            wrapper = param.wrapper(self.parent, row, column)
            wrappers[param.name] = wrapper
            self.setCellWrapper(row, column, wrapper)
            column += 1

        for out in self.alg.outputs:
            if out.hidden:
                continue

            self.tblParameters.setCellWidget(
                row, column, BatchOutputSelectionPanel(
                    out, self.alg, row, column, self))
            column += 1

        if self.alg.getVisibleOutputsCount():
            item = QComboBox()
            item.addItem(self.tr('Yes'))
            item.addItem(self.tr('No'))
            item.setCurrentIndex(0)
            self.tblParameters.setCellWidget(row, column, item)

        for wrapper in list(wrappers.values()):
            wrapper.postInitialize(list(wrappers.values()))
Exemple #15
0
    def addRow(self):
        self.wrappers.append([None] * self.tblParameters.columnCount())
        self.tblParameters.setRowCount(self.tblParameters.rowCount() + 1)

        wrappers = {}
        row = self.tblParameters.rowCount() - 1
        column = 0
        for param in self.alg.parameterDefinitions():
            if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination():
                continue

            wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent, row, column)
            wrappers[param.name()] = wrapper
            self.setCellWrapper(row, column, wrapper)
            column += 1

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

            self.tblParameters.setCellWidget(
                row, column, BatchOutputSelectionPanel(
                    out, self.alg, row, column, self))
            column += 1

        if len(self.alg.destinationParameterDefinitions()) > 0:
            item = QComboBox()
            item.addItem(self.tr('Yes'))
            item.addItem(self.tr('No'))
            item.setCurrentIndex(0)
            self.tblParameters.setCellWidget(row, column, item)

        for wrapper in list(wrappers.values()):
            wrapper.postInitialize(list(wrappers.values()))
Exemple #16
0
    def addRow(self):
        self.tblParameters.setRowCount(self.tblParameters.rowCount() + 1)

        row = self.tblParameters.rowCount() - 1
        column = 0
        for param in self.alg.parameters:
            if param.hidden:
                continue

            self.tblParameters.setCellWidget(
                row, column, self.getWidgetFromParameter(param, row, column))
            column += 1

        for out in self.alg.outputs:
            if out.hidden:
                continue

            self.tblParameters.setCellWidget(
                row, column, BatchOutputSelectionPanel(
                    out, self.alg, row, column, self))
            column += 1

        if self.alg.getVisibleOutputsCount():
            item = QComboBox()
            item.addItem(self.tr('Yes'))
            item.addItem(self.tr('No'))
            item.setCurrentIndex(0)
            self.tblParameters.setCellWidget(row, column, item)
 def setComboField(self,content,type,layer):
     '''
     returns a qcombobox loaded with compatible field names (depending on selected layer)
     '''
     combo = QComboBox();
     fieldNames = self.scanLayerFieldsNames(layer)
     fieldTypes = self.scanLayerFieldsTypes(layer)
     choices = []
     for n in range(0,len(fieldTypes)):
         if fieldTypes[n] == type:
             choices.append(fieldNames[n])
     combo.addItems(choices)
     if content in choices:
         combo.setCurrentIndex(choices.index(content))
     else:
         combo.addItem(content)
         combo.setCurrentIndex(combo.count()-1)
     combo.activated.connect(lambda: self.highlightCompatibleFields(LayerChange=None))
     return combo
 def _reverseAdresCallback(self, point):
     'private callback for reverseAdresMapTool'
     self.iface.mapCanvas().unsetMapTool(self.reverseAdresTool)
     self.showNormal()
     self.activateWindow()
 
     x,y = self.gh.prjPtFromMapCrs(point, 31370)
     adres = str(x) +","+ str(y)
 
     validAdresCol = self.ui.outPutTbl.columnCount() -1
     rowIds= self.getSelectedRows()
     for rowIdx in rowIds:
         validCombo = QComboBox(self.ui.adresColSelect)
         validCombo.addItems([adres])
         validCombo.setEnabled(False)
         self.ui.outPutTbl.setCellWidget(rowIdx, validAdresCol, validCombo)
         for col in range(validAdresCol):
             self.ui.outPutTbl.item(rowIdx,col).setBackground( QBrush( QColor("#DDFFDD")) )
         self.ui.outPutTbl.clearSelection()
    def initGui(self):
        self.setWindowTitle('Remote connection reference')
        verticalLayout = QVBoxLayout()

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(30)
        horizontalLayout.setMargin(0)
        remoteLabel = QLabel('Remote connection')
        self.remoteCombo = QComboBox()
        self.remotes = self.repo.remotes()
        self.remoteCombo.addItems(list(self.remotes.keys()))
        self.remoteCombo.currentIndexChanged.connect(self.currentRemoteChanged)
        horizontalLayout.addWidget(remoteLabel)
        horizontalLayout.addWidget(self.remoteCombo)
        verticalLayout.addLayout(horizontalLayout)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(30)
        horizontalLayout.setMargin(0)
        branchLabel = QLabel('Branch')
        self.branchCombo = QComboBox()
        self.branchCombo.addItems(self.repo.branches())
        horizontalLayout.addWidget(branchLabel)
        horizontalLayout.addWidget(self.branchCombo)
        verticalLayout.addLayout(horizontalLayout)

        self.groupBox = QGroupBox()
        self.groupBox.setTitle("Remote connection info")
        self.groupBox.setLayout(verticalLayout)

        layout = QVBoxLayout()
        layout.addWidget(self.groupBox)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        layout.addWidget(self.buttonBox)

        self.setLayout(layout)

        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)

        self.resize(400, 200)
Exemple #20
0
    def createEditor(self, parent, option, index):
        column = index.column()

        fieldType = FieldsMappingModel.columns[column]['type']
        if fieldType == QVariant.Type:
            editor = QComboBox(parent)
            for key, text in list(FieldsMappingModel.fieldTypes.items()):
                editor.addItem(text, key)

        elif fieldType == QgsExpression:
            editor = QgsFieldExpressionWidget(parent)
            editor.setLayer(index.model().layer())
            editor.registerExpressionContextGenerator(index.model().contextGenerator())
            editor.fieldChanged.connect(self.on_expression_fieldChange)

        else:
            editor = QStyledItemDelegate.createEditor(self, parent, option, index)

        editor.setAutoFillBackground(True)
        return editor
    def restoreState(self,layer,table):
        if layer.id() in self.states.keys():
            table.blockSignals(True)
            #clear dock widget
            while table.rowCount()>0:
                table.removeRow(0)
            #add rows
            table.setRowCount(len(self.states[layer.id()]))
            for n in range(0, len(self.states[layer.id()])):
                row = self.states[layer.id()][n]
                #set first column as checkbox
                item=QTableWidgetItem()
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                if row[0]:
                    item.setCheckState(Qt.Checked)
                else:
                    item.setCheckState(Qt.Unchecked)
                item.setText("")
                table.setItem(n,0,item)
                #set second column as combobox
                combo = QComboBox();
                combo.addItems(row[1])
                #print (row[1],row[2])
                combo.setCurrentIndex(row[2])
                table.setCellWidget(n,1,combo)
                #set third column as attribute value
                item = QTableWidgetItem(row[3])
                item.setData(Qt.DisplayRole,row[4])
                if row[5]:
                    item.setForeground(QBrush(QColor(0,0,0)))
                else:
                    item.setForeground(QBrush(QColor(130,130,130)))
                if row[6]:
                    item.setBackground(QBrush(QColor(183,213,225)))
                table.setItem(n,2,item)

            table.blockSignals(False)
            return True

        else:
            return None
Exemple #22
0
    def createWidget(self, connection_param=None):
        self._connection_param = connection_param
        self._connection = None
        self._database = None

        self._combo = QComboBox()
        self._combo.setEditable(True)
        self.refreshItems()
        self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
        self._combo.lineEdit().editingFinished.connect(lambda: self.widgetValueHasChanged.emit(self))

        return self.wrapWithExpressionButton(self._combo)
    def createWidget(self, schema_param=None):
        self._schema_param = schema_param
        self._database = None
        self._schema = None

        self._combo = QComboBox()
        self._combo.setEditable(True)
        self.refreshItems()
        self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
        self._combo.lineEdit().editingFinished.connect(lambda: self.widgetValueHasChanged.emit(self))

        return self._combo
Exemple #24
0
 def createWidget(self):
     if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
         return PointSelectionPanel(self.dialog, self.param.default)
     else:
         item = QComboBox()
         item.setEditable(True)
         points = self.dialog.getAvailableValuesOfType(ParameterPoint)
         for p in points:
             item.addItem(self.dialog.resolveValueDescription(p), p)
         item.setEditText(str(self.param.default))
         return item
class MapThemeWrapper(BasicWidgetWrapper):
    """
    WidgetWrapper for ParameterString that createe a combobox widget
    with the existing map themes.
    """

    def createWidget(self):
        self._combo = QComboBox()
        self._combo.addItem('', '')
        for item in self.items():
            self._combo.addItem(item, item)
        self._combo.currentIndexChanged.connect(lambda:
                                                self.widgetValueHasChanged.emit(self))
        return self._combo

    def items(self):
        return QgsProject.instance().mapThemeCollection().mapThemes()

    def setValue(self, value):
        self.setComboValue(value, self._combo)

    def value(self):
        return self.comboValue(combobox=self._combo)
    def __init__(self, expression, options):
        super(PredefinedExpressionDialog, self).__init__()
        self.setupUi(self)

        self.filledExpression = None
        self.options = options
        self.expression = expression
        self.variables = set(re.findall('\[.*?\]', expression))
        self.comboBoxes = {}
        for variable in self.variables:
            label = QLabel(variable[1:-1])
            combo = QComboBox()
            for opt in self.options.keys():
                combo.addItem(opt)
            self.comboBoxes[variable] = combo
            self.groupBox.layout().addWidget(label)
            self.groupBox.layout().addWidget(combo)

        verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.groupBox.layout().addItem(verticalSpacer)

        self.buttonBox.rejected.connect(self.cancelPressed)
        self.buttonBox.accepted.connect(self.okPressed)
 def __init__(self, parent, tree, providerName, param):
     QTreeWidgetItem.__init__(self, parent)
     self.providereName = providerName
     self.param = param
     self.tree = tree
     self.setText(0, param.description)
     self.paramName = settingName(providerName, param.name)
     if isinstance(param.defaultValue, bool):
         self.value = QSettings().value(self.paramName, defaultValue=param.defaultValue, type=bool)
         if self.value:
             self.setCheckState(1, Qt.Checked)
         else:
             self.setCheckState(1, Qt.Unchecked)
     elif isinstance(param.defaultValue, list):
         self.combo = QComboBox()
         for element in param.defaultValue:
             self.combo.addItem(element)
         self.tree.setItemWidget(self, 1, self.combo)
         self.value = QSettings().value(self.paramName, defaultValue=param.defaultValue[0])
         idx = self.combo.findText(self.value)
         self.combo.setCurrentIndex(idx)
     elif param.description == "Password":
         self.passwordField = QLineEdit()
         self.passwordField.setEchoMode(QLineEdit.Password);
         #self.passwordField.setStyleSheet("QLineEdit { border: none }");
         self.value = QSettings().value(self.paramName, defaultValue=param.defaultValue)
         self.passwordField.setText(str(self.value))
         self.tree.setItemWidget(self, 1, self.passwordField)
     elif param.action is not None:
         layout = QHBoxLayout()
         layout.setMargin(0)
         layout.setSpacing(0)
         self.textbox = QLineEdit()
         self.value = QSettings().value(self.paramName, defaultValue=param.defaultValue)
         self.textbox.setText(str(self.value))
         layout.addWidget(self.textbox)
         self.button = QToolButton()
         self.button.setText(param.actionText)
         self.button.clicked.connect(param.action)
         layout.addWidget(self.button)
         self.widget = QWidget()
         self.widget.setLayout(layout)
         self.tree.setItemWidget(self, 1, self.widget)
     else:
         self.textbox = QLineEdit()
         #self.textbox.setStyleSheet("QLineEdit { border: none }");
         self.tree.setItemWidget(self, 1, self.textbox)
         self.value = QSettings().value(self.paramName, defaultValue=param.defaultValue)
         self.textbox.setText(str(self.value))
 def __init__(self, options, parent=None):
     super(MultilineTextPanel, self).__init__(parent)
     self.options = options
     self.verticalLayout = QVBoxLayout(self)
     self.verticalLayout.setSpacing(2)
     self.verticalLayout.setMargin(0)
     self.combo = QComboBox()
     self.combo.addItem(self.tr("[Use text below]"))
     for option in options:
         self.combo.addItem(option[0], option[1])
     self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     self.verticalLayout.addWidget(self.combo)
     self.textBox = QPlainTextEdit()
     self.verticalLayout.addWidget(self.textBox)
     self.setLayout(self.verticalLayout)
Exemple #29
0
 def createWidget(self):
     if self.param.multiple:
         return MultipleInputPanel(options=self.param.options)
     else:
         widget = QComboBox()
         for option in self.param.options:
             widget.addItem(option[1], option[0])
         if self.param.default:
             widget.setCurrentIndex(widget.findData(self.param.default))
         return widget
Exemple #30
0
    def createWidget(self):
        self._layer = None

        if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
            if self.param.multiple:
                return MultipleInputPanel(options=[])
            else:
                widget = QComboBox()
                return widget
        else:
            widget = QComboBox()
            widget.setEditable(True)
            fields = self.dialog.getAvailableValuesOfType(ParameterTableField, None)
            if self.param.optional:
                widget.addItem(self.NOT_SET, None)
            for f in fields:
                widget.addItem(self.dialog.resolveValueDescription(f), f)
            return widget
Exemple #31
0
    def __init__(self):
        QDialog.__init__(self)

        self.setWindowTitle(tr('DMS Point Tool'))

        self.lat_D = QLineEdit()
        self.lat_M = QLineEdit()
        self.lat_S = QLineEdit()
        self.lat_DM = QLineEdit()
        self.lon_D = QLineEdit()
        self.lon_M = QLineEdit()
        self.lon_S = QLineEdit()
        self.lon_DM = QLineEdit()

        self.lat_M.textEdited.connect(self.lat_MS_edited)
        self.lat_S.textEdited.connect(self.lat_MS_edited)
        self.lat_DM.textEdited.connect(self.lat_DM_edited)
        self.lon_M.textEdited.connect(self.lon_MS_edited)
        self.lon_S.textEdited.connect(self.lon_MS_edited)
        self.lon_DM.textEdited.connect(self.lon_DM_edited)

        int_val = QIntValidator()
        int_val.setBottom(0)

        float_val = QDoubleValidator()
        float_val.setBottom(0)

        self.lat_D.setValidator(int_val)
        self.lat_M.setValidator(int_val)
        self.lat_S.setValidator(float_val)
        self.lat_DM.setValidator(float_val)

        self.lon_D.setValidator(int_val)
        self.lon_M.setValidator(int_val)
        self.lon_S.setValidator(float_val)
        self.lon_DM.setValidator(float_val)

        self.lat_NS = QComboBox()
        self.lat_NS.addItem("N")
        self.lat_NS.addItem("S")

        self.lon_EW = QComboBox()
        self.lon_EW.addItem("E")
        self.lon_EW.addItem("W")

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

        lat_grp = QGroupBox(tr("Latitude"), self)
        lat_grp.setStyleSheet(
            "QGroupBox { font-weight: bold; color: #3c3c3c; } ")
        lat_grid = QGridLayout()
        lat_grid.addWidget(QLabel(tr("Degrees")), 0, 0)
        lat_grid.addWidget(QLabel(tr("Minutes")), 0, 1)
        lat_grid.addWidget(QLabel(tr("Seconds")), 0, 2)
        lat_grid.addWidget(QLabel(tr("Direction")), 0, 3)
        lat_grid.addWidget(self.lat_D, 1, 0)
        lat_grid.addWidget(self.lat_M, 1, 1)
        lat_grid.addWidget(self.lat_S, 1, 2)
        lat_grid.addWidget(self.lat_NS, 1, 3)
        lat_grid.addWidget(QLabel(tr("Decimal minutes")), 2, 1)
        lat_grid.addWidget(self.lat_DM, 3, 1, 1, 2)
        lat_grp.setLayout(lat_grid)

        lon_grp = QGroupBox(tr("Longitude"), self)
        lon_grp.setStyleSheet(
            "QGroupBox { font-weight: bold; color: #3c3c3c; } ")
        lon_grid = QGridLayout()
        lon_grid.addWidget(QLabel(tr("Degrees")), 0, 0)
        lon_grid.addWidget(QLabel(tr("Minutes")), 0, 1)
        lon_grid.addWidget(QLabel(tr("Seconds")), 0, 2)
        lon_grid.addWidget(QLabel(tr("Direction")), 0, 3)
        lon_grid.addWidget(self.lon_D, 1, 0)
        lon_grid.addWidget(self.lon_M, 1, 1)
        lon_grid.addWidget(self.lon_S, 1, 2)
        lon_grid.addWidget(self.lon_EW, 1, 3)
        lon_grid.addWidget(QLabel(tr("Decimal minutes")), 2, 1)
        lon_grid.addWidget(self.lon_DM, 3, 1, 1, 2)
        lon_grp.setLayout(lon_grid)

        vbox = QVBoxLayout()
        vbox.addWidget(lat_grp)
        vbox.addWidget(lon_grp)
        vbox.addWidget(buttons)

        self.setLayout(vbox)
Exemple #32
0
class TreeLayerItem(QTreeWidgetItem):
    layerIcon = QIcon(
        os.path.join(os.path.dirname(__file__), "icons", "layer.png"))

    def __init__(self, iface, layer, tree, dlg):
        QTreeWidgetItem.__init__(self)
        self.iface = iface
        self.layer = layer
        self.setText(0, layer.name())
        self.setIcon(0, self.layerIcon)
        project = QgsProject.instance()
        if project.layerTreeRoot().findLayer(layer.id()).isVisible():
            self.setCheckState(0, Qt.Checked)
        else:
            self.setCheckState(0, Qt.Unchecked)
        self.visibleItem = QTreeWidgetItem(self)
        self.visibleCheck = QCheckBox()
        vis = layer.customProperty("qgis2web/Visible", True)
        if vis == 0 or str(vis).lower() == "false":
            self.visibleCheck.setChecked(False)
        else:
            self.visibleCheck.setChecked(True)
        self.visibleItem.setText(0, "Visible")
        self.addChild(self.visibleItem)
        tree.setItemWidget(self.visibleItem, 1, self.visibleCheck)
        self.interactiveItem = QTreeWidgetItem(self)
        self.interactiveCheck = QCheckBox()
        int = True
        if int == 0 or str(int).lower() == "false":
            self.interactiveCheck.setChecked(False)
        else:
            self.interactiveCheck.setChecked(True)
        self.interactiveItem.setText(0, "Popups")
        self.addChild(self.interactiveItem)
        tree.setItemWidget(self.interactiveItem, 1, self.interactiveCheck)
        if layer.type() == layer.VectorLayer:
            if layer.providerType() == 'WFS':
                self.jsonItem = QTreeWidgetItem(self)
                self.jsonCheck = QCheckBox()
                if layer.customProperty("qgis2web/Encode to JSON") == 2:
                    self.jsonCheck.setChecked(True)
                self.jsonItem.setText(0, "Encode to JSON")
                self.jsonCheck.stateChanged.connect(self.changeJSON)
                self.addChild(self.jsonItem)
                tree.setItemWidget(self.jsonItem, 1, self.jsonCheck)
            if layer.geometryType() == QgsWkbTypes.PointGeometry:
                self.clusterItem = QTreeWidgetItem(self)
                self.clusterCheck = QCheckBox()
                if layer.customProperty("qgis2web/Cluster") == 2:
                    self.clusterCheck.setChecked(True)
                self.clusterItem.setText(0, "Cluster")
                self.clusterCheck.stateChanged.connect(self.changeCluster)
                self.addChild(self.clusterItem)
                tree.setItemWidget(self.clusterItem, 1, self.clusterCheck)
            self.popupItem = QTreeWidgetItem(self)
            self.popupItem.setText(0, "Popup fields")
            options = []
            fields = self.layer.fields()
            for f in fields:
                fieldIndex = fields.indexFromName(f.name())
                editorWidget = layer.editorWidgetSetup(fieldIndex).type()
                if editorWidget == 'Hidden':
                    continue
                options.append(f.name())
            for option in options:
                self.attr = QTreeWidgetItem(self)
                self.attrWidget = QComboBox()
                self.attrWidget.addItem("no label")
                self.attrWidget.addItem("inline label")
                self.attrWidget.addItem("header label")
                custProp = layer.customProperty("qgis2web/popup/" + option)
                if (custProp != "" and custProp is not None):
                    self.attrWidget.setCurrentIndex(
                        self.attrWidget.findText(
                            layer.customProperty("qgis2web/popup/" + option)))
                self.attr.setText(1, option)
                self.popupItem.addChild(self.attr)
                tree.setItemWidget(self.attr, 2, self.attrWidget)
            self.addChild(self.popupItem)
        else:
            if layer.providerType() == 'wms':
                self.getFeatureInfoItem = QTreeWidgetItem(self)
                self.getFeatureInfoCheck = QCheckBox()
                if layer.customProperty("qgis2web/GetFeatureInfo") == 2:
                    self.getFeatureInfoCheck.setChecked(True)
                self.getFeatureInfoItem.setText(0, "Enable GetFeatureInfo?")
                self.getFeatureInfoCheck.stateChanged.connect(
                    self.changeGetFeatureInfo)
                self.addChild(self.getFeatureInfoItem)
                tree.setItemWidget(self.getFeatureInfoItem, 1,
                                   self.getFeatureInfoCheck)

    @property
    def popup(self):
        popup = []
        self.tree = self.treeWidget()
        for p in range(self.childCount()):
            item = self.child(p).text(1)
            if item != "":
                popupVal = self.tree.itemWidget(self.child(p), 2).currentText()
                pair = (item, popupVal)
                popup.append(pair)
        popup = OrderedDict(popup)
        return popup

    @property
    def visible(self):
        return self.visibleCheck.isChecked()

    @property
    def interactive(self):
        return self.interactiveCheck.isChecked()

    @property
    def json(self):
        try:
            return self.jsonCheck.isChecked()
        except Exception:
            return False

    @property
    def cluster(self):
        try:
            return self.clusterCheck.isChecked()
        except Exception:
            return False

    @property
    def getFeatureInfo(self):
        try:
            return self.getFeatureInfoCheck.isChecked()
        except Exception:
            return False

    def changeJSON(self, isJSON):
        self.layer.setCustomProperty("qgis2web/Encode to JSON", isJSON)

    def changeCluster(self, isCluster):
        self.layer.setCustomProperty("qgis2web/Cluster", isCluster)

    def changeGetFeatureInfo(self, isGetFeatureInfo):
        self.layer.setCustomProperty("qgis2web/GetFeatureInfo",
                                     isGetFeatureInfo)
Exemple #33
0
    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter definition'))
        self.setMinimumWidth(300)

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

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

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

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

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

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

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

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

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

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

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

        self.setLayout(self.verticalLayout)
Exemple #34
0
class SchemaWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin):
    """
    WidgetWrapper for ParameterString that create and manage a combobox widget
    with existing schemas from a parent connection parameter.
    """
    def createWidget(self, connection_param=None):
        self._connection_param = connection_param
        self._connection = None
        self._database = None

        self._combo = QComboBox()
        self._combo.setEditable(True)
        self.refreshItems()
        self._combo.currentIndexChanged.connect(
            lambda: self.widgetValueHasChanged.emit(self))
        self._combo.lineEdit().editingFinished.connect(
            lambda: self.widgetValueHasChanged.emit(self))

        return self.wrapWithExpressionButton(self._combo)

    def postInitialize(self, wrappers):
        for wrapper in wrappers:
            if wrapper.param.name == self._connection_param:
                self.connection_wrapper = wrapper
                self.setConnection(wrapper.value())
                wrapper.widgetValueHasChanged.connect(self.connectionChanged)
                break

    def connectionChanged(self, wrapper):
        connection = wrapper.value()
        if connection == self._connection:
            return
        self.setConnection(connection)

    def setConnection(self, connection):
        self._connection = connection
        if isinstance(connection, str):
            self._database = GeoDB.from_name(connection)
        else:
            self._database = None
        self.refreshItems()
        self.widgetValueHasChanged.emit(self)

    def refreshItems(self):
        value = self.comboValue(combobox=self._combo)

        self._combo.clear()

        if self._database is not None:
            for schema in self._database.list_schemas():
                self._combo.addItem(schema[1], schema[1])

        if self.dialogType == DIALOG_MODELER:
            strings = self.dialog.getAvailableValuesOfType([
                ParameterString, ParameterNumber, ParameterFile,
                ParameterTableField, ParameterExpression
            ], OutputString)
            for text, data in [(self.dialog.resolveValueDescription(s), s)
                               for s in strings]:
                self._combo.addItem(text, data)

        self.setComboValue(value, self._combo)

    def setValue(self, value):
        self.setComboValue(value, self._combo)
        self.widgetValueHasChanged.emit(self)

    def value(self):
        return self.comboValue(combobox=self._combo)

    def database(self):
        return self._database
Exemple #35
0
class TreeSettingItem(QTreeWidgetItem):
    def __init__(self, parent, tree, name, value, action=None):
        QTreeWidgetItem.__init__(self, parent)
        self.parent = parent
        self.tree = tree
        self.name = name
        self._value = value
        self.combo = None
        self.list = None
        self.setText(0, name)
        widget = None
        if isinstance(value, QgsColorButton):
            widget = value
        elif isinstance(value, bool):
            if value:
                self.setCheckState(1, Qt.Checked)
            else:
                self.setCheckState(1, Qt.Unchecked)
        elif isinstance(value, tuple):
            self.combo = QComboBox()
            self.combo.setSizeAdjustPolicy(0)
            for option in value:
                self.combo.addItem(option)
            widget = self.combo
        elif isinstance(value, list):
            self.list = QListWidget()
            self.list.setSizeAdjustPolicy(0)
            self.list.setSelectionMode(QListWidget.MultiSelection)
            for option in value:
                self.list.addItem(option)
            widget = self.list
        else:
            self.setText(1, unicode(value))

        if action:
            layout = QHBoxLayout()
            layout.setMargin(0)
            if widget:
                layout.addWidget(widget)
            button = QToolButton()
            button.setDefaultAction(action)
            button.setText(action.text())
            layout.addWidget(button)
            layout.addStretch(1)
            widget = QWidget()
            widget.setLayout(layout)

        if widget:
            self.tree.setItemWidget(self, 1, widget)

    def setValue(self, value):
        if isinstance(value, bool):
            if value:
                self.setCheckState(1, Qt.Checked)
            else:
                self.setCheckState(1, Qt.Unchecked)
        elif self.combo:
            index = self.combo.findText(value)
            if index != -1:
                self.combo.setCurrentIndex(index)
        else:
            self.setText(1, str(value))

    def value(self):
        if isinstance(self._value, bool):
            return self.checkState(1) == Qt.Checked
        elif isinstance(self._value, (int, float)):
            return float(self.text(1))
        elif isinstance(self._value, tuple):
            return self.combo.currentText()
        else:
            return self.text(1)
Exemple #36
0
class oiv:
    #initialize class attributes

    read_config_bl = []
    read_config_obj = []
    min_bouwlaag = -10
    max_bouwlaag = 30
    check_visible = False
    draw_layer = None
    place_feature = None
    soort_info = None

    # Save reference to the QGIS interface
    def __init__(self, iface):
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.pandidentifyTool = IdentifyPandTool(self.canvas)
        self.identifyTool = IdentifyGeometryTool(self.canvas)
        self.pinTool = QgsMapToolEmitPoint(self.canvas)
        self.tekenTool = SnapPointTool(self.canvas)
        self.selectTool = SelectTool(self.canvas)
        self.pinLine = CaptureTool(self.canvas)
        self.pinPolygon = CaptureTool(self.canvas)
        self.moveTool = MovePointTool(self.canvas, self.draw_layer)
        self.read_config_bl = self.read_config_file(
            "/config_files/csv/config_bouwlaag.csv")

    def initGui(self):
        #init actions plugin
        self.toolbar = self.iface.addToolBar("OIV Objecten")
        self.action = QAction(
            QIcon(":/plugins/oiv/config_files/png/oiv_plugin.png"),
            "OIV Objecten", self.iface.mainWindow())
        self.action.triggered.connect(self.run)
        self.toolbar.addAction(self.action)
        self.iface.addPluginToMenu('&OIV Objecten', self.action)
        self.settings = QAction(
            QIcon(":/plugins/oiv/config_files/png/settings.png"), "Settings",
            self.iface.mainWindow())
        self.settings.triggered.connect(self.run_config)
        self.iface.addPluginToMenu('&OIV Objecten', self.settings)
        #add label to toolbar
        self.label = QLabel(self.iface.mainWindow())
        self.labelAction = self.toolbar.addWidget(self.label)
        self.label.setText("OIV 3.0.9 | Actieve bouwlaag: ")
        #init dropdown to switch floors
        self.projCombo = QComboBox(self.iface.mainWindow())
        for i in range(self.max_bouwlaag - self.min_bouwlaag + 1):
            if self.max_bouwlaag - i != 0:
                if self.max_bouwlaag - i == 1:
                    init_index = i
                self.projCombo.addItem(str(self.max_bouwlaag - i))
        self.projComboAction = self.toolbar.addWidget(self.projCombo)
        self.projCombo.setFixedWidth(100)
        self.projCombo.setMaxVisibleItems(30)
        #set intial index to floor 1
        self.projCombo.setCurrentIndex(init_index)
        #connect to set layer subset if the index is changed
        self.projCombo.currentIndexChanged.connect(
            self.set_layer_subset_toolbar)
        #init projectVariable to communicate from plugin to original drawing possibilities
        project = QgsProject.instance()
        QgsExpressionContextUtils.setProjectVariable(project,
                                                     'actieve_bouwlaag', 1)

    def close_basewidget(self):
        #close plugin and re-activate toolbar combobox
        self.basewidget.close()
        self.toolbar.setEnabled(True)
        self.projCombo.setEnabled(True)
        self.check_visible = False

    # Read lines from input file and convert to list to link the signal and slots
    def read_config_file(self, file):
        config_list = []
        basepath = os.path.dirname(os.path.realpath(__file__))
        with open(basepath + file, 'r') as inp_file:
            lines = inp_file.read().splitlines()
        for line in lines:
            config_list.append(line.split(','))
        inp_file.close()
        return config_list

    #remove the plugin menu item and remove the widgets
    def unload(self):
        try:
            del self.basewidget
        except:
            None
        try:
            del self.objectwidget
        except:
            None
        try:
            del self.objectnieuwwidget
        except:
            None
        self.iface.removePluginMenu("&OIV Objecten", self.action)
        self.iface.removePluginMenu("&OIV Objecten", self.settings)
        self.projCombo.currentIndexChanged.disconnect()
        self.action.triggered.disconnect()
        self.settings.triggered.disconnect()
        del self.toolbar
        self.check_visible = None
        self.iface.removeToolBarIcon(self.action)

    def run_config(self):
        question = "Geef het wachtwoord:"
        qid = QInputDialog()
        password, ok = QInputDialog.getText(
            qid,
            "Password:"******"01v":
            self.configwidget = oivConfigWidget()
            self.iface.addDockWidget(Qt.RightDockWidgetArea, self.configwidget)
            self.configwidget.show()
        else:
            QMessageBox.information(None, "DEBUG:", "Verkeerd password!")

    #get the identification of a pand from the user
    def run_identify_pand(self):
        self.soort_info = 'pand'
        self.canvas.setMapTool(self.pandidentifyTool)
        self.pandidentifyTool.pandIdentified.connect(self.get_identified_pand)

    def run_identify_gebouw_terrein(self):
        self.soort_info = 'gebouw_terrein'
        self.canvas.setMapTool(self.pandidentifyTool)
        self.pandidentifyTool.pandIdentified.connect(
            self.get_identified_gebouw_terrein)

    #Return of identified layer and feature and get related object
    def get_identified_pand(self, ilayer, ifeature):
        #the identified layer must be "bouwlagen" or "BAG panden"
        if ilayer.name() == "Bouwlagen":
            #get_draw_layer_attr -> get attribute of identified layer from the config_file: Input (layername, attributename, searchable_config_list)
            objectId = str(ifeature["pand_id"])
            #open dockwidget object and pass along the identified object and feature
            self.run_bouwlagen()
            self.objectwidget.existing_object(ifeature, objectId)
        #a new object has to be created if a BAG pand was identified objectId -> Bag identificatie nummer
        elif ilayer.name() == "BAG panden":
            objectId = str(ifeature["identificatie"])
            #open dockwidget object and pass along the identified object and feature
            self.run_bouwlagen()
            self.objectwidget.existing_object(ifeature, objectId)
        #if another layer is identified there is no object that can be determined, so a message is send to the user
        else:
            QMessageBox.information(
                None, "Oeps:", "Geen pand gevonden! Klik boven op een pand.")
        self.pandidentifyTool.pandIdentified.disconnect()

    #Return of identified layer and feature and get related object
    def get_identified_gebouw_terrein(self, ilayer, ifeature):
        #the identified layer must be "bouwlagen" or "BAG panden"
        if ilayer == None:
            self.run_new_object('wordt gekoppeld in de database', 'BGT',
                                'wordt gekoppeld in de database')
        elif ilayer.name() == "Objecten" or ilayer.name() == "Object terrein":
            #get_draw_layer_attr -> get attribute of identified layer from the config_file: Input (layername, attributename, searchable_config_list)
            objectId = ifeature["id"]
            #if ifeature["bron"] == 'BAG':
            self.draw_layer = getlayer_byname("Objecten")
            #else:
            #    self.draw_layer = getlayer_byname("Objecten BGT")
            #open dockwidget object and pass along the identified object and feature
            self.run_object()
            self.repressiefobjectwidget.existing_object(ifeature, objectId)
            #a new object has to be created if a BAG pand was identified objectId -> Bag identificatie nummer
        elif ilayer.name() == "BAG panden":
            objectId = str(ifeature["identificatie"])
            bron = ifeature["bron"]
            bron_tabel = ifeature["bron_tbl"]
            self.run_new_object(objectId, bron, bron_tabel)
        elif ilayer.name() == "Bouwlagen":
            objectId = str(ifeature["pand_id"])
            bron = 'BAG'
            bron_tabel = 'pand'
            #open dockwidget object and pass along the identified object and feature
            self.run_new_object(objectId, bron, bron_tabel)
        else:
            QMessageBox.information(
                None, "Oeps:",
                "Geen repressief object gevonden! Selecteer opnieuw.")
        self.pandidentifyTool.pandIdentified.disconnect()

    #laag filter aanpassen naar de geselecteerd bouwlaag
    def set_layer_subset_toolbar(self):
        QgsExpressionContextUtils.setProjectVariable(
            QgsProject.instance(), 'actieve_bouwlaag',
            int(self.projCombo.currentText()))
        sub_string = "bouwlaag = " + str(self.projCombo.currentText())
        set_layer_substring(self.read_config_bl, sub_string)

    #pass on the tools to objectgegevens widget, intitializing the tools in the sub widget, draws an error
    def init_object_widget(self):
        #Load configuration file
        self.objectwidget = oivObjectWidget()
        self.objectwidget.read_config = self.read_config_bl
        self.objectwidget.canvas = self.canvas
        self.objectwidget.selectTool = self.selectTool
        self.objectwidget.basewidget = self.basewidget
        self.objectwidget.tekenTool = self.tekenTool
        self.objectwidget.lineTool = self.pinLine
        self.objectwidget.polygonTool = self.pinPolygon
        self.objectwidget.moveTool = self.moveTool
        self.objectwidget.identifyTool = self.identifyTool

    #pass on the tools to objectgegevens widget, intitializing the tools in the sub widget, draws an error
    def init_repressief_object_widget(self):
        self.read_config_obj = self.read_config_file(
            "/config_files/csv/config_object.csv")
        self.repressiefobjectwidget = oivRepressiefObjectWidget()
        self.repressiefobjectwidget.read_config = self.read_config_obj
        self.repressiefobjectwidget.canvas = self.canvas
        self.repressiefobjectwidget.draw_layer = self.draw_layer
        self.repressiefobjectwidget.selectTool = self.selectTool
        self.repressiefobjectwidget.basewidget = self.basewidget
        self.repressiefobjectwidget.tekenTool = self.tekenTool
        self.repressiefobjectwidget.lineTool = self.pinLine
        self.repressiefobjectwidget.polygonTool = self.pinPolygon
        self.repressiefobjectwidget.moveTool = self.moveTool
        self.repressiefobjectwidget.identifyTool = self.identifyTool
        #self.repressiefobjectwidget.connect_buttons(self.read_config_obj)

    #start objectgegevens widget
    def run_bouwlagen(self):
        self.init_object_widget()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.objectwidget)
        self.iface.actionPan().trigger()
        self.objectwidget.show()
        self.basewidget.close()

    def run_object(self):
        self.init_repressief_object_widget()
        self.iface.addDockWidget(Qt.RightDockWidgetArea,
                                 self.repressiefobjectwidget)
        self.iface.actionPan().trigger()
        self.repressiefobjectwidget.show()
        self.basewidget.close()

    #start new object widget, eventhough passing trough the tools to objectgegevens widget
    def run_new_object(self, objectId, bron, bron_tbl):
        self.init_repressief_object_widget()
        self.objectnieuwwidget = oivObjectNieuwWidget()
        self.objectnieuwwidget.basewidget = self.basewidget
        self.objectnieuwwidget.objectwidget = self.repressiefobjectwidget
        self.iface.addDockWidget(Qt.RightDockWidgetArea,
                                 self.objectnieuwwidget)
        self.objectnieuwwidget.read_config = self.read_config_obj
        self.objectnieuwwidget.canvas = self.canvas
        self.objectnieuwwidget.mapTool = self.pinTool
        self.objectnieuwwidget.identificatienummer.setText(str(objectId))
        self.objectnieuwwidget.bron.setText(str(bron))
        self.objectnieuwwidget.bron_table.setText(str(bron_tbl))
        self.iface.actionPan().trigger()
        self.objectnieuwwidget.show()
        self.basewidget.close()

    #run the plugin, if project is not OIV object, deactivate plugin when clicked on icon
    def run(self):
        project = QgsProject.instance()
        projectTest = str(
            QgsExpressionContextUtils.projectScope(project).variable(
                'project_title'))
        if 'Objecten' not in projectTest:
            self.toolbar.setEnabled(False)
            self.action.setEnabled(False)
        else:
            #always start from floor 1
            sub_string = "bouwlaag = 1"
            set_layer_substring(self.read_config_bl, sub_string)
            self.basewidget = oivBaseWidget()
            self.iface.addDockWidget(Qt.RightDockWidgetArea, self.basewidget)
            self.basewidget.identify_pand.clicked.connect(
                self.run_identify_pand)
            self.basewidget.identify_gebouw.clicked.connect(
                self.run_identify_gebouw_terrein)
            self.basewidget.closewidget.clicked.connect(self.close_basewidget)
            self.basewidget.show()
            self.toolbar.setEnabled(False)
            self.projCombo.setEnabled(False)
            self.check_visible = True
Exemple #37
0
    def setupUi(self):
        self.setWindowTitle(self.tr('Parameter definition'))
        self.setMinimumWidth(300)

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

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

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

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

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

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

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

        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_VECTOR
              or isinstance(self.param, ParameterVector)):
            self.verticalLayout.addWidget(QLabel(self.tr('Shape type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Any'))
            self.shapetypeCombo.addItem(self.tr('Point'))
            self.shapetypeCombo.addItem(self.tr('Line'))
            self.shapetypeCombo.addItem(self.tr('Polygon'))
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(self.param.datatype[0] + 1)
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE
              or isinstance(self.param, ParameterMultipleInput)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Vector (any)'))
            self.datatypeCombo.addItem(self.tr('Vector (point)'))
            self.datatypeCombo.addItem(self.tr('Vector (line)'))
            self.datatypeCombo.addItem(self.tr('Vector (polygon)'))
            self.datatypeCombo.addItem(self.tr('Raster'))
            self.datatypeCombo.addItem(self.tr('File'))
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(self.param.datatype + 1)
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_NUMBER
              or isinstance(self.param, ParameterNumber)):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.min))
                self.maxTextBox.setText(str(self.param.max))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.default
                if self.param.isInteger:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_STRING
              or isinstance(self.param, ParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE
              or isinstance(self.param, ParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(
                    1 if self.param.isFolder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_POINT
              or isinstance(self.param, ParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS
              or isinstance(self.param, ParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = CrsSelectionPanel('EPSG:4326')
            if self.param is not None:
                self.defaultTextBox.setAuthId(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)

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

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

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

        self.setLayout(self.verticalLayout)
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)
    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 addEnrichRow(self):
     layers = QgsProject.instance().layerTreeRoot().children()
     selectedLayerIndex = self.chooseLayerEnrich.currentIndex()
     layer = layers[selectedLayerIndex].layer()
     self.enrichTableResult.hide()
     fieldnames = [field.name() for field in layer.fields()]
     item = QTableWidgetItem("new_column")
     #item.setFlags(QtCore.Qt.ItemIsEnabled)
     row = self.enrichTable.rowCount()
     self.enrichTable.insertRow(row)
     self.enrichTable.setItem(row, 0, item)
     cbox = QComboBox()
     cbox.addItem("Get Remote")
     cbox.addItem("No Enrichment")
     cbox.addItem("Exclude")
     self.enrichTable.setCellWidget(row, 3, cbox)
     cbox = QComboBox()
     cbox.addItem("Enrich Value")
     cbox.addItem("Enrich URI")
     cbox.addItem("Enrich Both")
     self.enrichTable.setCellWidget(row, 4, cbox)
     cbox = QComboBox()
     for fieldd in fieldnames:
         cbox.addItem(fieldd)
     self.enrichTable.setCellWidget(row, 5, cbox)
     itemm = QTableWidgetItem("http://www.w3.org/2000/01/rdf-schema#label")
     self.enrichTable.setItem(row, 6, itemm)
     itemm = QTableWidgetItem("")
     self.enrichTable.setItem(row, 7, itemm)
     itemm = QTableWidgetItem("")
     self.enrichTable.setItem(row, 8, itemm)
Exemple #41
0
    def widgetFromParameter(self, param):
        paramtype = param["type"]
        if paramtype == FILES:

            def edit(textbox):
                f = QFileDialog.getOpenFileNames(self, "Select file", "",
                                                 "*.*")
                if f:
                    textbox.value = ",".join(f)

            return TextBoxWithLink("Browse", edit, None, True)
        elif paramtype == FOLDER:

            def edit(textbox):
                f = QFileDialog.getExistingDirectory(self, "Select folder", "")
                if f:
                    textbox.value = f

            return TextBoxWithLink("Browse", edit, None, True)
        elif paramtype == BOOL:
            check = QCheckBox(param["label"])
            if param["default"]:
                check.setCheckState(Qt.Checked)
            else:
                check.setCheckState(Qt.Unchecked)
            return check
        elif paramtype == CHOICE:
            combo = QComboBox()
            for option in param["options"]:
                combo.addItem(option)
            idx = combo.findText(str(param["default"]))
            combo.setCurrentIndex(idx)
            return combo
        elif paramtype == TEXT:
            textEdit = QTextEdit()
            textEdit.setPlainText(param["default"])
            return textEdit
        elif paramtype == VECTOR:
            combo = QgsMapLayerComboBox()
            combo.setFilters(QgsMapLayerProxyModel.VectorLayer)
            return combo
        elif paramtype == RASTER:
            combo = QgsMapLayerComboBox()
            combo.setFilters(QgsMapLayerProxyModel.RasterLayer)
            return combo
        elif paramtype == PASSWORD:
            lineEdit = QLineEdit()
            lineEdit.setEchoMode(QLineEdit.Password)
            return lineEdit
        else:
            lineEdit = QLineEdit()
            lineEdit.setText(str(param["default"]))
            return lineEdit
 def loadLayerForInterlink(self):
     layers = QgsProject.instance().layerTreeRoot().children()
     selectedLayerIndex = self.chooseLayerInterlink.currentIndex()
     if len(layers) == 0:
         return
     layer = layers[selectedLayerIndex].layer()
     fieldnames = [field.name() for field in layer.fields()]
     while self.interlinkTable.rowCount() > 0:
         self.interlinkTable.removeRow(0)
     row = 0
     self.interlinkTable.setHorizontalHeaderLabels([
         "Export?", "IDColumn?", "GeoColumn?", "Column", "ColumnProperty",
         "PropertyType", "ColumnConcept", "ValueConcepts"
     ])
     self.interlinkTable.setColumnCount(8)
     for field in fieldnames:
         item = QTableWidgetItem(field)
         item.setFlags(QtCore.Qt.ItemIsEnabled)
         item2 = QTableWidgetItem()
         item2.setCheckState(True)
         item3 = QTableWidgetItem()
         item3.setCheckState(False)
         item4 = QTableWidgetItem()
         item4.setCheckState(False)
         self.interlinkTable.insertRow(row)
         self.interlinkTable.setItem(row, 3, item)
         self.interlinkTable.setItem(row, 0, item2)
         self.interlinkTable.setItem(row, 1, item3)
         self.interlinkTable.setItem(row, 2, item4)
         cbox = QComboBox()
         cbox.addItem("Automatic")
         cbox.addItem("AnnotationProperty")
         cbox.addItem("DataProperty")
         cbox.addItem("ObjectProperty")
         cbox.addItem("SubClass")
         self.interlinkTable.setCellWidget(row, 5, cbox)
         currentRowCount = self.interlinkTable.rowCount()
         row += 1
 def loadLayerForEnrichment(self):
     layers = QgsProject.instance().layerTreeRoot().children()
     selectedLayerIndex = self.chooseLayerEnrich.currentIndex()
     if len(layers) == 0:
         return
     layer = layers[selectedLayerIndex].layer()
     self.enrichTableResult.hide()
     while self.enrichTableResult.rowCount() > 0:
         self.enrichTableResult.removeRow(0)
     self.enrichTable.show()
     self.addEnrichedLayerRowButton.setEnabled(True)
     fieldnames = [field.name() for field in layer.fields()]
     while self.enrichTable.rowCount() > 0:
         self.enrichTable.removeRow(0)
     row = 0
     self.enrichTable.setColumnCount(9)
     self.enrichTable.setHorizontalHeaderLabels([
         "Column", "EnrichmentConcept", "TripleStore", "Strategy",
         "content", "ID Column", "ID Property", "ID Domain", "Language"
     ])
     for field in fieldnames:
         item = QTableWidgetItem(field)
         item.setFlags(QtCore.Qt.ItemIsEnabled)
         currentRowCount = self.enrichTable.rowCount()
         self.enrichTable.insertRow(row)
         self.enrichTable.setItem(row, 0, item)
         cbox = QComboBox()
         cbox.addItem("No Enrichment")
         cbox.addItem("Keep Local")
         cbox.addItem("Keep Remote")
         cbox.addItem("Replace Local")
         cbox.addItem("Merge")
         cbox.addItem("Ask User")
         cbox.addItem("Exclude")
         self.enrichTable.setCellWidget(row, 3, cbox)
         cbox = QComboBox()
         cbox.addItem("Enrich Value")
         cbox.addItem("Enrich URI")
         cbox.addItem("Enrich Both")
         self.enrichTable.setCellWidget(row, 4, cbox)
         cbox = QComboBox()
         for fieldd in fieldnames:
             cbox.addItem(fieldd)
         self.enrichTable.setCellWidget(row, 5, cbox)
         itemm = QTableWidgetItem(
             "http://www.w3.org/2000/01/rdf-schema#label")
         self.enrichTable.setItem(row, 6, itemm)
         itemm = QTableWidgetItem("")
         self.enrichTable.setItem(row, 7, itemm)
         itemm = QTableWidgetItem("")
         self.enrichTable.setItem(row, 8, itemm)
         celllayout = QHBoxLayout()
         upbutton = QPushButton("Up")
         removebutton = QPushButton("Remove", self)
         removebutton.clicked.connect(self.deleteEnrichRow)
         downbutton = QPushButton("Down")
         celllayout.addWidget(upbutton)
         celllayout.addWidget(downbutton)
         celllayout.addWidget(removebutton)
         w = QWidget()
         w.setLayout(celllayout)
         optitem = QTableWidgetItem()
         #self.enrichTable.setCellWidget(row,4,w)
         #self.enrichTable.setItem(row,3,cbox)
         row += 1
     self.originalRowCount = row
Exemple #44
0
class DistanceInputPanel(NumberInputPanel):
    """
    Distance input panel for use outside the modeler - this input panel
    contains a label showing the distance unit.
    """
    def __init__(self, param):
        super().__init__(param)

        self.label = QLabel('')

        self.units_combo = QComboBox()
        self.base_units = QgsUnitTypes.DistanceUnknownUnit
        for u in (QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceKilometers,
                  QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMiles,
                  QgsUnitTypes.DistanceYards):
            self.units_combo.addItem(QgsUnitTypes.toString(u), u)

        label_margin = self.fontMetrics().width('X')
        self.layout().insertSpacing(1, label_margin / 2)
        self.layout().insertWidget(2, self.label)
        self.layout().insertWidget(3, self.units_combo)
        self.layout().insertSpacing(4, label_margin / 2)
        self.warning_label = QLabel()
        icon = QgsApplication.getThemeIcon('mIconWarning.svg')
        size = max(24, self.spnValue.height() * 0.5)
        self.warning_label.setPixmap(
            icon.pixmap(icon.actualSize(QSize(size, size))))
        self.warning_label.setToolTip(
            self.
            tr('Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results.'
               ))
        self.layout().insertWidget(4, self.warning_label)
        self.layout().insertSpacing(5, label_margin)

        self.setUnits(QgsUnitTypes.DistanceUnknownUnit)

    def setUnits(self, units):
        self.label.setText(QgsUnitTypes.toString(units))
        if QgsUnitTypes.unitType(units) != QgsUnitTypes.Standard:
            self.units_combo.hide()
            self.label.show()
        else:
            self.units_combo.setCurrentIndex(self.units_combo.findData(units))
            self.units_combo.show()
            self.label.hide()
        self.warning_label.setVisible(units == QgsUnitTypes.DistanceDegrees)
        self.base_units = units

    def setUnitParameterValue(self, value):
        units = QgsUnitTypes.DistanceUnknownUnit
        layer = self.getLayerFromValue(value)
        if isinstance(layer, QgsMapLayer):
            units = layer.crs().mapUnits()
        elif isinstance(value, QgsCoordinateReferenceSystem):
            units = value.mapUnits()
        elif isinstance(value, str):
            crs = QgsCoordinateReferenceSystem(value)
            if crs.isValid():
                units = crs.mapUnits()
        self.setUnits(units)

    def getValue(self):
        val = super().getValue()
        if isinstance(val, float) and self.units_combo.isVisible():
            display_unit = self.units_combo.currentData()
            return val * QgsUnitTypes.fromUnitToUnitFactor(
                display_unit, self.base_units)

        return val

    def setValue(self, value):
        try:
            self.spnValue.setValue(float(value))
        except:
            return
Exemple #45
0
class DMSDialog(QDialog):
    def __init__(self):
        QDialog.__init__(self)

        self.setWindowTitle(tr('DMS Point Tool'))

        self.lat_D = QLineEdit()
        self.lat_M = QLineEdit()
        self.lat_S = QLineEdit()
        self.lat_DM = QLineEdit()
        self.lon_D = QLineEdit()
        self.lon_M = QLineEdit()
        self.lon_S = QLineEdit()
        self.lon_DM = QLineEdit()

        self.lat_M.textEdited.connect(self.lat_MS_edited)
        self.lat_S.textEdited.connect(self.lat_MS_edited)
        self.lat_DM.textEdited.connect(self.lat_DM_edited)
        self.lon_M.textEdited.connect(self.lon_MS_edited)
        self.lon_S.textEdited.connect(self.lon_MS_edited)
        self.lon_DM.textEdited.connect(self.lon_DM_edited)

        int_val = QIntValidator()
        int_val.setBottom(0)

        float_val = QDoubleValidator()
        float_val.setBottom(0)

        self.lat_D.setValidator(int_val)
        self.lat_M.setValidator(int_val)
        self.lat_S.setValidator(float_val)
        self.lat_DM.setValidator(float_val)

        self.lon_D.setValidator(int_val)
        self.lon_M.setValidator(int_val)
        self.lon_S.setValidator(float_val)
        self.lon_DM.setValidator(float_val)

        self.lat_NS = QComboBox()
        self.lat_NS.addItem("N")
        self.lat_NS.addItem("S")

        self.lon_EW = QComboBox()
        self.lon_EW.addItem("E")
        self.lon_EW.addItem("W")

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

        lat_grp = QGroupBox(tr("Latitude"), self)
        lat_grp.setStyleSheet(
            "QGroupBox { font-weight: bold; color: #3c3c3c; } ")
        lat_grid = QGridLayout()
        lat_grid.addWidget(QLabel(tr("Degrees")), 0, 0)
        lat_grid.addWidget(QLabel(tr("Minutes")), 0, 1)
        lat_grid.addWidget(QLabel(tr("Seconds")), 0, 2)
        lat_grid.addWidget(QLabel(tr("Direction")), 0, 3)
        lat_grid.addWidget(self.lat_D, 1, 0)
        lat_grid.addWidget(self.lat_M, 1, 1)
        lat_grid.addWidget(self.lat_S, 1, 2)
        lat_grid.addWidget(self.lat_NS, 1, 3)
        lat_grid.addWidget(QLabel(tr("Decimal minutes")), 2, 1)
        lat_grid.addWidget(self.lat_DM, 3, 1, 1, 2)
        lat_grp.setLayout(lat_grid)

        lon_grp = QGroupBox(tr("Longitude"), self)
        lon_grp.setStyleSheet(
            "QGroupBox { font-weight: bold; color: #3c3c3c; } ")
        lon_grid = QGridLayout()
        lon_grid.addWidget(QLabel(tr("Degrees")), 0, 0)
        lon_grid.addWidget(QLabel(tr("Minutes")), 0, 1)
        lon_grid.addWidget(QLabel(tr("Seconds")), 0, 2)
        lon_grid.addWidget(QLabel(tr("Direction")), 0, 3)
        lon_grid.addWidget(self.lon_D, 1, 0)
        lon_grid.addWidget(self.lon_M, 1, 1)
        lon_grid.addWidget(self.lon_S, 1, 2)
        lon_grid.addWidget(self.lon_EW, 1, 3)
        lon_grid.addWidget(QLabel(tr("Decimal minutes")), 2, 1)
        lon_grid.addWidget(self.lon_DM, 3, 1, 1, 2)
        lon_grp.setLayout(lon_grid)

        vbox = QVBoxLayout()
        vbox.addWidget(lat_grp)
        vbox.addWidget(lon_grp)
        vbox.addWidget(buttons)

        self.setLayout(vbox)

    def getPoint(self):
        dialog = DMSDialog()
        result = dialog.exec_()

        latitude = 0
        longitude = 0
        if dialog.lat_D.text().strip() \
                and dialog.lat_M.text().strip() \
                and dialog.lat_S.text().strip() \
                and dialog.lon_D.text().strip() \
                and dialog.lon_M.text().strip() \
                and dialog.lon_S.text().strip():
            latitude = int(dialog.lat_D.text()) \
                + float(dialog.lat_M.text()) / 60 \
                + float(dialog.lat_S.text()) / 3600
            if dialog.lat_NS.currentIndex() == 1:
                latitude *= -1
            longitude = int(dialog.lon_D.text()) \
                + float(dialog.lon_M.text()) / 60 \
                + float(dialog.lon_S.text()) / 3600
            if dialog.lon_EW.currentIndex() == 1:
                longitude *= -1
        return (QgsPointXY(longitude, latitude), result == QDialog.Accepted)

    def lat_MS_edited(self):
        if self.lat_M.text().strip():
            M = int(self.lat_M.text())
        else:
            M = 0
        if self.lat_S.text().strip():
            S = float(self.lat_S.text())
        else:
            S = 0
        if M == 0 and S == 0:
            self.lat_DM.clear()
        else:
            self.lat_DM.setText(str(M + (S / 60)))

    def lat_DM_edited(self):
        if self.lat_DM.text().strip():
            DM = float(self.lat_DM.text())
            self.lat_M.setText(str(int(DM)))
            self.lat_S.setText(str((DM - int(DM)) * 60))
        else:
            self.lat_M.clear()
            self.lat_S.clear()

    def lon_MS_edited(self):
        if self.lon_M.text().strip():
            M = int(self.lon_M.text())
        else:
            M = 0
        if self.lon_S.text().strip():
            S = float(self.lon_S.text())
        else:
            S = 0
        if M == 0 and S == 0:
            self.lon_DM.clear()
        else:
            self.lon_DM.setText(str(M + (S / 60)))

    def lon_DM_edited(self):
        if self.lon_DM.text().strip():
            DM = float(self.lon_DM.text())
            self.lon_M.setText(str(int(DM)))
            self.lon_S.setText(str((DM - int(DM)) * 60))
        else:
            self.lon_M.clear()
            self.lon_S.clear()
class ModelerParameterDefinitionDialog(QDialog):
    PARAMETER_NUMBER = 'Number'
    PARAMETER_RASTER = 'Raster Layer'
    PARAMETER_TABLE = 'Vector Layer'
    PARAMETER_VECTOR = 'Feature Source'
    PARAMETER_STRING = 'String'
    PARAMETER_EXPRESSION = 'Expression'
    PARAMETER_BOOLEAN = 'Boolean'
    PARAMETER_TABLE_FIELD = 'Layer Field'
    PARAMETER_EXTENT = 'Extent'
    PARAMETER_FILE = 'File'
    PARAMETER_POINT = 'Point'
    PARAMETER_CRS = 'CRS'
    PARAMETER_MULTIPLE = 'Multiple Input'
    PARAMETER_BAND = 'Raster Band'
    PARAMETER_MAP_LAYER = 'Map Layer'

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.setLayout(self.verticalLayout)

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

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

        QDialog.accept(self)

    def reject(self):
        self.param = None

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

        QDialog.reject(self)
class MultilineTextPanel(QWidget):

    USE_TEXT = 0

    def __init__(self, options, parent=None):
        super(MultilineTextPanel, self).__init__(parent)
        self.options = options
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setSpacing(2)
        self.verticalLayout.setMargin(0)
        self.combo = QComboBox()
        self.combo.addItem(self.tr('[Use text below]'))
        for option in options:
            self.combo.addItem(option[0], option[1])
        self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.verticalLayout.addWidget(self.combo)
        self.textBox = QPlainTextEdit()
        self.verticalLayout.addWidget(self.textBox)
        self.setLayout(self.verticalLayout)

    def setText(self, text):
        self.textBox.setPlainText(text)

    def getOption(self):
        return self.combo.currentIndex()

    def getValue(self):
        if self.combo.currentIndex() == 0:
            return str(self.textBox.toPlainText())
        else:
            return self.combo.currentData()

    def setValue(self, value):
        items = [self.combo.itemData(i) for i in range(1, self.combo.count())]
        for idx, item in enumerate(items):
            if item == value:
                self.combo.setCurrentIndex(idx)
                return
        self.combo.setCurrentIndex(0)
        if value:
            self.textBox.setPlainText(value)
Exemple #48
0
 def createWidget(self):
     widget = QComboBox()
     widget.addItems(self.param.options)
     if self.dialogType in (DIALOG_MODELER, DIALOG_STANDARD):
         widget.currentIndexChanged.connect(self.updateAllParameters)
     return widget
Exemple #49
0
    def getWidgetFromParameter(self, param):
        # TODO Create Parameter widget class that holds the logic
        # for creating a widget that belongs to the parameter.
        if isinstance(param, ParameterRaster):
            layers = dataobjects.getRasterLayers()
            items = []
            if param.optional:
                items.append((self.NOT_SELECTED, None))
            for layer in layers:
                items.append((self.getExtendedLayerName(layer), layer))
            item = InputLayerSelectorPanel(items, param)
        elif isinstance(param, ParameterVector):
            if self.somethingDependsOnThisParameter(
                    param) or self.alg.allowOnlyOpenedLayers:
                item = QComboBox()
                layers = dataobjects.getVectorLayers(param.shapetype)
                layers.sort(key=lambda lay: lay.name())
                if param.optional:
                    item.addItem(self.NOT_SELECTED, None)
                for layer in layers:
                    item.addItem(self.getExtendedLayerName(layer), layer)
                item.currentIndexChanged.connect(self.updateDependentFields)
                item.name = param.name
            else:
                layers = dataobjects.getVectorLayers(param.shapetype)
                items = []
                if param.optional:
                    items.append((self.NOT_SELECTED, None))
                for layer in layers:
                    items.append((self.getExtendedLayerName(layer), layer))
                # if already set, put first in list
                for i, (name, layer) in enumerate(items):
                    if layer and layer.source() == param.value:
                        items.insert(0, items.pop(i))
                item = InputLayerSelectorPanel(items, param)
        elif isinstance(param, ParameterTable):
            if self.somethingDependsOnThisParameter(param):
                item = QComboBox()
                layers = dataobjects.getTables()
                if param.optional:
                    item.addItem(self.NOT_SELECTED, None)
                for layer in layers:
                    item.addItem(layer.name(), layer)
                item.currentIndexChanged.connect(self.updateDependentFields)
                item.name = param.name
            else:
                layers = dataobjects.getTables()
                items = []
                if param.optional:
                    items.append((self.NOT_SELECTED, None))
                for layer in layers:
                    items.append((layer.name(), layer))
                # if already set, put first in list
                for i, (name, layer) in enumerate(items):
                    if layer and layer.source() == param.value:
                        items.insert(0, items.pop(i))
                item = InputLayerSelectorPanel(items, param)
        elif isinstance(param, ParameterBoolean):
            item = QCheckBox()
            if param.default:
                item.setChecked(True)
            else:
                item.setChecked(False)
        elif isinstance(param, ParameterTableField):
            item = QComboBox()
            if param.parent in self.dependentItems:
                items = self.dependentItems[param.parent]
            else:
                items = []
                self.dependentItems[param.parent] = items
            items.append(param.name)
            parent = self.alg.getParameterFromName(param.parent)
            if isinstance(parent, ParameterVector):
                layers = dataobjects.getVectorLayers(parent.shapetype)
            else:
                layers = dataobjects.getTables()
            if len(layers) > 0:
                if param.optional:
                    item.addItem(self.tr('[not set]'))
                item.addItems(self.getFields(layers[0], param.datatype))
        elif isinstance(param, ParameterSelection):
            item = QComboBox()
            item.addItems(param.options)
            if param.default:
                item.setCurrentIndex(param.default)
        elif isinstance(param, ParameterFixedTable):
            item = FixedTablePanel(param)
        elif isinstance(param, ParameterRange):
            item = RangePanel(param)
        elif isinstance(param, ParameterFile):
            item = FileSelectionPanel(param.isFolder, param.ext)
        elif isinstance(param, ParameterMultipleInput):
            if param.datatype == ParameterMultipleInput.TYPE_FILE:
                item = MultipleInputPanel(
                    datatype=ParameterMultipleInput.TYPE_FILE)
            else:
                if param.datatype == ParameterMultipleInput.TYPE_RASTER:
                    options = dataobjects.getRasterLayers(sorting=False)
                elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
                    options = dataobjects.getVectorLayers(sorting=False)
                else:
                    options = dataobjects.getVectorLayers([param.datatype],
                                                          sorting=False)
                opts = [self.getExtendedLayerName(opt) for opt in options]
                item = MultipleInputPanel(opts)
        elif isinstance(param, ParameterNumber):
            item = NumberInputPanel(param.default, param.min, param.max,
                                    param.isInteger)
        elif isinstance(param, ParameterExtent):
            item = ExtentSelectionPanel(self.parent, self.alg, param.default)
        elif isinstance(param, ParameterPoint):
            item = PointSelectionPanel(self.parent, param.default)
        elif isinstance(param, ParameterCrs):
            item = CrsSelectionPanel(param.default)
        elif isinstance(param, ParameterString):
            if param.multiline:
                verticalLayout = QVBoxLayout()
                verticalLayout.setSizeConstraint(QLayout.SetDefaultConstraint)
                textEdit = QPlainTextEdit()
                if param.default:
                    textEdit.setPlainText(param.default)
                verticalLayout.addWidget(textEdit)
                item = textEdit
            else:
                item = QLineEdit()
                if param.default:
                    item.setText(unicode(param.default))
        elif isinstance(param, ParameterGeometryPredicate):
            item = GeometryPredicateSelectionPanel(param.enabledPredicates)
            if param.left:
                widget = self.valueItems[param.left]
                if isinstance(widget, InputLayerSelectorPanel):
                    widget = widget.cmbText
                widget.currentIndexChanged.connect(item.onLeftLayerChange)
                item.leftLayer = widget.itemData(widget.currentIndex())
            if param.right:
                widget = self.valueItems[param.right]
                if isinstance(widget, InputLayerSelectorPanel):
                    widget = widget.cmbText
                widget.currentIndexChanged.connect(item.onRightLayerChange)
                item.rightLayer = widget.itemData(widget.currentIndex())
            item.updatePredicates()
            if param.default:
                item.setValue(param.default)
        else:
            item = QLineEdit()
            if param.default:
                item.setText(unicode(param.default))

        return item
    def _create_exposure_combos(self):
        """Create one combobox for each exposure and insert them in the UI."""
        # Map registry may be invalid if QGIS is shutting down
        project = QgsProject.instance()
        canvas_layers = self.iface.mapCanvas().layers()
        # MapLayers returns a QMap<QString id, QgsMapLayer layer>
        layers = list(project.mapLayers().values())
        # Sort by name for tests
        layers.sort(key=lambda x: x.name())

        show_only_visible_layers = setting('visibleLayersOnlyFlag',
                                           expected_type=bool)

        # For issue #618
        if len(layers) == 0:
            # self.message_viewer.setHtml(getting_started_message())
            return

        for one_exposure in exposure_all:
            label = QLabel(one_exposure['name'])
            combo = QComboBox()
            combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
            combo.addItem(tr('Do not use'), None)
            self.form_layout.addRow(label, combo)
            self.combos_exposures[one_exposure['key']] = combo

        for layer in layers:
            if (show_only_visible_layers and (layer not in canvas_layers)):
                continue

            try:
                layer_purpose = self.keyword_io.read_keywords(
                    layer, 'layer_purpose')
                keyword_version = str(
                    self.keyword_io.read_keywords(layer,
                                                  inasafe_keyword_version_key))
                if not is_keyword_version_supported(keyword_version):
                    continue
            except BaseException:  # pylint: disable=W0702
                # continue ignoring this layer
                continue

            # See if there is a title for this layer, if not,
            # fallback to the layer's filename
            # noinspection PyBroadException
            try:
                title = self.keyword_io.read_keywords(layer, 'title')
            except (NoKeywordsFoundError, KeywordNotFoundError,
                    MetadataReadError):
                # Skip if there are no keywords at all, or missing keyword
                continue
            except BaseException:  # pylint: disable=W0702
                pass
            else:
                # Lookup internationalised title if available
                title = self.tr(title)

            # Register title with layer
            set_layer_from_title = setting('set_layer_from_title_flag', True,
                                           bool)
            if title and set_layer_from_title:
                if qgis_version() >= 21800:
                    layer.setName(title)
                else:
                    # QGIS 2.14
                    layer.setLayerName(title)

            source = layer.id()

            icon = layer_icon(layer)

            if layer_purpose == layer_purpose_hazard['key']:
                add_ordered_combo_item(self.cbx_hazard,
                                       title,
                                       source,
                                       icon=icon)
            elif layer_purpose == layer_purpose_aggregation['key']:
                if self.use_selected_only:
                    count_selected = layer.selectedFeatureCount()
                    if count_selected > 0:
                        add_ordered_combo_item(self.cbx_aggregation,
                                               title,
                                               source,
                                               count_selected,
                                               icon=icon)
                    else:
                        add_ordered_combo_item(self.cbx_aggregation, title,
                                               source, None, icon)
                else:
                    add_ordered_combo_item(self.cbx_aggregation, title, source,
                                           None, icon)
            elif layer_purpose == layer_purpose_exposure['key']:

                # fetching the exposure
                try:
                    exposure_type = self.keyword_io.read_keywords(
                        layer, layer_purpose_exposure['key'])
                except BaseException:  # pylint: disable=W0702
                    # continue ignoring this layer
                    continue

                for key, combo in list(self.combos_exposures.items()):
                    if key == exposure_type:
                        add_ordered_combo_item(combo, title, source, icon=icon)

        self.cbx_aggregation.addItem(entire_area_item_aggregation, None)
        for combo in list(self.combos_exposures.values()):
            combo.currentIndexChanged.connect(self.validate_impact_function)
Exemple #51
0
class ModelerParameterDefinitionDialog(QDialog):

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

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

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

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

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

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

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

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

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

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

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

        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_VECTOR
              or isinstance(self.param, ParameterVector)):
            self.verticalLayout.addWidget(QLabel(self.tr('Shape type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Any'))
            self.shapetypeCombo.addItem(self.tr('Point'))
            self.shapetypeCombo.addItem(self.tr('Line'))
            self.shapetypeCombo.addItem(self.tr('Polygon'))
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(self.param.datatype[0] + 1)
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_MULTIPLE
              or isinstance(self.param, ParameterMultipleInput)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Vector (any)'))
            self.datatypeCombo.addItem(self.tr('Vector (point)'))
            self.datatypeCombo.addItem(self.tr('Vector (line)'))
            self.datatypeCombo.addItem(self.tr('Vector (polygon)'))
            self.datatypeCombo.addItem(self.tr('Raster'))
            self.datatypeCombo.addItem(self.tr('File'))
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(self.param.datatype + 1)
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_NUMBER
              or isinstance(self.param, ParameterNumber)):
            self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
            self.minTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.minTextBox)
            self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
            self.maxTextBox = QLineEdit()
            self.verticalLayout.addWidget(self.maxTextBox)
            if self.param is not None:
                self.minTextBox.setText(str(self.param.min))
                self.maxTextBox.setText(str(self.param.max))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.default
                if self.param.isInteger:
                    default = int(math.floor(default))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_STRING
              or isinstance(self.param, ParameterString)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_FILE
              or isinstance(self.param, ParameterFile)):
            self.verticalLayout.addWidget(QLabel(self.tr('Type')))
            self.fileFolderCombo = QComboBox()
            self.fileFolderCombo.addItem(self.tr('File'))
            self.fileFolderCombo.addItem(self.tr('Folder'))
            if self.param is not None:
                self.fileFolderCombo.setCurrentIndex(
                    1 if self.param.isFolder else 0)
            self.verticalLayout.addWidget(self.fileFolderCombo)
        elif (self.paramType
              == ModelerParameterDefinitionDialog.PARAMETER_POINT
              or isinstance(self.param, ParameterPoint)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            if self.param is not None:
                self.defaultTextBox.setText(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)
        elif (self.paramType == ModelerParameterDefinitionDialog.PARAMETER_CRS
              or isinstance(self.param, ParameterCrs)):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = CrsSelectionPanel('EPSG:4326')
            if self.param is not None:
                self.defaultTextBox.setAuthId(self.param.default)
            self.verticalLayout.addWidget(self.defaultTextBox)

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

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

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

        self.setLayout(self.verticalLayout)

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

    def cancelPressed(self):
        self.param = None
        self.close()
Exemple #52
0
 def createWidget(self):
     if self.dialogType == DIALOG_MODELER:
         widget = QComboBox()
         widget.setEditable(True)
         strings = self.dialog.getAvailableValuesOfType(
             QgsProcessingParameterString, QgsProcessingOutputString)
         options = [(self.dialog.resolveValueDescription(s), s)
                    for s in strings]
         for desc, val in options:
             widget.addItem(desc, val)
         widget.setEditText(self.param.defaultValue() or '')
         return widget
     elif self.dialogType == DIALOG_BATCH:
         widget = QLineEdit()
         if self.param.defaultValue():
             widget.setText(self.param.defaultValue())
     else:
         return QgsRasterFormatSaveOptionsWidget()
Exemple #53
0
class TableWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin):
    """
    WidgetWrapper for ParameterString that create and manage a combobox widget
    with existing tables from a parent schema parameter.
    """
    def createWidget(self, schema_param=None):
        self._schema_param = schema_param
        self._database = None
        self._schema = None

        self._combo = QComboBox()
        self._combo.setEditable(True)
        self.refreshItems()
        self._combo.currentIndexChanged.connect(
            lambda: self.widgetValueHasChanged.emit(self))
        self._combo.lineEdit().editingFinished.connect(
            lambda: self.widgetValueHasChanged.emit(self))

        return self.wrapWithExpressionButton(self._combo)

    def postInitialize(self, wrappers):
        for wrapper in wrappers:
            if wrapper.param.name == self._schema_param:
                self.schema_wrapper = wrapper
                self.setSchema(wrapper.database(), wrapper.value())
                wrapper.widgetValueHasChanged.connect(self.schemaChanged)
                break

    def schemaChanged(self, wrapper):
        database = wrapper.database()
        schema = wrapper.value()
        if database == self._database and schema == self._schema:
            return
        self.setSchema(database, schema)

    def setSchema(self, database, schema):
        self._database = database
        self._schema = schema
        self.refreshItems()
        self.widgetValueHasChanged.emit(self)

    def refreshItems(self):
        value = self.comboValue(combobox=self._combo)

        self._combo.clear()

        if (self._database is not None and isinstance(self._schema, str)):
            for table in self._database.list_geotables(self._schema):
                self._combo.addItem(table[0], table[0])

        if self.dialogType == DIALOG_MODELER:
            strings = self.dialog.getAvailableValuesOfType([
                ParameterString, ParameterNumber, ParameterFile,
                ParameterTableField, ParameterExpression
            ], OutputString)
            for text, data in [(self.dialog.resolveValueDescription(s), s)
                               for s in strings]:
                self._combo.addItem(text, data)

        self.setComboValue(value, self._combo)

    def setValue(self, value):
        self.setComboValue(value, self._combo)
        self.widgetValueHasChanged.emit(self)

    def value(self):
        return self.comboValue(combobox=self._combo)
Exemple #54
0
    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.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 == parameters.PARAMETER_LAYOUTITEM or \
                isinstance(self.param, QgsProcessingParameterLayoutItem):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layout')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterLayout)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayoutParameterName(
                        ) == 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
              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 (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)
Exemple #55
0
 def __init__(self, iface, layer, tree, dlg):
     QTreeWidgetItem.__init__(self)
     self.iface = iface
     self.layer = layer
     self.setText(0, layer.name())
     self.setIcon(0, self.layerIcon)
     project = QgsProject.instance()
     if project.layerTreeRoot().findLayer(layer.id()).isVisible():
         self.setCheckState(0, Qt.Checked)
     else:
         self.setCheckState(0, Qt.Unchecked)
     self.visibleItem = QTreeWidgetItem(self)
     self.visibleCheck = QCheckBox()
     vis = layer.customProperty("qgis2web/Visible", True)
     if vis == 0 or str(vis).lower() == "false":
         self.visibleCheck.setChecked(False)
     else:
         self.visibleCheck.setChecked(True)
     self.visibleItem.setText(0, "Visible")
     self.addChild(self.visibleItem)
     tree.setItemWidget(self.visibleItem, 1, self.visibleCheck)
     self.interactiveItem = QTreeWidgetItem(self)
     self.interactiveCheck = QCheckBox()
     int = True
     if int == 0 or str(int).lower() == "false":
         self.interactiveCheck.setChecked(False)
     else:
         self.interactiveCheck.setChecked(True)
     self.interactiveItem.setText(0, "Popups")
     self.addChild(self.interactiveItem)
     tree.setItemWidget(self.interactiveItem, 1, self.interactiveCheck)
     if layer.type() == layer.VectorLayer:
         if layer.providerType() == 'WFS':
             self.jsonItem = QTreeWidgetItem(self)
             self.jsonCheck = QCheckBox()
             if layer.customProperty("qgis2web/Encode to JSON") == 2:
                 self.jsonCheck.setChecked(True)
             self.jsonItem.setText(0, "Encode to JSON")
             self.jsonCheck.stateChanged.connect(self.changeJSON)
             self.addChild(self.jsonItem)
             tree.setItemWidget(self.jsonItem, 1, self.jsonCheck)
         if layer.geometryType() == QgsWkbTypes.PointGeometry:
             self.clusterItem = QTreeWidgetItem(self)
             self.clusterCheck = QCheckBox()
             if layer.customProperty("qgis2web/Cluster") == 2:
                 self.clusterCheck.setChecked(True)
             self.clusterItem.setText(0, "Cluster")
             self.clusterCheck.stateChanged.connect(self.changeCluster)
             self.addChild(self.clusterItem)
             tree.setItemWidget(self.clusterItem, 1, self.clusterCheck)
         self.popupItem = QTreeWidgetItem(self)
         self.popupItem.setText(0, "Popup fields")
         options = []
         fields = self.layer.fields()
         for f in fields:
             fieldIndex = fields.indexFromName(f.name())
             editorWidget = layer.editorWidgetSetup(fieldIndex).type()
             if editorWidget == 'Hidden':
                 continue
             options.append(f.name())
         for option in options:
             self.attr = QTreeWidgetItem(self)
             self.attrWidget = QComboBox()
             self.attrWidget.addItem("no label")
             self.attrWidget.addItem("inline label")
             self.attrWidget.addItem("header label")
             custProp = layer.customProperty("qgis2web/popup/" + option)
             if (custProp != "" and custProp is not None):
                 self.attrWidget.setCurrentIndex(
                     self.attrWidget.findText(
                         layer.customProperty("qgis2web/popup/" + option)))
             self.attr.setText(1, option)
             self.popupItem.addChild(self.attr)
             tree.setItemWidget(self.attr, 2, self.attrWidget)
         self.addChild(self.popupItem)
     else:
         if layer.providerType() == 'wms':
             self.getFeatureInfoItem = QTreeWidgetItem(self)
             self.getFeatureInfoCheck = QCheckBox()
             if layer.customProperty("qgis2web/GetFeatureInfo") == 2:
                 self.getFeatureInfoCheck.setChecked(True)
             self.getFeatureInfoItem.setText(0, "Enable GetFeatureInfo?")
             self.getFeatureInfoCheck.stateChanged.connect(
                 self.changeGetFeatureInfo)
             self.addChild(self.getFeatureInfoItem)
             tree.setItemWidget(self.getFeatureInfoItem, 1,
                                self.getFeatureInfoCheck)
Exemple #56
0
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):
        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.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 == parameters.PARAMETER_LAYOUTITEM or \
                isinstance(self.param, QgsProcessingParameterLayoutItem):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layout')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterLayout)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayoutParameterName(
                        ) == 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
              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 (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_LAYOUTITEM
              or isinstance(self.param, QgsProcessingParameterLayoutItem)):
            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 = QgsProcessingParameterLayoutItem(
                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_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
        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)
Exemple #57
0
class Serval(object):

    LINE_SELECTION = "line"
    POLYGON_SELECTION = "polygon"
    RGB = "RGB"
    SINGLE_BAND = "Single band"

    def __init__(self, iface):
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.plugin_dir = os.path.dirname(__file__)
        self.uc = UserCommunication(iface, 'Serval')
        self.load_settings()
        self.raster = None
        self.handler = None
        self.spin_boxes = None
        self.exp_dlg = None
        self.exp_builder = None
        self.block_pts_layer = None
        self.px, self.py = [0, 0]
        self.last_point = QgsPointXY(0, 0)
        self.rbounds = None
        self.changes = dict()  # dict with rasters changes {raster_id: RasterChanges instance}
        self.project = QgsProject.instance()
        self.crs_transform = None
        self.all_touched = None
        self.selection_mode = None
        self.spatial_index_time = dict()  # {layer_id: creation time}
        self.spatial_index = dict()  # {layer_id: spatial index}
        self.selection_layers_count = 1
        self.debug = DEBUG
        self.logger = get_logger() if self.debug else None

        self.menu = u'Serval'
        self.actions = []
        self.actions_always_on = []
        self.toolbar = self.iface.addToolBar(u'Serval Main Toolbar')
        self.toolbar.setObjectName(u'Serval Main Toolbar')
        self.toolbar.setToolTip(u'Serval Main Toolbar')

        self.sel_toolbar = self.iface.addToolBar(u'Serval Selection Toolbar')
        self.sel_toolbar.setObjectName(u'Serval Selection Toolbar')
        self.sel_toolbar.setToolTip(u'Serval Selection Toolbar')

        # Map tools
        self.probe_tool = QgsMapToolEmitPoint(self.canvas)
        self.probe_tool.setObjectName('ServalProbeTool')
        self.probe_tool.setCursor(QCursor(QPixmap(icon_path('probe_tool.svg')), hotX=2, hotY=22))
        self.probe_tool.canvasClicked.connect(self.point_clicked)
        self.draw_tool = QgsMapToolEmitPoint(self.canvas)
        self.draw_tool.setObjectName('ServalDrawTool')
        self.draw_tool.setCursor(QCursor(QPixmap(icon_path('draw_tool.svg')), hotX=2, hotY=22))
        self.draw_tool.canvasClicked.connect(self.point_clicked)
        self.selection_tool = RasterCellSelectionMapTool(self.iface, self.uc, self.raster, debug=self.debug)
        self.selection_tool.setObjectName('RasterSelectionTool')
        self.map_tool_btn = dict()  # {map tool: button activating the tool}

        self.iface.currentLayerChanged.connect(self.set_active_raster)
        self.project.layersAdded.connect(self.set_active_raster)
        self.canvas.mapToolSet.connect(self.check_active_tool)

        self.register_exp_functions()

    def load_settings(self):
        """Return plugin settings dict - default values are overriden by user prefered values from QSettings."""
        self.default_settings = {
            "undo_steps": {"value": 3, "vtype": int},
        }
        self.settings = dict()
        s = QSettings()
        s.beginGroup("serval")
        for k, v in self.default_settings.items():
            user_val = s.value(k, v["value"], v["vtype"])
            self.settings[k] = user_val

    def edit_settings(self):
        """Open dialog with plugin settings."""
        s = QSettings()
        s.beginGroup("serval")
        k = "undo_steps"
        cur_val = self.settings[k]
        val_type = self.default_settings[k]["vtype"]
        cur_steps = s.value(k, cur_val, val_type)

        label = 'Nr of Undo/Redo steps:'
        steps, ok = QInputDialog.getInt(None, "Serval Settings", label, cur_steps)
        if not ok:
            return
        if steps >= 0:
            s.setValue("undo_steps", steps)
        self.load_settings()
        self.uc.show_info("Some new settings may require QGIS restart.")

    def initGui(self):
        _ = self.add_action(
            'serval_icon.svg',
            text=u'Show Serval Toolbars',
            add_to_menu=True,
            callback=self.show_toolbar,
            always_on=True, )

        _ = self.add_action(
            'serval_icon.svg',
            text=u'Hide Serval Toolbars',
            add_to_menu=True,
            callback=self.hide_toolbar,
            always_on=True, )

        self.probe_btn = self.add_action(
            'probe.svg',
            text="Probe raster",
            callback=self.activate_probing,
            add_to_toolbar=self.toolbar,
            checkable=True, )
        self.map_tool_btn[self.probe_tool] = self.probe_btn

        self.color_btn = QgsColorButton()
        self.color_btn.setColor(Qt.gray)
        self.color_btn.setMinimumSize(QSize(40, 24))
        self.color_btn.setMaximumSize(QSize(40, 24))
        self.toolbar.addWidget(self.color_btn)
        self.color_picker_connection(connect=True)
        self.color_btn.setDisabled(True)

        self.toolbar.addWidget(QLabel("Band:"))
        self.bands_cbo = QComboBox()
        self.bands_cbo.addItem("1", 1)
        self.toolbar.addWidget(self.bands_cbo)
        self.bands_cbo.currentIndexChanged.connect(self.update_active_bands)
        self.bands_cbo.setDisabled(True)

        self.spin_boxes = BandBoxes()
        self.toolbar.addWidget(self.spin_boxes)
        self.spin_boxes.enter_hit.connect(self.apply_spin_box_values)

        self.draw_btn = self.add_action(
            'draw.svg',
            text="Apply Value(s) To Single Cell",
            callback=self.activate_drawing,
            add_to_toolbar=self.toolbar,
            checkable=True, )
        self.map_tool_btn[self.draw_tool] = self.draw_btn

        self.apply_spin_box_values_btn = self.add_action(
            'apply_const_value.svg',
            text="Apply Value(s) to Selection",
            callback=self.apply_spin_box_values,
            add_to_toolbar=self.toolbar, )

        self.gom_btn = self.add_action(
            'apply_nodata_value.svg',
            text="Apply NoData to Selection",
            callback=self.apply_nodata_value,
            add_to_toolbar=self.toolbar, )

        self.exp_dlg_btn = self.add_action(
            'apply_expression_value.svg',
            text="Apply Expression Value To Selection",
            callback=self.define_expression,
            add_to_toolbar=self.toolbar,
            checkable=False, )

        self.low_pass_filter_btn = self.add_action(
            'apply_low_pass_filter.svg',
            text="Apply Low-Pass 3x3 Filter To Selection",
            callback=self.apply_low_pass_filter,
            add_to_toolbar=self.toolbar,
            checkable=False, )

        self.undo_btn = self.add_action(
            'undo.svg',
            text="Undo",
            callback=self.undo,
            add_to_toolbar=self.toolbar, )

        self.redo_btn = self.add_action(
            'redo.svg',
            text="Redo",
            callback=self.redo,
            add_to_toolbar=self.toolbar, )

        self.set_nodata_btn = self.add_action(
            'set_nodata.svg',
            text="Edit Raster NoData Values",
            callback=self.set_nodata,
            add_to_toolbar=self.toolbar, )

        self.settings_btn = self.add_action(
            'edit_settings.svg',
            text="Serval Settings",
            callback=self.edit_settings,
            add_to_toolbar=self.toolbar,
            always_on=True, )

        self.show_help = self.add_action(
            'help.svg',
            text="Help",
            add_to_menu=True,
            callback=self.show_website,
            add_to_toolbar=self.toolbar,
            always_on=True, )

        # Selection Toolbar

        line_width_icon = QIcon(icon_path("line_width.svg"))
        line_width_lab = QLabel()
        line_width_lab.setPixmap(line_width_icon.pixmap(22, 12))
        self.sel_toolbar.addWidget(line_width_lab)

        self.line_width_sbox = QgsDoubleSpinBox()
        self.line_width_sbox.setMinimumSize(QSize(50, 24))
        self.line_width_sbox.setMaximumSize(QSize(50, 24))
        # self.line_width_sbox.setButtonSymbols(QAbstractSpinBox.NoButtons)
        self.line_width_sbox.setValue(1)
        self.line_width_sbox.setMinimum(0.01)
        self.line_width_sbox.setShowClearButton(False)
        self.line_width_sbox.setToolTip("Selection Line Width")
        self.line_width_sbox.valueChanged.connect(self.update_selection_tool)

        self.width_unit_cbo = QComboBox()
        self.width_units = ("map units", "pixel width", "pixel height", "hairline",)
        for u in self.width_units:
            self.width_unit_cbo.addItem(u)
        self.width_unit_cbo.setToolTip("Selection Line Width Unit")
        self.sel_toolbar.addWidget(self.line_width_sbox)
        self.sel_toolbar.addWidget(self.width_unit_cbo)
        self.width_unit_cbo.currentIndexChanged.connect(self.update_selection_tool)

        self.line_select_btn = self.add_action(
            'select_line.svg',
            text="Select Raster Cells by Line",
            callback=self.activate_line_selection,
            add_to_toolbar=self.sel_toolbar,
            checkable=True, )

        self.polygon_select_btn = self.add_action(
            'select_polygon.svg',
            text="Select Raster Cells by Polygon",
            callback=self.activate_polygon_selection,
            add_to_toolbar=self.sel_toolbar,
            checkable=True, )

        self.selection_from_layer_btn = self.add_action(
            'select_from_layer.svg',
            text="Create Selection From Layer",
            callback=self.selection_from_layer,
            add_to_toolbar=self.sel_toolbar, )

        self.selection_to_layer_btn = self.add_action(
            'selection_to_layer.svg',
            text="Create Memory Layer From Selection",
            callback=self.selection_to_layer,
            add_to_toolbar=self.sel_toolbar, )

        self.clear_selection_btn = self.add_action(
            'clear_selection.svg',
            text="Clear selection",
            callback=self.clear_selection,
            add_to_toolbar=self.sel_toolbar, )

        self.toggle_all_touched_btn = self.add_action(
            'all_touched.svg',
            text="Toggle All Touched Get Selected",
            callback=self.toggle_all_touched,
            checkable=True, checked=True,
            add_to_toolbar=self.sel_toolbar, )
        self.all_touched = True

        self.enable_toolbar_actions(enable=False)
        self.check_undo_redo_btns()

    def add_action(self, icon_name, callback=None, text="", enabled_flag=True, add_to_menu=False, add_to_toolbar=None,
                   status_tip=None, whats_this=None, checkable=False, checked=False, always_on=False):
            
        icon = QIcon(icon_path(icon_name))
        action = QAction(icon, text, self.iface.mainWindow())
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)
        action.setCheckable(checkable)
        action.setChecked(checked)

        if status_tip is not None:
            action.setStatusTip(status_tip)
        if whats_this is not None:
            action.setWhatsThis(whats_this)
        if add_to_toolbar is not None:
            add_to_toolbar.addAction(action)
        if add_to_menu:
            self.iface.addPluginToMenu(self.menu, action)

        self.actions.append(action)
        if always_on:
            self.actions_always_on.append(action)
        return action

    def unload(self):
        self.changes = None
        if self.selection_tool:
            self.selection_tool.reset()
        if self.spin_boxes is not None:
            self.spin_boxes.remove_spinboxes()
        for action in self.actions:
            self.iface.removePluginMenu('Serval', action)
            self.iface.removeToolBarIcon(action)
        del self.toolbar
        del self.sel_toolbar
        self.iface.actionPan().trigger()
        self.unregister_exp_functions()

    def show_toolbar(self):
        if self.toolbar:
            self.toolbar.show()
            self.sel_toolbar.show()

    def hide_toolbar(self):
        if self.toolbar:
            self.toolbar.hide()
            self.sel_toolbar.hide()

    @staticmethod
    def register_exp_functions():
        QgsExpression.registerFunction(nearest_feature_attr_value)
        QgsExpression.registerFunction(nearest_pt_on_line_interpolate_z)
        QgsExpression.registerFunction(intersecting_features_attr_average)
        QgsExpression.registerFunction(interpolate_from_mesh)

    @staticmethod
    def unregister_exp_functions():
        QgsExpression.unregisterFunction('nearest_feature_attr_value')
        QgsExpression.unregisterFunction('nearest_pt_on_line_interpolate_z')
        QgsExpression.unregisterFunction('intersecting_features_attr_average')
        QgsExpression.unregisterFunction('interpolate_from_mesh')

    def uncheck_all_btns(self):
        self.probe_btn.setChecked(False)
        self.draw_btn.setChecked(False)
        self.gom_btn.setChecked(False)
        self.line_select_btn.setChecked(False)
        self.polygon_select_btn.setChecked(False)

    def check_active_tool(self, cur_tool):
        self.uncheck_all_btns()
        if cur_tool in self.map_tool_btn:
            self.map_tool_btn[cur_tool].setChecked(True)
        if cur_tool == self.selection_tool:
            if self.selection_mode == self.LINE_SELECTION:
                self.line_select_btn.setChecked(True)
            else:
                self.polygon_select_btn.setChecked(True)

    def activate_probing(self):
        self.mode = 'probe'
        self.canvas.setMapTool(self.probe_tool)

    def define_expression(self):
        if not self.selection_tool.selected_geometries:
            self.uc.bar_warn("No selection for raster layer. Select some cells and retry...")
            return
        self.handler.select(self.selection_tool.selected_geometries, all_touched_cells=self.all_touched)
        self.handler.create_cell_pts_layer()
        if self.handler.cell_pts_layer.featureCount() == 0:
            self.uc.bar_warn("No selection for raster layer. Select some cells and retry...")
            return
        self.exp_dlg = QgsExpressionBuilderDialog(self.handler.cell_pts_layer)
        self.exp_builder = self.exp_dlg.expressionBuilder()
        self.exp_dlg.accepted.connect(self.apply_exp_value)
        self.exp_dlg.show()

    def apply_exp_value(self):
        if not self.exp_dlg.expressionText() or not self.exp_builder.isExpressionValid():
            return
        QApplication.setOverrideCursor(Qt.WaitCursor)
        exp = self.exp_dlg.expressionText()
        idx = self.handler.cell_pts_layer.addExpressionField(exp, QgsField('exp_val', QVariant.Double))
        self.handler.exp_field_idx = idx
        self.handler.write_block()
        QApplication.restoreOverrideCursor()
        self.raster.triggerRepaint()

    def activate_drawing(self):
        self.mode = 'draw'
        self.canvas.setMapTool(self.draw_tool)

    def get_cur_line_width(self):
        width_coef = {
            "map units": 1.,
            "pixel width": self.raster.rasterUnitsPerPixelX(),
            "pixel height": self.raster.rasterUnitsPerPixelY(),
            "hairline": 0.000001,
        }
        return self.line_width_sbox.value() * width_coef[self.width_unit_cbo.currentText()]

    def set_selection_tool(self, mode):
        if self.raster is None:
            self.uc.bar_warn("Select a raster layer")
            return
        self.selection_mode = mode
        self.selection_tool.init_tool(self.raster, mode=self.selection_mode, line_width=self.get_cur_line_width())
        self.selection_tool.set_prev_tool(self.canvas.mapTool())
        self.canvas.setMapTool(self.selection_tool)

    def activate_line_selection(self):
        self.set_selection_tool(self.LINE_SELECTION)

    def activate_polygon_selection(self):
        self.set_selection_tool(self.POLYGON_SELECTION)

    def update_selection_tool(self):
        """Reactivate the selection tool with updated line width and units."""
        if self.selection_mode == self.LINE_SELECTION:
            self.activate_line_selection()
        elif self.selection_mode == self.POLYGON_SELECTION:
            self.activate_polygon_selection()
        else:
            pass

    def apply_values(self, new_values):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.handler.select(self.selection_tool.selected_geometries, all_touched_cells=self.all_touched)
        self.handler.write_block(new_values)
        QApplication.restoreOverrideCursor()
        self.raster.triggerRepaint()

    def apply_values_single_cell(self, new_vals):
        """Create single cell selection and apply the new values."""
        cp = self.last_point
        if self.logger:
            self.logger.debug(f"Changing single cell for pt {cp}")
        col, row = self.handler.point_to_index([cp.x(), cp.y()])
        px, py = self.handler.index_to_point(row, col, upper_left=False)
        d = 0.001
        bbox = QgsRectangle(px - d, py - d, px + d, py + d)
        if self.logger:
            self.logger.debug(f"Changing single cell in {bbox}")
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.handler.select([QgsGeometry.fromRect(bbox)], all_touched_cells=False, transform=False)
        self.handler.write_block(new_vals)
        QApplication.restoreOverrideCursor()
        self.raster.triggerRepaint()

    def apply_spin_box_values(self):
        if not self.selection_tool.selected_geometries:
            return
        self.apply_values(self.spin_boxes.get_values())

    def apply_nodata_value(self):
        if not self.selection_tool.selected_geometries:
            return
        self.apply_values(self.handler.nodata_values)

    def apply_low_pass_filter(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.handler.select(self.selection_tool.selected_geometries, all_touched_cells=self.all_touched)
        self.handler.write_block(low_pass_filter=True)
        QApplication.restoreOverrideCursor()
        self.raster.triggerRepaint()

    def clear_selection(self):
        if self.selection_tool:
            self.selection_tool.clear_all_selections()

    def selection_from_layer(self):
        """Create a new selection from layer."""
        self.selection_tool.init_tool(self.raster, mode=self.POLYGON_SELECTION, line_width=self.get_cur_line_width())
        dlg = LayerSelectDialog()
        if not dlg.exec_():
            return
        cur_layer = dlg.cbo.currentLayer()
        if not cur_layer.type() == QgsMapLayerType.VectorLayer:
            return
        self.selection_tool.selection_from_layer(cur_layer)

    def selection_to_layer(self):
        """Create a memory layer from current selection"""
        geoms = self.selection_tool.selected_geometries
        if geoms is None or not self.raster:
            return
        crs_str = self.raster.crs().toProj()
        nr = self.selection_layers_count
        self.selection_layers_count += 1
        mlayer = QgsVectorLayer(f"Polygon?crs={crs_str}&field=fid:int", f"Raster selection {nr}", "memory")
        fields = mlayer.dataProvider().fields()
        features = []
        for i, geom in enumerate(geoms):
            feat = QgsFeature(fields)
            feat["fid"] = i + 1
            feat.setGeometry(geom)
            features.append(feat)
        mlayer.dataProvider().addFeatures(features)
        self.project.addMapLayer(mlayer)

    def toggle_all_touched(self):
        """Toggle selection mode."""
        # button is toggled automatically when clicked, just update the attribute
        self.all_touched = self.toggle_all_touched_btn.isChecked()

    def point_clicked(self, point=None, button=None):
        if self.raster is None:
            self.uc.bar_warn("Choose a raster to work with...", dur=3)
            return

        if self.logger:
            self.logger.debug(f"Clicked point in canvas CRS: {point if point else self.last_point}")

        if point is None:
            ptxy_in_src_crs = self.last_point
        else:
            if self.crs_transform:
                if self.logger:
                    self.logger.debug(f"Transforming clicked point {point}")
                try:
                    ptxy_in_src_crs = self.crs_transform.transform(point)
                except QgsCsException as err:
                    self.uc.show_warn(
                        "Point coordinates transformation failed! Check the raster projection:\n\n{}".format(repr(err)))
                    return
            else:
                ptxy_in_src_crs = QgsPointXY(point.x(), point.y())

        if self.logger:
            self.logger.debug(f"Clicked point in raster CRS: {ptxy_in_src_crs}")
        self.last_point = ptxy_in_src_crs

        ident_vals = self.handler.provider.identify(ptxy_in_src_crs, QgsRaster.IdentifyFormatValue).results()
        cur_vals = list(ident_vals.values())

        # check if the point is within active raster extent
        if not self.rbounds[0] <= ptxy_in_src_crs.x() <= self.rbounds[2]:
            self.uc.bar_info("Out of x bounds", dur=3)
            return
        if not self.rbounds[1] <= ptxy_in_src_crs.y() <= self.rbounds[3]:
            self.uc.bar_info("Out of y bounds", dur=3)
            return

        if self.mode == 'draw':
            new_vals = self.spin_boxes.get_values()
            if self.logger:
                self.logger.debug(f"Applying const value {new_vals}")
            self.apply_values_single_cell(new_vals)
        else:
            self.spin_boxes.set_values(cur_vals)
            if 2 < self.handler.bands_nr < 5:
                self.color_picker_connection(connect=False)
                self.color_btn.setColor(QColor(*self.spin_boxes.get_values()[:4]))
                self.color_picker_connection(connect=True)

    def set_values_from_picker(self, c):
        """Set bands spinboxes values after color change in the color picker"""
        values = None
        if self.handler.bands_nr > 2:
            values = [c.red(), c.green(), c.blue()]
            if self.handler.bands_nr == 4:
                values.append(c.alpha())
        if values:
            self.spin_boxes.set_values(values)

    def set_nodata(self):
        """Set NoData value(s) for each band of current raster."""
        if not self.raster:
            self.uc.bar_warn('Select a raster layer to define/change NoData value!')
            return
        if self.handler.provider.userNoDataValues(1):
            note = '\nNote: there is a user defined NODATA value.\nCheck the raster properties (Transparency).'
        else:
            note = ''
        dt = self.handler.provider.dataType(1)
        
        # current NODATA value
        if self.handler.provider.sourceHasNoDataValue(1):
            cur_nodata = self.handler.provider.sourceNoDataValue(1)
            if dt < 6:
                cur_nodata = '{0:d}'.format(int(float(cur_nodata)))
        else:
            cur_nodata = ''
        
        label = 'Define/change raster NODATA value.\n\n'
        label += 'Raster src_data type: {}.{}'.format(dtypes[dt]['name'], note)
        nd, ok = QInputDialog.getText(None, "Define NODATA Value", label, QLineEdit.Normal, str(cur_nodata))
        if not ok:
            return
        if not is_number(nd):
            self.uc.show_warn('Wrong NODATA value!')
            return
        new_nodata = int(nd) if dt < 6 else float(nd)
        
        # set the NODATA value for each band
        res = []
        for nr in self.handler.bands_range:
            res.append(self.handler.provider.setNoDataValue(nr, new_nodata))
            self.handler.provider.sourceHasNoDataValue(nr)
        
        if False in res:
            self.uc.show_warn('Setting new NODATA value failed!')
        else:
            self.uc.bar_info('Successful setting new NODATA values!', dur=2)

        self.set_active_raster()
        self.raster.triggerRepaint()
        
    def check_undo_redo_btns(self):
        """Enable/Disable undo and redo buttons based on availability of undo/redo for current raster."""
        self.undo_btn.setDisabled(True)
        self.redo_btn.setDisabled(True)
        if self.raster is None or self.raster.id() not in self.changes:
            return
        changes = self.changes[self.raster.id()]
        if changes.nr_undos() > 0:
            self.undo_btn.setEnabled(True)
        if changes.nr_redos() > 0:
            self.redo_btn.setEnabled(True)

    def enable_toolbar_actions(self, enable=True):
        """Enable / disable all toolbar actions but Help (for vectors and unsupported rasters)"""
        for widget in self.actions + [self.width_unit_cbo, self.line_width_sbox]:
            widget.setEnabled(enable)
            if widget in self.actions_always_on:
                widget.setEnabled(True)
        self.spin_boxes.enable(enable)

    @staticmethod
    def check_layer(layer):
        """Check if we can work with the raster"""
        if layer is None:
            return False
        if layer.type() != QgsMapLayerType.RasterLayer:
            return False
        if layer.providerType() != 'gdal':
            return False
        if all([
            layer.isValid(),
            layer.crs() is not None,
            check_gdal_driver_create_option(layer),                 # GDAL driver has CREATE option
            os.path.isfile(layer.dataProvider().dataSourceUri()),   # is it a local file?
        ]):
            return True
        else:
            return False

    def set_bands_cbo(self):
        self.bands_cbo.currentIndexChanged.disconnect(self.update_active_bands)
        self.bands_cbo.clear()
        for band in self.handler.bands_range:
            self.bands_cbo.addItem(f"{band}", [band])
        if self.handler.bands_nr > 1:
            self.bands_cbo.addItem(self.RGB, [1, 2, 3])
        self.bands_cbo.setCurrentIndex(0)
        self.bands_cbo.currentIndexChanged.connect(self.update_active_bands)

    def update_active_bands(self, idx):
        bands = self.bands_cbo.currentData()
        self.handler.active_bands = bands
        self.spin_boxes.create_spinboxes(bands, self.handler.data_types, self.handler.nodata_values)
        self.color_btn.setEnabled(len(bands) > 1)
        self.exp_dlg_btn.setEnabled(len(bands) == 1)

    def set_active_raster(self):
        """Active layer has changed - check if it is a raster layer and prepare it for the plugin"""
        old_spin_boxes_values = self.spin_boxes.get_values()
        self.crs_transform = None
        layer = self.iface.activeLayer()
        if self.check_layer(layer):
            self.raster = layer
            self.crs_transform = None if self.project.crs() == self.raster.crs() else \
                QgsCoordinateTransform(self.project.crs(), self.raster.crs(), self.project)
            self.handler = RasterHandler(self.raster, self.uc, self.debug)
            supported, unsupported_type = self.handler.write_supported()
            if supported:
                self.enable_toolbar_actions()
                self.set_bands_cbo()
                self.spin_boxes.create_spinboxes(self.handler.active_bands,
                                                 self.handler.data_types, self.handler.nodata_values)
                if self.handler.bands_nr == len(old_spin_boxes_values):
                    self.spin_boxes.set_values(old_spin_boxes_values)
                self.bands_cbo.setEnabled(self.handler.bands_nr > 1)
                self.color_btn.setEnabled(len(self.handler.active_bands) > 1)
                self.rbounds = self.raster.extent().toRectF().getCoords()
                self.handler.raster_changed.connect(self.add_to_undo)
                if self.raster.id() not in self.changes:
                    self.changes[self.raster.id()] = RasterChanges(nr_to_keep=self.settings["undo_steps"])
            else:
                msg = f"The raster has unsupported src_data type: {unsupported_type}"
                msg += "\nServal can't work with it, sorry..."
                self.uc.show_warn(msg)
                self.enable_toolbar_actions(enable=False)
                self.reset_raster()
        
        else:
            # unsupported raster
            self.enable_toolbar_actions(enable=False)
            self.reset_raster()

        self.check_undo_redo_btns()

    def add_to_undo(self, change):
        """Add the old and new blocks to undo stack."""
        self.changes[self.raster.id()].add_change(change)
        self.check_undo_redo_btns()
        if self.logger:
            self.logger.debug(self.get_undo_redo_values())

    def get_undo_redo_values(self):
        changes = self.changes[self.raster.id()]
        return f"nr undos: {changes.nr_undos()}, redos: {changes.nr_redos()}"

    def undo(self):
        undo_data = self.changes[self.raster.id()].undo()
        self.handler.write_block_undo(undo_data)
        self.raster.triggerRepaint()
        self.check_undo_redo_btns()

    def redo(self):
        redo_data = self.changes[self.raster.id()].redo()
        self.handler.write_block_undo(redo_data)
        self.raster.triggerRepaint()
        self.check_undo_redo_btns()

    def reset_raster(self):
        self.raster = None
        self.color_btn.setDisabled(True)

    def color_picker_connection(self, connect=True):
        if connect:
            self.color_btn.colorChanged.connect(self.set_values_from_picker)
        else:
            self.color_btn.colorChanged.disconnect(self.set_values_from_picker)

    @staticmethod
    def show_website():
        QDesktopServices.openUrl(QUrl("https://github.com/lutraconsulting/serval/blob/master/Serval/docs/user_manual.md"))

    def recreate_spatial_index(self, layer):
        """Check if spatial index exists for the layer and if it is relatively old and eventually recreate it."""
        ctime = self.spatial_index_time[layer.id()] if layer.id() in self.spatial_index_time else None
        if ctime is None or datetime.now() - ctime > timedelta(seconds=30):
            self.spatial_index = QgsSpatialIndex(layer.getFeatures(), None, QgsSpatialIndex.FlagStoreFeatureGeometries)
            self.spatial_index_time[layer.id()] = datetime.now()

    def get_nearest_feature(self, pt_feat, vlayer_id):
        """Given the point feature, return nearest feature from vlayer."""
        vlayer = self.project.mapLayer(vlayer_id)
        self.recreate_spatial_index(vlayer)
        ptxy = pt_feat.geometry().asPoint()
        near_fid = self.spatial_index.nearestNeighbor(ptxy)[0]
        return vlayer.getFeature(near_fid)

    def nearest_feature_attr_value(self, pt_feat, vlayer_id, attr_name):
        """Find nearest feature to pt_feat and return its attr_name attribute value."""
        near_feat = self.get_nearest_feature(pt_feat, vlayer_id)
        return near_feat[attr_name]

    def nearest_pt_on_line_interpolate_z(self, pt_feat, vlayer_id):
        """Find nearest line feature to pt_feat and interpolate z value from vertices."""
        near_feat = self.get_nearest_feature(pt_feat, vlayer_id)
        near_geom = near_feat.geometry()
        closest_pt_dist = near_geom.lineLocatePoint(pt_feat.geometry())
        closest_pt = near_geom.interpolate(closest_pt_dist)
        return closest_pt.get().z()

    def intersecting_features_attr_average(self, pt_feat, vlayer_id, attr_name, only_center):
        """
        Find all features intersecting current feature (cell center, or raster cell polygon) and calculate average
        value of their attr_name attribute.
        """
        vlayer = self.project.mapLayer(vlayer_id)
        self.recreate_spatial_index(vlayer)
        ptxy = pt_feat.geometry().asPoint()
        pt_x, pt_y = ptxy.x(), ptxy.y()
        dxy = 0.001
        half_pix_x = self.handler.pixel_size_x / 2.
        half_pix_y = self.handler.pixel_size_y / 2.
        if only_center:
            cell = QgsRectangle(pt_x, pt_y, pt_x + dxy, pt_y + dxy)
        else:
            cell = QgsRectangle(pt_x - half_pix_x, pt_y - half_pix_y,
                                pt_x + half_pix_x, pt_y + half_pix_y)
        inter_fids = self.spatial_index.intersects(cell)
        values = []
        for fid in inter_fids:
            feat = vlayer.getFeature(fid)
            if not feat.geometry().intersects(cell):
                continue
            val = feat[attr_name]
            if not is_number(val):
                continue
            values.append(val)
        if len(values) == 0:
            return None
        return sum(values) / float(len(values))

    def interpolate_from_mesh(self, pt_feat, mesh_layer_id, group, dataset, above_existing):
        """Interpolate from mesh."""
        mesh_layer = self.project.mapLayer(mesh_layer_id)
        ptxy = pt_feat.geometry().asPoint()
        dataset_val = mesh_layer.datasetValue(QgsMeshDatasetIndex(group, dataset), ptxy)
        val = dataset_val.scalar()
        if math.isnan(val):
            return val
        if above_existing:
            ident_vals = self.handler.provider.identify(ptxy, QgsRaster.IdentifyFormatValue).results()
            org_val = list(ident_vals.values())[0]
            if org_val == self.handler.nodata_values[0]:
                return val
            return max(org_val, val)
        else:
            return val
Exemple #58
0
 def createEditor(self, parent, option, index):
     editor = QComboBox(parent)
     for key, text in FieldsMappingModel.fieldTypes.items():
         editor.addItem(text, key)
     return editor
Exemple #59
0
 def createEditor(self, parent, option, index):
     editor = QComboBox(parent)
     for function in AGGREGATES:
         editor.addItem(function, function)
     return editor
Exemple #60
0
class FieldsMappingWidgetWrapper(WidgetWrapper):
    def __init__(self, *args, **kwargs):
        super(FieldsMappingWidgetWrapper, self).__init__(*args, **kwargs)
        self._layer = None

    def createPanel(self):
        return FieldsMappingPanel()

    def createWidget(self):
        self.panel = self.createPanel()
        self.panel.dialogType = self.dialogType

        self.panel.setContextGenerator(self)

        if self.dialogType == DIALOG_MODELER:
            self.combobox = QComboBox()
            self.combobox.addItem(
                QCoreApplication.translate('Processing', '[Preconfigure]'),
                None)
            fieldsMappingInputs = self.dialog.getAvailableValuesOfType(
                FieldsMapper.ParameterFieldsMapping)
            for input in fieldsMappingInputs:
                self.combobox.addItem(
                    self.dialog.resolveValueDescription(input), input)

            def updatePanelEnabledState():
                if self.combobox.currentData() is None:
                    self.panel.setEnabled(True)
                else:
                    self.panel.setEnabled(False)

            self.combobox.currentIndexChanged.connect(updatePanelEnabledState)

            widget = QWidget()
            widget.setLayout(QVBoxLayout())
            widget.layout().addWidget(self.combobox)
            widget.layout().addWidget(self.panel)
            return widget
        else:
            return self.panel

    def postInitialize(self, wrappers):
        for wrapper in wrappers:
            if wrapper.parameterDefinition().name(
            ) == self.parameterDefinition().parentLayerParameter():
                if wrapper.parameterValue():
                    self.setLayer(wrapper.parameterValue())
                wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
                break

        # remove exiting spacers to get FieldsMappingPanel fully expanded
        if self.dialogType in (DIALOG_STANDARD, DIALOG_MODELER):
            layout = self.widget.parent().layout()
            spacer = layout.itemAt(layout.count() - 1)
            if isinstance(spacer, QSpacerItem):
                layout.removeItem(spacer)

    def parentLayerChanged(self, layer=None):
        self.setLayer(self.sender().value())

    def setLayer(self, layer):
        context = dataobjects.createContext()
        if layer == self._layer:
            return
        if isinstance(layer, QgsProcessingFeatureSourceDefinition):
            layer, ok = layer.source.valueAsString(context.expressionContext())
        if isinstance(layer, str):
            layer = QgsProcessingUtils.mapLayerFromString(layer, context)
        if not isinstance(layer, QgsVectorLayer):
            layer = None
        self._layer = layer
        self.panel.setLayer(self._layer)

    def linkedVectorLayer(self):
        return self._layer

    def setValue(self, value):
        self.panel.setValue(value)

    def value(self):
        if self.dialogType == DIALOG_MODELER:
            if self.combobox.currentData() is None:
                return self.panel.value()
            else:
                return self.comboValue(combobox=self.combobox)
        else:
            return self.panel.value()