def createWidget(self): if self.dialogType == DIALOG_STANDARD: if self.param.multiline: widget = QPlainTextEdit() if self.param.default: widget.setPlainText(self.param.default) else: widget = StringInputPanel(self.param) if self.param.default: widget.setValue(self.param.default) elif self.dialogType == DIALOG_BATCH: widget = QLineEdit() if self.param.default: widget.setText(self.param.default) else: strings = self.dialog.getAvailableValuesOfType(ParameterString, OutputString) options = [(self.dialog.resolveValueDescription(s), s) for s in strings] if self.param.multiline: widget = MultilineTextPanel(options) widget.setText(self.param.default or "") else: widget = QComboBox() widget.setEditable(True) for desc, val in options: widget.addItem(desc, val) widget.setEditText(self.param.default or "") return widget
def createWidget(self): if self.dialogType == DIALOG_STANDARD: if self.param.multiline: widget = QPlainTextEdit() if self.param.default: widget.setPlainText(self.param.default) else: widget = StringInputPanel(self.param) if self.param.default: widget.setValue(self.param.default) elif self.dialogType == DIALOG_BATCH: widget = QLineEdit() if self.param.default: widget.setText(self.param.default) else: # strings, numbers, files and table fields are all allowed input types strings = self.dialog.getAvailableValuesOfType([ParameterString, ParameterNumber, ParameterFile, ParameterTableField, ParameterExpression], OutputString) options = [(self.dialog.resolveValueDescription(s), s) for s in strings] if self.param.multiline: widget = MultilineTextPanel(options) widget.setText(self.param.default or "") else: widget = QComboBox() widget.setEditable(True) for desc, val in options: widget.addItem(desc, val) widget.setEditText(self.param.default or "") return widget
class ErrorReportDialog(QDialog): def __init__(self, title, message, errors, username, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(title) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(message, self) self.verticalLayout.addWidget(self.label) self.plainTextEdit = QPlainTextEdit(self) self.plainTextEdit.setPlainText(errors) self.plainTextEdit.setReadOnly(True) self.verticalLayout.addWidget(self.plainTextEdit) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Close) self.verticalLayout.addWidget(self.buttonBox) self.reportButton = self.buttonBox.addButton(self.tr("Report error"), QDialogButtonBox.ActionRole) self.reportButton.clicked.connect(self.__reportError) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.username = username self.metadata = MetaData() def __reportError(self): body = ("Please provide any additional information here:\n\n\n" "If you encountered an upload error, if possible please attach a zip file containing a minimal extract of the dataset, as well as the QGIS project file.\n\n\n" "Technical information:\n%s\n\n" "Versions:\n" " QGIS: %s\n" " Python: %s\n" " OS: %s\n" " QGIS Cloud Plugin: %s\n\n" "Username: %s\n") % ( self.plainTextEdit.toPlainText(), Qgis.QGIS_VERSION, sys.version.replace("\n", " "), platform.platform(), self.metadata.version(), self.username) url = QUrl() url.toEncoded("mailto:[email protected]?subject=%s&body=%s" % ( urllib.parse.quote(self.windowTitle()), urllib.parse.quote(body)), ) QDesktopServices.openUrl(url)
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)
class GdalParametersPanel(ParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__(self, parent, alg) w = QWidget() layout = QVBoxLayout() layout.setMargin(0) layout.setSpacing(6) label = QLabel() label.setText(self.tr("GDAL/OGR console call")) layout.addWidget(label) self.text = QPlainTextEdit() self.text.setReadOnly(True) layout.addWidget(self.text) w.setLayout(layout) self.layoutMain.addWidget(w) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for wrapper in list(self.wrappers.values()): w = wrapper.widget if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) def parametersHaveChanged(self): try: parameters = self.parent.getParamValues() for output in self.alg.destinationParameterDefinitions(): if parameters[output.name()] is None: parameters[output.name()] = self.tr("[temporary file]") commands = self.alg.getConsoleCommands(parameters) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description())) except: self.text.setPlainText("")
class FromShapefileParametersPanel(ChloeParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__(self, parent, alg) ## Création le l'interface Qt pour les paramètres ## Add console command w = QWidget() # New Qt Windows layout = QVBoxLayout() # New Qt vertical Layout layout.setMargin(0) layout.setSpacing(6) label = QLabel() # New Qt label (text) label.setText(self.tr("Chloe/Java console call")) layout.addWidget(label) # Add label in layout self.text = QPlainTextEdit() # New Qt champs de text in/out self.text.setReadOnly(True) # Read only layout.addWidget(self.text) # Add in layout w.setLayout(layout) # layout -in-> Windows self.layoutMain.addWidget(w) # windows -in-> Windows system for output in self.alg.outputs: if isinstance(output, (OutputRaster, OutputVector, OutputTable)): self.checkBoxes[output.name].setText(self.tr('Open output file after running algorithm')) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for w in self.widgets.values(): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, CSVFieldSelectionPanel): w.leText.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, CustomFileSelectionPanel): w.leText.textChanged.connect(self.parametersHaveChanged) w.leText.textChanged.connect(self.cleanFieldDependent) # Clean # Update console display self.valueItems["SAVE_PROPERTIES"].leText.textChanged.connect(self.parametersHaveChanged) #@pyqtSlot(str) def cleanFieldDependent(self): """ cleanFieldDependent When receiving signal, clean 'leText' of QWidget selectionned """ for w in self.widgets.values(): if isinstance(w, CSVFieldSelectionPanel): w.leText.setText("") #@pyqtSlot(str) def parametersHaveChanged(self): try: # === Update values of widgets-to->params === # For custom widget (like CustomPanel), overload AlgorithmDialog.setParamValue() # Important, can lunch exception if value is 'null' and 'required' self.parent.setParamValues() for output in self.alg.outputs: # Manage output fileds if output.value is None: output.value = self.tr("[temporary file]") properties = self.valueItems["SAVE_PROPERTIES"].leText.text() commands = self.alg.getConsoleCommands(properties) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '%s'") % e.parameter.description) except Exception as e: self.text.setPlainText("Error : " + e.message)
class GdalParametersPanel(ParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__(self, parent, alg) w = QWidget() layout = QVBoxLayout() layout.setMargin(0) layout.setSpacing(6) label = QLabel() label.setText(self.tr("GDAL/OGR console call")) layout.addWidget(label) self.text = QPlainTextEdit() self.text.setReadOnly(True) layout.addWidget(self.text) w.setLayout(layout) self.layoutMain.addWidget(w) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for wrapper in list(self.wrappers.values()): wrapper.widgetValueHasChanged.connect(self.parametersHaveChanged) # TODO - remove when all wrappers correctly emit widgetValueHasChanged! # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): w = wrapper.widget else: w = wrapper.wrappedWidget() self.connectWidgetChangedSignals(w) for c in w.findChildren(QWidget): self.connectWidgetChangedSignals(c) for output_widget in self.outputWidgets.values(): self.connectWidgetChangedSignals(output_widget) def connectWidgetChangedSignals(self, w): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QgsProjectionSelectionWidget): w.crsChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, DestinationSelectionPanel): w.destinationChanged.connect(self.parametersHaveChanged) def parametersHaveChanged(self): context = createContext() feedback = QgsProcessingFeedback() try: parameters = self.parent.getParameterValues() for output in self.alg.destinationParameterDefinitions(): if not output.name() in parameters or parameters[output.name()] is None: parameters[output.name()] = self.tr("[temporary file]") for p in self.alg.parameterDefinitions(): if (not p.name() in parameters and not p.flags() & QgsProcessingParameterDefinition.FlagOptional) \ or (not p.checkValueIsAcceptable(parameters[p.name()])): # not ready yet self.text.setPlainText('') return commands = self.alg.getConsoleCommands(parameters, context, feedback, executing=False) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description())) except AlgorithmDialogBase.InvalidOutputExtension as e: self.text.setPlainText(e.message)
class FilterParametersPanel(ChloeParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__( self, parent, alg) ## Création le l'interface Qt pour les paramètres ## Add console command w = QWidget() # New Qt Windows layout = QVBoxLayout() # New Qt vertical Layout layout.setMargin(0) layout.setSpacing(6) label = QLabel() # New Qt label (text) label.setText(self.tr("Chloe/Java console call")) layout.addWidget(label) # Add label in layout self.text = QPlainTextEdit() # New Qt champs de text in/out self.text.setReadOnly(True) # Read only layout.addWidget(self.text) # Add in layout w.setLayout(layout) # layout -in-> Windows self.layoutMain.addWidget(w) # windows -in-> Windows system for output in self.alg.outputs: if isinstance(output, (OutputRaster, OutputVector, OutputTable)): self.checkBoxes[output.name].setText( self.tr('Open output file after running algorithm')) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for w in self.widgets.values(): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, ValuesSelectionPanel): w.leText.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, CustomInputLayerSelectorPanel): w.currentIndexChanged.connect(self.parametersHaveChanged) w.currentIndexChanged.connect( self.cleanFieldDependent) # Clean # Update console display self.valueItems["SAVE_PROPERTIES"].leText.textChanged.connect( self.parametersHaveChanged) #@pyqtSlot(str) def cleanFieldDependent(self): """ cleanFieldDependent When receiving signal, clean 'leText' of QWidget selectionned """ for w in self.widgets.values(): if isinstance(w, ValuesSelectionPanel): w.leText.setText("") #@pyqtSlot(str) def parametersHaveChanged(self): try: # === Update values of widgets-to->params === # For custom widget (like CustomPanel), overload AlgorithmDialog.setParamValue() # Important, can lunch exception if value is 'null' and 'required' self.parent.setParamValues() # output for output in self.alg.outputs: # Manage output fileds if output.value is None: output.value = self.tr("[temporary file]") properties = self.valueItems["SAVE_PROPERTIES"].leText.text() commands = self.alg.getConsoleCommands(properties) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText( self.tr("Invalid value for parameter '%s'") % e.parameter.description) except Exception as e: self.text.setPlainText("Error : " + e.message) def getWidgetFromParameter(self, param): """ Overload for custom Qwidget(Panel) from Parameter return item : Qwidget(Panel) """ if isinstance(param, ParameterString) and param.name in ["FILTER_VALUES"]: # === Overload ParameterString for special parameter name like VALUES_RANGES,.. item = ValuesSelectionPanel(self.parent, self.alg, param.default, 'ASCII_FILTER') if param.default: item.setText(unicode(param.default)) elif isinstance(param, ParameterRaster): # === Overload of Panel for Raster in order to add signal for updating param layers = dataobjects.getRasterLayers() items = [] if param.optional: items.append((self.NOT_SELECTED, None)) self.NONE_SELECTED = self.tr('Chose a layer') items.append((self.NONE_SELECTED, "")) # Not use None for layer in layers: items.append((self.getExtendedLayerName(layer), layer)) item = CustomInputLayerSelectorPanel(items, param) else: # == default Wigdet from Parameter, i.e. use parent method item = ParametersPanel.getWidgetFromParameter(self, param) return item
class GdalParametersPanel(ParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__(self, parent, alg) w = QWidget() layout = QVBoxLayout() layout.setMargin(0) layout.setSpacing(6) label = QLabel() label.setText(self.tr("GDAL/OGR console call")) layout.addWidget(label) self.text = QPlainTextEdit() self.text.setReadOnly(True) layout.addWidget(self.text) w.setLayout(layout) self.layoutMain.addWidget(w) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for wrapper in list(self.wrappers.values()): w = wrapper.widget self.connectWidgetChangedSignals(w) for c in w.findChildren(QWidget): self.connectWidgetChangedSignals(c) def connectWidgetChangedSignals(self, w): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QgsProjectionSelectionWidget): w.crsChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) def parametersHaveChanged(self): context = createContext() feedback = QgsProcessingFeedback() try: parameters = self.parent.getParameterValues() for output in self.alg.destinationParameterDefinitions(): if not output.name() in parameters or parameters[output.name()] is None: parameters[output.name()] = self.tr("[temporary file]") for p in self.alg.parameterDefinitions(): if (not p.name() in parameters and not p.flags() & QgsProcessingParameterDefinition.FlagOptional) \ or (not p.checkValueIsAcceptable(parameters[p.name()], context)): # not ready yet self.text.setPlainText('') return commands = self.alg.getConsoleCommands(parameters, context, feedback, executing=False) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description()))
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) or isinstance(param, ParameterTableMultipleField): if isinstance(param, ParameterTableMultipleField): item = ListMultiSelectWidget() else: item = QComboBox() if param.parent in self.dependentItems: items = self.dependentItems[param.parent] else: items = [] self.dependentItems[param.parent] = items items.append(param) 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 and isinstance(param, ParameterTableField): 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
class CommitDialog(QDialog): def __init__(self, repo, layername, _message = "", parent = None): super(CommitDialog, self).__init__(parent) self.repo = repo self.branch = None self.layername = layername self._message = _message or suggestedMessage self.message = None self.initGui() def initGui(self): self.setObjectName("CommitDialog") self.resize(600, 250) self.setWindowTitle("Syncronize layer to repository branch") self.verticalLayout = QVBoxLayout() self.verticalLayout.setSpacing(2) self.verticalLayout.setMargin(5) self.branchLabel = QLabel("Branch") self.verticalLayout.addWidget(self.branchLabel) self.branchCombo = QComboBox() self.branches = [] branches = self.repo.branches() for branch in branches: trees = self.repo.trees(branch) if self.layername in trees: self.branches.append(branch) self.branchCombo.addItems(self.branches) try: idx = self.branches.index("master") except: idx = 0 self.branchCombo.setCurrentIndex(idx) self.verticalLayout.addWidget(self.branchCombo) self.msgLabel = QLabel("Message to describe this update") self.verticalLayout.addWidget(self.msgLabel) self.text = QPlainTextEdit() self.text.setPlainText(self._message) self.verticalLayout.addWidget(self.text) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) self.verticalLayout.addWidget(self.buttonBox) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(bool(self.branches)) self.setLayout(self.verticalLayout) self.buttonBox.accepted.connect(self.okPressed) self.text.setFocus() def okPressed(self): self.branch = self.branchCombo.currentText() self.message = self.text.toPlainText() or datetime.now().strftime("%Y-%m-%d %H_%M_%S") self.close()
class GdalParametersPanel(ParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__(self, parent, alg) w = QWidget() layout = QVBoxLayout() layout.setMargin(0) layout.setSpacing(6) label = QLabel() label.setText(self.tr("GDAL/OGR console call")) layout.addWidget(label) self.text = QPlainTextEdit() self.text.setReadOnly(True) layout.addWidget(self.text) w.setLayout(layout) self.layoutMain.addWidget(w) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for wrapper in list(self.wrappers.values()): w = wrapper.widget self.connectWidgetChangedSignals(w) for c in w.findChildren(QWidget): self.connectWidgetChangedSignals(c) for output_widget in self.outputWidgets.values(): self.connectWidgetChangedSignals(output_widget) def connectWidgetChangedSignals(self, w): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QgsProjectionSelectionWidget): w.crsChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, DestinationSelectionPanel): w.destinationChanged.connect(self.parametersHaveChanged) def parametersHaveChanged(self): context = createContext() feedback = QgsProcessingFeedback() try: parameters = self.parent.getParameterValues() for output in self.alg.destinationParameterDefinitions(): if not output.name() in parameters or parameters[ output.name()] is None: parameters[output.name()] = self.tr("[temporary file]") for p in self.alg.parameterDefinitions(): if (not p.name() in parameters and not p.flags() & QgsProcessingParameterDefinition.FlagOptional) \ or (not p.checkValueIsAcceptable(parameters[p.name()])): # not ready yet self.text.setPlainText('') return commands = self.alg.getConsoleCommands(parameters, context, feedback, executing=False) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText( self.tr("Invalid value for parameter '{0}'").format( e.parameter.description()))
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
class GdalParametersPanel(ParametersPanel): def __init__(self, parent, alg): super().__init__(parent, alg) self.dialog = parent w = QWidget() layout = QVBoxLayout() layout.setMargin(0) layout.setSpacing(6) label = QLabel() label.setText(self.tr("GDAL/OGR console call")) layout.addWidget(label) self.text = QPlainTextEdit() self.text.setReadOnly(True) layout.addWidget(self.text) w.setLayout(layout) self.addExtraWidget(w) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for wrapper in list(self.wrappers.values()): wrapper.widgetValueHasChanged.connect(self.parametersHaveChanged) # TODO - remove when all wrappers correctly emit widgetValueHasChanged! # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): w = wrapper.widget else: w = wrapper.wrappedWidget() self.connectWidgetChangedSignals(w) for c in w.findChildren(QWidget): self.connectWidgetChangedSignals(c) def connectWidgetChangedSignals(self, w): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QgsProjectionSelectionWidget): w.crsChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, QgsProcessingLayerOutputDestinationWidget): w.destinationChanged.connect(self.parametersHaveChanged) def parametersHaveChanged(self): context = createContext() feedback = QgsProcessingFeedback() try: # messy as all heck, but we don't want to call the dialog's implementation of # createProcessingParameters as we want to catch the exceptions raised by the # parameter panel instead... parameters = {} if self.dialog.mainWidget() is None else self.dialog.mainWidget().createProcessingParameters() for output in self.algorithm().destinationParameterDefinitions(): if not output.name() in parameters or parameters[output.name()] is None: if not output.flags() & QgsProcessingParameterDefinition.FlagOptional: parameters[output.name()] = self.tr("[temporary file]") for p in self.algorithm().parameterDefinitions(): if p.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if p.flags() & QgsProcessingParameterDefinition.FlagOptional and p.name() not in parameters: continue if p.name() not in parameters or not p.checkValueIsAcceptable(parameters[p.name()]): # not ready yet self.text.setPlainText('') return commands = self.algorithm().getConsoleCommands(parameters, context, feedback, executing=False) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description())) except AlgorithmDialogBase.InvalidOutputExtension as e: self.text.setPlainText(e.message)
class MapMultiParametersPanel(ChloeParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__(self, parent, alg) ## Création le l'interface Qt pour les paramètres ## Add console command w = QWidget() # New Qt Windows layout = QVBoxLayout() # New Qt vertical Layout layout.setMargin(0) layout.setSpacing(6) label = QLabel() # New Qt label (text) label.setText(self.tr("Chloe/Java console call")) layout.addWidget(label) # Add label in layout self.text = QPlainTextEdit() # New Qt champs de text in/out self.text.setReadOnly(True) # Read only layout.addWidget(self.text) # Add in layout w.setLayout(layout) # layout -in-> Windows self.layoutMain.addWidget(w) # windows -in-> Windows system for output in self.alg.outputs: if isinstance(output, (OutputRaster, OutputVector, OutputTable)): self.checkBoxes[output.name].setText(self.tr('Open output file after running algorithm')) self.connectParameterSignals() self.parametersHaveChanged() # === Init cbFilter cbFilter = self.widgets["METRICS"].cbFilter cbFilter.addItems(self.alg.types_of_metrics.keys()) # === Init listSrc value = cbFilter.currentText() listSrc = self.widgets["METRICS"].listSrc listSrc.clear() listSrc.addItems(self.alg.types_of_metrics[value]) # === Init listDest listDest = self.widgets["METRICS"].listDest listDest.clear() self.metrics_selected = set() lineEdit = self.widgets["METRICS"].lineEdit lineEdit.setReadOnly(True) def connectParameterSignals(self): for w in self.widgets.values(): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, FileSelectionPanel): w.cmbText.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, InputLayerSelectorPanel): w.cmbText.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, ListSelectionPanel): w.pbRight.clicked.connect(self.addInListDst) w.listSrc.itemDoubleClicked.connect(self.addInListDst) w.pbLeft.clicked.connect(self.removeInListDst) w.pbAll.clicked.connect(self.addAllInListDst) w.pbClear.clicked.connect(self.removeAllListDst) w.lineEdit.textChanged.connect(self.parametersHaveChanged) # Update console display self.valueItems["SAVE_PROPERTIES"].leText.textChanged.connect(self.parametersHaveChanged) w = self.widgets["METRICS"].cbFilter w.currentIndexChanged.connect(self.changeMetricDependent) @staticmethod def iterAllItems(lws): for i in range(lws.count()): yield lws.item(i) #@pyqtSlot(str) def addAllInListDst(self): self.addInListDst(all=True) #@pyqtSlot(str) def addInListDst(self,item=None,all=False): """Add metrics selected in listSrc to ListDst""" if not all: selected = self.widgets["METRICS"].listSrc.selectedItems() else: selected = self.iterAllItems(self.widgets["METRICS"].listSrc) for lw in selected: self.metrics_selected.add(lw.text()) listDest = self.widgets["METRICS"].listDest listDest.clear() listDest.addItems(list(self.metrics_selected)) self.updateMetricsLigneEdit() #@pyqtSlot() def removeAllListDst(self): listDest = self.widgets["METRICS"].listDest listDest.clear() self.metrics_selected = set() self.updateMetricsLigneEdit() #@pyqtSlot(str) def removeInListDst(self): """Remove metrics selected in listDest""" selected = self.widgets["METRICS"].listDest.selectedItems() for lw in selected: self.metrics_selected.remove(lw.text()) listDest = self.widgets["METRICS"].listDest listDest.clear() listDest.addItems(list(self.metrics_selected)) self.updateMetricsLigneEdit() def updateMetricsLigneEdit(self): """update Metrics (QLineEdit in readOnly mode)""" lineEdit = self.widgets["METRICS"].lineEdit metrics = list(self.metrics_selected) if metrics: lineEdit.setText(";".join(metrics)) else: lineEdit.setText("") #@pyqtSlot(str) def changeMetricDependent(self): """ Update metric source list when the filter of metric change """ cbFilter = self.widgets["METRICS"].cbFilter # === Init list metric value = cbFilter.currentText() listSrc = self.widgets["METRICS"].listSrc listSrc.clear() listSrc.addItems(self.alg.types_of_metrics[value]) #@pyqtSlot(str) def parametersHaveChanged(self): try: # === Update values of widgets-to->params === # For custom widget (like CustomPanel), overload AlgorithmDialog.setParamValue() # Important, can lunch exception if value is 'null' and 'required' self.parent.setParamValues() for output in self.alg.outputs: # Manage output fileds if output.value is None: output.value = self.tr("[temporary file]") properties = self.valueItems["SAVE_PROPERTIES"].leText.text() commands = self.alg.getConsoleCommands(properties) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '%s'") % e.parameter.description) except Exception as e: self.text.setPlainText("Error : " + e.message) #raise e def getWidgetFromParameter(self, param): """ Overload for custom Qwidget(Panel) from Parameter return item : Qwidget(Panel) """ if param.name in ["METRICS"]: # === Overload ParameterString for special parameter name like FIELDS,..s item = ListSelectionPanel(self.parent, self.alg, param.default) else: # == default Wigdet from Parameter, i.e. use parent method item = ParametersPanel.getWidgetFromParameter(self,param) return item
class OverlayParametersPanel(ChloeParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__( self, parent, alg) ## Création le l'interface Qt pour les paramètres ## Add console command w = QWidget() # New Qt Windows layout = QVBoxLayout() # New Qt vertical Layout layout.setMargin(0) layout.setSpacing(6) label = QLabel() # New Qt label (text) label.setText(self.tr("Chloe/Java console call")) layout.addWidget(label) # Add label in layout self.text = QPlainTextEdit() # New Qt champs de text in/out self.text.setReadOnly(True) # Read only layout.addWidget(self.text) # Add in layout w.setLayout(layout) # layout -in-> Windows self.layoutMain.addWidget(w) # windows -in-> Windows system for output in self.alg.outputs: if isinstance(output, (OutputRaster, OutputVector, OutputTable)): self.checkBoxes[output.name].setText( self.tr('Open output file after running algorithm')) self.connectParameterSignals() self.parametersHaveChanged() def connectParameterSignals(self): for w in self.widgets.values(): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, FileSelectionPanel): w.leText.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, InputLayerSelectorPanel): w.cmbText.currentIndexChanged.connect( self.parametersHaveChanged) # Update console display self.valueItems["SAVE_PROPERTIES"].leText.textChanged.connect( self.parametersHaveChanged) #@pyqtSlot(str) def parametersHaveChanged(self): try: self.parent.setParamValues() for output in self.alg.outputs: # Manage output fileds if output.value is None: output.value = self.tr("[temporary file]") properties = self.valueItems["SAVE_PROPERTIES"].leText.text() commands = self.alg.getConsoleCommands(properties) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText( self.tr("Invalid value for parameter '%s'") % e.parameter.description) except Exception as e: self.text.setPlainText("Error : " + e.message) #raise e def getWidgetFromParameter(self, param): """ Overload for custom Qwidget(Panel) from Parameter return item : Qwidget(Panel) """ if param.name in ["INPUTS_MATRIX"]: options = dataobjects.getRasterLayers(sorting=False) opts = [self.getExtendedLayerName(opt) for opt in options] item = OrderedMultipleInputPanel(opts) else: # == default Wigdet from Parameter, i.e. use parent method item = ParametersPanel.getWidgetFromParameter(self, param) return item
class SelectedParametersPanel(ChloeParametersPanel): def __init__(self, parent, alg): ParametersPanel.__init__( self, parent, alg) ## Création le l'interface Qt pour les paramètres ## Add console command w = QWidget() # New Qt Windows layout = QVBoxLayout() # New Qt vertical Layout layout.setMargin(0) layout.setSpacing(6) label = QLabel() # New Qt label (text) label.setText(self.tr("Chloe/Java console call")) layout.addWidget(label) # Add label in layout self.text = QPlainTextEdit() # New Qt champs de text in/out self.text.setReadOnly(True) # Read only layout.addWidget(self.text) # Add in layout w.setLayout(layout) # layout -in-> Windows self.layoutMain.addWidget(w) # windows -in-> Windows system self.types_of_metrics = {} for output in self.alg.outputs: if isinstance(output, (OutputRaster, OutputVector, OutputTable)): self.checkBoxes[output.name].setText( self.tr('Open output file after running algorithm')) self.connectParameterSignals() self.parametersHaveChanged() self.changePixelsPointsSelectDependent() self.changeWindowShapeDependent() # === Init cbFilter cbFilter = self.widgets["METRICS"].cbFilter cbFilter.addItems(self.alg.types_of_metrics.keys()) # === Init listSrc filter_txt = cbFilter.currentText() w_value = self.widgets["METRICS"].cbValue w_value.clear() if self.types_of_metrics: if filter_txt in self.types_of_metrics.keys(): w_value.addItems(self.types_of_metrics[filter_txt]) def connectParameterSignals(self): for w in self.widgets.values(): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, FileSelectionPanel): w.leText.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, InputLayerSelectorPanel): w.cmbText.currentIndexChanged.connect(self.initCalculateMetric) w.cmbText.currentIndexChanged.connect( self.parametersHaveChanged) w.cmbText.currentIndexChanged.connect(self.updateMetric) elif isinstance(w, DoubleCmbBoxSelectionPanel): w.cbFilter.currentIndexChanged.connect(self.updateMetric) w.cbValue.currentIndexChanged.connect( self.parametersHaveChanged) elif isinstance(w, ValuesSelectionPanel): w.leText.textChanged.connect(self.parametersHaveChanged) w = self.widgets["WINDOW_SHAPE"] w.currentIndexChanged.connect(self.changeWindowShapeDependent) w = self.widgets["WINDOW_SIZES"] w.spnValue.setSingleStep(2) # step incrementation and decrementation w = self.widgets["PIXELS_POINTS_SELECT"] w.currentIndexChanged.connect(self.changePixelsPointsSelectDependent) # Update console display self.valueItems["SAVE_PROPERTIES"].leText.textChanged.connect( self.parametersHaveChanged) w = self.widgets["METRICS"].cbFilter w.currentIndexChanged.emit(0) self.widgets["INPUT_LAYER_ASC"].cmbText.currentIndexChanged.emit(0) #@pyqtSlot(str) def initCalculateMetric(self): w = self.widgets['INPUT_LAYER_ASC'] try: val = w.getValue() if isinstance(val, QgsRasterLayer): rasterLayerParam = val.source().encode('utf-8') else: rasterLayerParam = val.encode('utf-8') int_values_and_nodata = ChloeUtils.extractValueNotNull( rasterLayerParam) self.types_of_metrics = ChloeUtils.calculateMetric( self.alg.types_of_metrics, self.alg.types_of_metrics_simple, self.alg.types_of_metrics_cross, int_values_and_nodata) except: self.types_of_metrics = [] # === param:PIXELS_POINTS_SELECT Widget:ComboBox #@pyqtSlot(str) def changePixelsPointsSelectDependent(self): index = self.widgets["PIXELS_POINTS_SELECT"].currentIndex() if index == 0: # pixel(s) file self.widgets["PIXELS_FILE"].leText.setDisabled(False) self.widgets["POINTS_FILE"].leText.setDisabled(True) elif index == 1: # point(s) file self.widgets["PIXELS_FILE"].leText.setDisabled(True) self.widgets["POINTS_FILE"].leText.setDisabled(False) # === param:WINDOW_SHAPE Widget:ComboBox #@pyqtSlot(str) def changeWindowShapeDependent(self): txt = self.widgets["WINDOW_SHAPE"].currentText() if txt == "FUNCTIONAL": self.widgets["FRICTION_FILE"].setEnabled(True) else: self.widgets["FRICTION_FILE"].setDisabled(True) #@pyqtSlot(str) def updateMetric(self): filter_txt = self.widgets["METRICS"].cbFilter.currentText() w_value = self.widgets["METRICS"].cbValue w_value.clear() if self.types_of_metrics: if filter_txt in self.types_of_metrics.keys(): w_value.addItems(self.types_of_metrics[filter_txt]) # == One parameter have changed == #@pyqtSlot(str) def parametersHaveChanged(self): try: # === Update values of widgets-to->params === # For custom widget (like CustomPanel), overload AlgorithmDialog.setParamValue() # Important, can lunch exception if value is 'null' and 'required' self.parent.setParamValues() for output in self.alg.outputs: # Manage output fileds if output.value is None: output.value = self.tr("[temporary file]") properties = self.valueItems["SAVE_PROPERTIES"].leText.text() commands = self.alg.getConsoleCommands(properties) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText( self.tr("Invalid value for parameter '%s'") % e.parameter.description) except Exception as e: self.text.setPlainText("Error : " + e.message) #raise e def getWidgetFromParameter(self, param): """ Overload for custom Qwidget(Panel) from Parameter return item : Qwidget(Panel) """ if param.name in ["METRICS"]: # === Overload ParameterString for special parameter name like FIELDS,..s item = DoubleCmbBoxSelectionPanel(self.parent, self.alg, param.default) elif param.name in ["FILTER", "UNFILTER"]: # === Overload ParameterString for special parameter name like FIELDS,..s item = ValuesSelectionPanel(self.parent, self.alg, param.default, 'INPUT_LAYER_ASC') if param.default: item.setText(unicode(param.default)) elif isinstance(param, ParameterRaster): # === Overload of Panel for Raster in order to add signal for updating param layers = dataobjects.getRasterLayers() items = [] if param.optional: items.append((self.NOT_SELECTED, None)) self.NONE_SELECTED = self.tr('Chose a layer') items.append((self.NONE_SELECTED, "")) # Not use None for layer in layers: items.append((self.getExtendedLayerName(layer), layer)) item = InputLayerSelectorPanel(items, param) else: # == default Wigdet from Parameter, i.e. use parent method item = ParametersPanel.getWidgetFromParameter(self, param) return item
class ChloeParametersPanel(ParametersPanel): def __init__(self, parent, alg): super().__init__(parent, alg) w = QWidget() layout = QVBoxLayout() layout.setMargin(0) layout.setSpacing(6) label = QLabel() label.setText(self.tr("Chloe Command line")) layout.addWidget(label) self.text = QPlainTextEdit() self.text.setReadOnly(True) layout.addWidget(self.text) w.setLayout(layout) self.layoutMain.addWidget(w) self.connectParameterSignals() self.parametersHaveChanged() # def initWidgets(self): # """Init widget panel for each input output""" # super().initWidgets() # for output_name, output_panel in self.outputWidgets.items(): # # # Add check box for automacial load after process algorithm # # for 'OUTPUT_ASC' (QgsProcessingParameterFileDestination) # if output_name == 'OUTPUT_ASC': # check = QCheckBox() # check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file after running algorithm')) # # def skipOutputChanged(checkbox, skipped): # checkbox.setEnabled(not skipped) # if skipped: # checkbox.setChecked(False) # check.setChecked(not output_panel.outputIsSkipped()) # check.setEnabled(not output_panel.outputIsSkipped()) # # output_panel.skipOutputChanged.connect(partial(skipOutputChanged, check)) # self.layoutMain.insertWidget(self.layoutMain.count() - 1, check) # self.checkBoxes[output_name] = check def initWidgets(self): # Heavy overload # If there are advanced parameters — show corresponding groupbox for param in self.alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.grpAdvanced.show() break #widget_context = QgsProcessingParameterWidgetContext() #if iface is not None: # widget_context.setMapCanvas(iface.mapCanvas()) # Create widgets and put them in layouts for param in self.alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue print('initWidgets - param.name(): {}'.format(param.name())) if param.isDestination(): # and param.name() != 'OUTPUT_ASC': continue else: wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent) self.wrappers[param.name()] = wrapper #widget = wrapper.widget # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove is_python_wrapper = issubclass(wrapper.__class__, WidgetWrapper) if not is_python_wrapper: from qgis.gui import (QgsProcessingContextGenerator, QgsProcessingParameterWidgetContext) widget_context = QgsProcessingParameterWidgetContext() if iface is not None: widget_context.setMapCanvas(iface.mapCanvas()) wrapper.setWidgetContext(widget_context) widget = wrapper.createWrappedWidget(self.processing_context) wrapper.registerProcessingContextGenerator(self.context_generator) else: widget = wrapper.widget #if self.in_place and param.name() in ('INPUT', 'OUTPUT'): # don't show the input/output parameter widgets in in-place mode # we still need to CREATE them, because other wrappers may need to interact # with them (e.g. those parameters which need the input layer for field # selections/crs properties/etc) # continue if widget is not None: if is_python_wrapper: widget.setToolTip(param.toolTip()) if isinstance(param, QgsProcessingParameterFeatureSource): layout = QHBoxLayout() layout.setSpacing(6) layout.setMargin(0) layout.addWidget(widget) button = QToolButton() icon = QIcon(os.path.join(pluginPath, 'images', 'iterate.png')) button.setIcon(icon) button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) button.setToolTip(self.tr('Iterate over this layer, creating a separate output for every feature in the layer')) button.setCheckable(True) layout.addWidget(button) layout.setAlignment(button, Qt.AlignTop) self.iterateButtons[param.name()] = button button.toggled.connect(self.buttonToggled) widget = QWidget() widget.setLayout(layout) label = None if not is_python_wrapper: label = wrapper.createWrappedLabel() else: label = wrapper.label if label is not None: if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.layoutAdvanced.addWidget(label) else: self.layoutMain.insertWidget( self.layoutMain.count() - 2, label) elif is_python_wrapper: desc = param.description() if isinstance(param, QgsProcessingParameterExtent): desc += self.tr(' (xmin, xmax, ymin, ymax)') if isinstance(param, QgsProcessingParameterPoint): desc += self.tr(' (x, y)') if param.flags() & QgsProcessingParameterDefinition.FlagOptional: desc += self.tr(' [optional]') widget.setText(desc) if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced: self.layoutAdvanced.addWidget(widget) else: self.layoutMain.insertWidget( self.layoutMain.count() - 2, widget) for output in self.alg.destinationParameterDefinitions(): if output.flags() & QgsProcessingParameterDefinition.FlagHidden: continue #if self.in_place and param.name() in ('INPUT', 'OUTPUT'): # continue label = QLabel(output.description()) #print('initWidgets 2 - param.name(): {}'.format(param.name())) widget = DestinationSelectionPanel(output, self.alg) # TODO, overload self.layoutMain.insertWidget(self.layoutMain.count() - 1, label) self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget) if isinstance(output, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination # alk: checkboxes for Chloe handling ,ChloeCSVParameterFileDestination, ChloeASCParameterFileDestination, ChloeParameterFolderDestination) ): check = QCheckBox() check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file(s) after running algorithm')) def skipOutputChanged(checkbox, skipped): checkbox.setEnabled(not skipped) if skipped: checkbox.setChecked(False) check.setChecked(not widget.outputIsSkipped()) check.setEnabled(not widget.outputIsSkipped()) widget.skipOutputChanged.connect(partial(skipOutputChanged, check)) self.layoutMain.insertWidget(self.layoutMain.count() - 1, check) self.checkBoxes[output.name()] = check # initial state if hasattr(output,'addToMapDefaultState'): check.setChecked(output.addToMapDefaultState) widget.setToolTip(param.toolTip()) self.outputWidgets[output.name()] = widget for wrapper in list(self.wrappers.values()): wrapper.postInitialize(list(self.wrappers.values())) # # alk: checkboxes for Chloe handling # for output in self.alg.destinationParameterDefinitions(): # if output.flags() & QgsProcessingParameterDefinition.FlagHidden: # continue # if isinstance(output, (ChloeCSVParameterFileDestination)) or isinstance(output, (ChloeASCParameterFileDestination)): # check = QCheckBox() # check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file(s) after running algorithm')) # def skipOutputChanged(checkbox, skipped): # checkbox.setEnabled(not skipped) # if skipped: # checkbox.setChecked(False) # check.setChecked(not widget.outputIsSkipped()) # check.setEnabled(not widget.outputIsSkipped()) # widget.skipOutputChanged.connect(partial(skipOutputChanged, check)) # print(str(self.layoutMain)+1) # self.layoutMain.insertWidget(self.layoutMain.count() - 1, check) # self.checkBoxes[output.name()] = check # # connecting alg outputLoading info with checkbox state # self.alg.outputLoading[output.name()] = check.isChecked() # def updateOutputLoadingState(alg, outputName, checkbox, state): # self.alg.outputLoading[outputName] = checkbox.isChecked() # print( outputName + " " + str(checkbox.isChecked()) + " " + str(self.alg.outputLoading) + " " + str(self.alg)) # #print(str(self.alg.parameters)) # check.stateChanged.connect(partial(updateOutputLoadingState, self, output.name(), check)) # alk: addition of wrapper special config handling # for dependancy between wrapper, i.e. changing the value # of a FileSelectionPanel entails the update of another widget for k in self.wrappers: w = self.wrappers[k] if hasattr(w,'getParentWidgetConfig'): print(str(w) + " " + "getParentWidgetConfig") config = w.getParentWidgetConfig() if config != None: p = self.wrappers[config['paramName']] m = getattr(w, config['refreshMethod']) if m!=None: print(str(p) + " " + str(p.widget)) # todo generalize valueChanged handling # to any type of widget componant if isinstance(p.widget, FileSelectionPanel): p.widget.leText.textChanged.connect(m) elif isinstance(p, RasterWidgetWrapper): try: p.combo.valueChanged.connect(m) # QGIS 3.8 version except: p.combo.currentIndexChanged.connect(m) # QGIS LTR 3.4 def connectParameterSignals(self): for wrapper in list(self.wrappers.values()): wrapper.widgetValueHasChanged.connect(self.parametersHaveChanged) # TODO - remove when all wrappers correctly emit widgetValueHasChanged! # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): w = wrapper.widget else: w = wrapper.wrappedWidget() self.connectWidgetChangedSignals(w) for c in w.findChildren(QWidget): self.connectWidgetChangedSignals(c) for output_widget in self.outputWidgets.values(): self.connectWidgetChangedSignals(output_widget) def connectWidgetChangedSignals(self, w): if isinstance(w, QLineEdit): w.textChanged.connect(self.parametersHaveChanged) elif isinstance(w, QComboBox): w.currentIndexChanged.connect(self.parametersHaveChanged) elif isinstance(w, QgsProjectionSelectionWidget): w.crsChanged.connect(self.parametersHaveChanged) elif isinstance(w, QCheckBox): w.stateChanged.connect(self.parametersHaveChanged) elif isinstance(w, MultipleInputPanel): w.selectionChanged.connect(self.parametersHaveChanged) elif isinstance(w, NumberInputPanel): w.hasChanged.connect(self.parametersHaveChanged) elif isinstance(w, DestinationSelectionPanel): w.destinationChanged.connect(self.parametersHaveChanged) def parametersHaveChanged(self): context = createContext() feedback = QgsProcessingFeedback() try: parameters = self.parent.getParameterValues() for output in self.alg.destinationParameterDefinitions(): if not output.name() in parameters or parameters[output.name()] is None: parameters[output.name()] = self.tr("[temporary file]") for p in self.alg.parameterDefinitions(): if (not p.name() in parameters and not p.flags() & QgsProcessingParameterDefinition.FlagOptional) \ or (not p.checkValueIsAcceptable(parameters[p.name()])): # not ready yet self.text.setPlainText('') return commands = self.alg.getConsoleCommands(parameters, context, feedback, executing=False) commands = [c for c in commands if c not in ['cmd.exe', '/C ']] self.text.setPlainText(" ".join(commands)) except AlgorithmDialogBase.InvalidParameterValue as e: self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description())) if e.parameter.name()=='MAP_CSV': raise