mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-10-31 00:06:02 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			2529 lines
		
	
	
		
			89 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			2529 lines
		
	
	
		
			89 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| ***************************************************************************
 | |
|     wrappers.py - Standard parameters widget wrappers
 | |
|     ---------------------
 | |
|     Date                 : May 2016
 | |
|     Copyright            : (C) 2016 by Arnaud Morvan, Victor Olaya
 | |
|     Email                : arnaud dot morvan at camptocamp dot com
 | |
|                            volayaf at gmail dot com
 | |
| ***************************************************************************
 | |
| *                                                                         *
 | |
| *   This program is free software; you can redistribute it and/or modify  *
 | |
| *   it under the terms of the GNU General Public License as published by  *
 | |
| *   the Free Software Foundation; either version 2 of the License, or     *
 | |
| *   (at your option) any later version.                                   *
 | |
| *                                                                         *
 | |
| ***************************************************************************
 | |
| """
 | |
| 
 | |
| __author__ = "Arnaud Morvan"
 | |
| __date__ = "May 2016"
 | |
| __copyright__ = "(C) 2016, Arnaud Morvan"
 | |
| 
 | |
| import os
 | |
| import re
 | |
| from inspect import isclass
 | |
| from copy import deepcopy
 | |
| 
 | |
| from qgis.core import (
 | |
|     QgsApplication,
 | |
|     QgsCoordinateReferenceSystem,
 | |
|     QgsExpression,
 | |
|     QgsFieldProxyModel,
 | |
|     QgsSettings,
 | |
|     QgsProject,
 | |
|     QgsMapLayerType,
 | |
|     QgsVectorLayer,
 | |
|     QgsProcessing,
 | |
|     QgsProcessingUtils,
 | |
|     QgsProcessingParameterDefinition,
 | |
|     QgsProcessingParameterBoolean,
 | |
|     QgsProcessingParameterCrs,
 | |
|     QgsProcessingParameterExtent,
 | |
|     QgsProcessingParameterPoint,
 | |
|     QgsProcessingParameterFile,
 | |
|     QgsProcessingParameterMultipleLayers,
 | |
|     QgsProcessingParameterNumber,
 | |
|     QgsProcessingParameterRasterLayer,
 | |
|     QgsProcessingParameterEnum,
 | |
|     QgsProcessingParameterString,
 | |
|     QgsProcessingParameterExpression,
 | |
|     QgsProcessingParameterVectorLayer,
 | |
|     QgsProcessingParameterMeshLayer,
 | |
|     QgsProcessingParameterField,
 | |
|     QgsProcessingParameterFeatureSource,
 | |
|     QgsProcessingParameterMapLayer,
 | |
|     QgsProcessingParameterBand,
 | |
|     QgsProcessingParameterMatrix,
 | |
|     QgsProcessingParameterDistance,
 | |
|     QgsProcessingParameterDuration,
 | |
|     QgsProcessingFeatureSourceDefinition,
 | |
|     QgsProcessingOutputRasterLayer,
 | |
|     QgsProcessingOutputVectorLayer,
 | |
|     QgsProcessingOutputMapLayer,
 | |
|     QgsProcessingOutputMultipleLayers,
 | |
|     QgsProcessingOutputFile,
 | |
|     QgsProcessingOutputString,
 | |
|     QgsProcessingOutputNumber,
 | |
|     QgsProcessingModelChildParameterSource,
 | |
|     NULL,
 | |
|     Qgis,
 | |
| )
 | |
| 
 | |
| from qgis.PyQt.QtWidgets import (
 | |
|     QCheckBox,
 | |
|     QComboBox,
 | |
|     QLabel,
 | |
|     QDialog,
 | |
|     QFileDialog,
 | |
|     QHBoxLayout,
 | |
|     QLineEdit,
 | |
|     QPlainTextEdit,
 | |
|     QToolButton,
 | |
|     QWidget,
 | |
|     QSizePolicy,
 | |
| )
 | |
| from qgis.PyQt.QtGui import QIcon
 | |
| from qgis.gui import (
 | |
|     QgsGui,
 | |
|     QgsExpressionLineEdit,
 | |
|     QgsExpressionBuilderDialog,
 | |
|     QgsFieldComboBox,
 | |
|     QgsFieldExpressionWidget,
 | |
|     QgsProjectionSelectionDialog,
 | |
|     QgsMapLayerComboBox,
 | |
|     QgsProjectionSelectionWidget,
 | |
|     QgsRasterBandComboBox,
 | |
|     QgsProcessingGui,
 | |
|     QgsAbstractProcessingParameterWidgetWrapper,
 | |
|     QgsProcessingMapLayerComboBox,
 | |
| )
 | |
| from qgis.PyQt.QtCore import QVariant, Qt
 | |
| from qgis.utils import iface
 | |
| 
 | |
| from processing.core.ProcessingConfig import ProcessingConfig
 | |
| from processing.modeler.MultilineTextPanel import MultilineTextPanel
 | |
| 
 | |
| from processing.gui.NumberInputPanel import (
 | |
|     NumberInputPanel,
 | |
|     ModelerNumberInputPanel,
 | |
|     DistanceInputPanel,
 | |
| )
 | |
| from processing.gui.RangePanel import RangePanel
 | |
| from processing.gui.PointSelectionPanel import PointSelectionPanel
 | |
| from processing.gui.FileSelectionPanel import FileSelectionPanel
 | |
| from processing.gui.CheckboxesPanel import CheckboxesPanel
 | |
| from processing.gui.MultipleInputPanel import MultipleInputPanel
 | |
| from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
 | |
| from processing.gui.FixedTablePanel import FixedTablePanel
 | |
| from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel
 | |
| 
 | |
| from processing.tools import dataobjects
 | |
| 
 | |
| DIALOG_STANDARD = QgsProcessingGui.WidgetType.Standard
 | |
| DIALOG_BATCH = QgsProcessingGui.WidgetType.Batch
 | |
| DIALOG_MODELER = QgsProcessingGui.WidgetType.Modeler
 | |
| 
 | |
| pluginPath = os.path.split(os.path.dirname(__file__))[0]
 | |
| 
 | |
| 
 | |
| class InvalidParameterValue(Exception):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| dialogTypes = {
 | |
|     "AlgorithmDialog": DIALOG_STANDARD,
 | |
|     "ModelerParametersDialog": DIALOG_MODELER,
 | |
|     "BatchAlgorithmDialog": DIALOG_BATCH,
 | |
| }
 | |
| 
 | |
| 
 | |
| def getExtendedLayerName(layer):
 | |
|     authid = layer.crs().authid()
 | |
|     if (
 | |
|         ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF)
 | |
|         and authid is not None
 | |
|     ):
 | |
|         return f"{layer.name()} [{authid}]"
 | |
|     else:
 | |
|         return layer.name()
 | |
| 
 | |
| 
 | |
| class WidgetWrapper(QgsAbstractProcessingParameterWidgetWrapper):
 | |
|     NOT_SET_OPTION = "~~~~!!!!NOT SET!!!!~~~~~~~"
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         self.dialogType = dialogTypes.get(
 | |
|             dialog.__class__.__name__, QgsProcessingGui.WidgetType.Standard
 | |
|         )
 | |
|         super().__init__(param, self.dialogType)
 | |
| 
 | |
|         self.dialog = dialog
 | |
|         self.row = row
 | |
|         self.col = col
 | |
| 
 | |
|         self.widget = self.createWidget(**kwargs)
 | |
|         self.label = self.createLabel()
 | |
|         if param.defaultValue() is not None:
 | |
|             self.setValue(param.defaultValue())
 | |
| 
 | |
|     def comboValue(self, validator=None, combobox=None):
 | |
|         if combobox is None:
 | |
|             combobox = self.widget
 | |
|         idx = combobox.findText(combobox.currentText())
 | |
|         if idx < 0:
 | |
|             v = combobox.currentText().strip()
 | |
|             if validator is not None and not validator(v):
 | |
|                 raise InvalidParameterValue()
 | |
|             return v
 | |
|         if combobox.currentData() == self.NOT_SET_OPTION:
 | |
|             return None
 | |
|         elif combobox.currentData() is not None:
 | |
|             return combobox.currentData()
 | |
|         else:
 | |
|             return combobox.currentText()
 | |
| 
 | |
|     def createWidget(self, **kwargs):
 | |
|         pass
 | |
| 
 | |
|     def createLabel(self):
 | |
|         if self.dialogType == DIALOG_BATCH:
 | |
|             return None
 | |
|         desc = self.parameterDefinition().description()
 | |
|         if isinstance(self.parameterDefinition(), QgsProcessingParameterExtent):
 | |
|             desc += self.tr(" (xmin, xmax, ymin, ymax)")
 | |
|         if isinstance(self.parameterDefinition(), QgsProcessingParameterPoint):
 | |
|             desc += self.tr(" (x, y)")
 | |
|         if (
 | |
|             self.parameterDefinition().flags()
 | |
|             & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|         ):
 | |
|             desc += self.tr(" [optional]")
 | |
| 
 | |
|         label = QLabel(desc)
 | |
|         label.setToolTip(self.parameterDefinition().name())
 | |
|         return label
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         pass
 | |
| 
 | |
|     def value(self):
 | |
|         return None
 | |
| 
 | |
|     def widgetValue(self):
 | |
|         return self.value()
 | |
| 
 | |
|     def setWidgetValue(self, value, context):
 | |
|         self.setValue(value)
 | |
| 
 | |
|     def setComboValue(self, value, combobox=None):
 | |
|         if combobox is None:
 | |
|             combobox = self.widget
 | |
|         if isinstance(value, list):
 | |
|             if value:
 | |
|                 value = value[0]
 | |
|             else:
 | |
|                 value = None
 | |
|         values = [combobox.itemData(i) for i in range(combobox.count())]
 | |
|         try:
 | |
|             idx = values.index(value)
 | |
|             combobox.setCurrentIndex(idx)
 | |
|             return
 | |
|         except ValueError:
 | |
|             pass
 | |
|         if combobox.isEditable():
 | |
|             if value is not None:
 | |
|                 combobox.setEditText(str(value))
 | |
|         else:
 | |
|             combobox.setCurrentIndex(0)
 | |
| 
 | |
|     def refresh(self):
 | |
|         pass
 | |
| 
 | |
|     def getFileName(self, initial_value=""):
 | |
|         """Shows a file open dialog"""
 | |
|         settings = QgsSettings()
 | |
|         if os.path.isdir(initial_value):
 | |
|             path = initial_value
 | |
|         elif os.path.isdir(os.path.dirname(initial_value)):
 | |
|             path = os.path.dirname(initial_value)
 | |
|         elif settings.contains("/Processing/LastInputPath"):
 | |
|             path = str(settings.value("/Processing/LastInputPath"))
 | |
|         else:
 | |
|             path = ""
 | |
| 
 | |
|         # TODO: should use selectedFilter argument for default file format
 | |
|         filename, selected_filter = QFileDialog.getOpenFileName(
 | |
|             self.widget,
 | |
|             self.tr("Select File"),
 | |
|             path,
 | |
|             self.parameterDefinition().createFileFilter(),
 | |
|         )
 | |
|         if filename:
 | |
|             settings.setValue(
 | |
|                 "/Processing/LastInputPath", os.path.dirname(str(filename))
 | |
|             )
 | |
|         return filename, selected_filter
 | |
| 
 | |
| 
 | |
| class BasicWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def createWidget(self):
 | |
|         return QLineEdit()
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         self.widget.setText(value)
 | |
| 
 | |
|     def value(self):
 | |
|         return self.widget.text()
 | |
| 
 | |
| 
 | |
| class BooleanWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "BooleanWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createLabel(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             return None
 | |
|         else:
 | |
|             return super().createLabel()
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             return QCheckBox()
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             widget = QComboBox()
 | |
|             widget.addItem(self.tr("Yes"), True)
 | |
|             widget.addItem(self.tr("No"), False)
 | |
|             return widget
 | |
|         else:
 | |
|             widget = QComboBox()
 | |
|             widget.addItem(self.tr("Yes"), True)
 | |
|             widget.addItem(self.tr("No"), False)
 | |
|             bools = self.dialog.getAvailableValuesOfType(
 | |
|                 QgsProcessingParameterBoolean, None
 | |
|             )
 | |
|             for b in bools:
 | |
|                 widget.addItem(self.dialog.resolveValueDescription(b), b)
 | |
|             return widget
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             self.widget.setChecked(value)
 | |
|         else:
 | |
|             self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             return self.widget.isChecked()
 | |
|         else:
 | |
|             return self.comboValue()
 | |
| 
 | |
| 
 | |
| class CrsWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "CrsWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_MODELER:
 | |
|             self.combo = QComboBox()
 | |
|             widget = QWidget()
 | |
|             layout = QHBoxLayout()
 | |
|             layout.setMargin(0)
 | |
|             layout.setContentsMargins(0, 0, 0, 0)
 | |
|             layout.setSpacing(1)
 | |
|             layout.addWidget(self.combo)
 | |
|             btn = QToolButton()
 | |
|             btn.setIcon(QgsApplication.getThemeIcon("mActionSetProjection.svg"))
 | |
|             btn.setToolTip(self.tr("Select CRS"))
 | |
|             btn.clicked.connect(self.selectProjection)
 | |
|             layout.addWidget(btn)
 | |
| 
 | |
|             widget.setLayout(layout)
 | |
|             self.combo.setEditable(True)
 | |
|             crss = self.dialog.getAvailableValuesOfType(
 | |
|                 (QgsProcessingParameterCrs, QgsProcessingParameterString),
 | |
|                 QgsProcessingOutputString,
 | |
|             )
 | |
|             for crs in crss:
 | |
|                 self.combo.addItem(self.dialog.resolveValueDescription(crs), crs)
 | |
|             layers = self.dialog.getAvailableValuesOfType(
 | |
|                 [
 | |
|                     QgsProcessingParameterRasterLayer,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMeshLayer,
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                 ],
 | |
|                 [
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputRasterLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                 ],
 | |
|             )
 | |
|             for l in layers:
 | |
|                 self.combo.addItem(
 | |
|                     "Crs of layer " + self.dialog.resolveValueDescription(l), l
 | |
|                 )
 | |
|             if self.parameterDefinition().defaultValue():
 | |
|                 self.combo.setEditText(self.parameterDefinition().defaultValue())
 | |
|             return widget
 | |
|         else:
 | |
|             widget = QgsProjectionSelectionWidget()
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 widget.setOptionVisible(
 | |
|                     QgsProjectionSelectionWidget.CrsOption.CrsNotSet, True
 | |
|                 )
 | |
| 
 | |
|             if self.parameterDefinition().defaultValue():
 | |
|                 if self.parameterDefinition().defaultValue() == "ProjectCrs":
 | |
|                     crs = QgsProject.instance().crs()
 | |
|                 else:
 | |
|                     crs = QgsCoordinateReferenceSystem(
 | |
|                         self.parameterDefinition().defaultValue()
 | |
|                     )
 | |
|                 widget.setCrs(crs)
 | |
|             else:
 | |
|                 widget.setOptionVisible(
 | |
|                     QgsProjectionSelectionWidget.CrsOption.CrsNotSet, True
 | |
|                 )
 | |
| 
 | |
|             widget.crsChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
| 
 | |
|     def selectProjection(self):
 | |
|         dialog = QgsProjectionSelectionDialog(self.widget)
 | |
|         current_crs = QgsCoordinateReferenceSystem(self.combo.currentText())
 | |
|         if current_crs.isValid():
 | |
|             dialog.setCrs(current_crs)
 | |
| 
 | |
|         if dialog.exec():
 | |
|             self.setValue(dialog.crs().authid())
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType == DIALOG_MODELER:
 | |
|             self.setComboValue(value, self.combo)
 | |
|         elif value == "ProjectCrs":
 | |
|             self.widget.setCrs(QgsProject.instance().crs())
 | |
|         else:
 | |
|             self.widget.setCrs(QgsCoordinateReferenceSystem(value))
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_MODELER:
 | |
|             return self.comboValue(combobox=self.combo)
 | |
|         else:
 | |
|             crs = self.widget.crs()
 | |
|             if crs.isValid():
 | |
|                 return self.widget.crs().authid()
 | |
|             else:
 | |
|                 return None
 | |
| 
 | |
| 
 | |
| class ExtentWidgetWrapper(WidgetWrapper):
 | |
|     USE_MIN_COVERING_EXTENT = "[Use min covering extent]"
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.14
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "ExtentWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             widget = ExtentSelectionPanel(self.dialog, self.parameterDefinition())
 | |
|             widget.hasChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             widget = QComboBox()
 | |
|             widget.setEditable(True)
 | |
|             extents = self.dialog.getAvailableValuesOfType(
 | |
|                 QgsProcessingParameterExtent, (QgsProcessingOutputString)
 | |
|             )
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 widget.addItem(self.USE_MIN_COVERING_EXTENT, None)
 | |
|             layers = self.dialog.getAvailableValuesOfType(
 | |
|                 [
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterRasterLayer,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMeshLayer,
 | |
|                 ],
 | |
|                 [
 | |
|                     QgsProcessingOutputRasterLayer,
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                 ],
 | |
|             )
 | |
|             for ex in extents:
 | |
|                 widget.addItem(self.dialog.resolveValueDescription(ex), ex)
 | |
|             for l in layers:
 | |
|                 widget.addItem("Extent of " + self.dialog.resolveValueDescription(l), l)
 | |
|             if not self.parameterDefinition().defaultValue():
 | |
|                 widget.setEditText(self.parameterDefinition().defaultValue())
 | |
|             return widget
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             self.widget.setExtentFromString(value)
 | |
|         else:
 | |
|             self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
|             idx = self.widget.findText(self.widget.currentText())
 | |
|             if idx < 0:
 | |
|                 s = str(self.widget.currentText()).strip()
 | |
|                 if s:
 | |
|                     try:
 | |
|                         tokens = s.split(",")
 | |
|                         if len(tokens) != 4:
 | |
|                             raise InvalidParameterValue()
 | |
|                         for token in tokens:
 | |
|                             float(token)
 | |
|                     except:
 | |
|                         raise InvalidParameterValue()
 | |
|                 elif (
 | |
|                     self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 ):
 | |
|                     s = None
 | |
|                 else:
 | |
|                     raise InvalidParameterValue()
 | |
|                 return s
 | |
|             else:
 | |
|                 return self.widget.currentData()
 | |
| 
 | |
| 
 | |
| class PointWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "PointWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return PointSelectionPanel(
 | |
|                 self.dialog, self.parameterDefinition().defaultValue()
 | |
|             )
 | |
|         else:
 | |
|             item = QComboBox()
 | |
|             item.setEditable(True)
 | |
|             points = self.dialog.getAvailableValuesOfType(
 | |
|                 (QgsProcessingParameterPoint, QgsProcessingParameterString),
 | |
|                 (QgsProcessingOutputString),
 | |
|             )
 | |
|             for p in points:
 | |
|                 item.addItem(self.dialog.resolveValueDescription(p), p)
 | |
|             item.setEditText(str(self.parameterDefinition().defaultValue()))
 | |
|             return item
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             self.widget.setPointFromString(value)
 | |
|         else:
 | |
|             self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
|             idx = self.widget.findText(self.widget.currentText())
 | |
|             if idx < 0:
 | |
|                 s = str(self.widget.currentText()).strip()
 | |
|                 if s:
 | |
|                     try:
 | |
|                         tokens = s.split(",")
 | |
|                         if len(tokens) != 2:
 | |
|                             raise InvalidParameterValue()
 | |
|                         for token in tokens:
 | |
|                             float(token)
 | |
|                     except:
 | |
|                         raise InvalidParameterValue()
 | |
|                 elif (
 | |
|                     self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 ):
 | |
|                     s = None
 | |
|                 else:
 | |
|                     raise InvalidParameterValue()
 | |
|                 return s
 | |
|             else:
 | |
|                 return self.widget.currentData()
 | |
| 
 | |
| 
 | |
| class FileWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "FileWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return FileSelectionPanel(
 | |
|                 self.parameterDefinition().behavior()
 | |
|                 == QgsProcessingParameterFile.Behavior.Folder,
 | |
|                 self.parameterDefinition().extension(),
 | |
|             )
 | |
|         else:
 | |
|             self.combo = QComboBox()
 | |
|             self.combo.setEditable(True)
 | |
|             files = self.dialog.getAvailableValuesOfType(
 | |
|                 QgsProcessingParameterFile,
 | |
|                 (
 | |
|                     QgsProcessingOutputRasterLayer,
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputFile,
 | |
|                     QgsProcessingOutputString,
 | |
|                 ),
 | |
|             )
 | |
|             for f in files:
 | |
|                 self.combo.addItem(self.dialog.resolveValueDescription(f), f)
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 self.combo.setEditText("")
 | |
|             widget = QWidget()
 | |
|             layout = QHBoxLayout()
 | |
|             layout.setMargin(0)
 | |
|             layout.setContentsMargins(0, 0, 0, 0)
 | |
|             layout.setSpacing(6)
 | |
|             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
 | |
| 
 | |
|     def selectFile(self):
 | |
|         settings = QgsSettings()
 | |
|         if os.path.isdir(os.path.dirname(self.combo.currentText())):
 | |
|             path = os.path.dirname(self.combo.currentText())
 | |
|         if settings.contains("/Processing/LastInputPath"):
 | |
|             path = settings.value("/Processing/LastInputPath")
 | |
|         else:
 | |
|             path = ""
 | |
| 
 | |
|         if self.parameterDefinition().extension():
 | |
|             filter = (
 | |
|                 self.tr("{} files").format(
 | |
|                     self.parameterDefinition().extension().upper()
 | |
|                 )
 | |
|                 + " (*."
 | |
|                 + self.parameterDefinition().extension()
 | |
|                 + self.tr(");;All files (*.*)")
 | |
|             )
 | |
|         else:
 | |
|             filter = self.tr("All files (*.*)")
 | |
| 
 | |
|         filename, selected_filter = QFileDialog.getOpenFileName(
 | |
|             self.widget, self.tr("Select File"), path, filter
 | |
|         )
 | |
|         if filename:
 | |
|             self.combo.setEditText(filename)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             self.widget.setText(value)
 | |
|         else:
 | |
|             self.setComboValue(value, combobox=self.combo)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
|             return self.comboValue(combobox=self.combo)
 | |
| 
 | |
| 
 | |
| class FixedTableWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "FixedTableWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return FixedTablePanel(self.parameterDefinition())
 | |
|         else:
 | |
|             self.combobox = QComboBox()
 | |
|             values = self.dialog.getAvailableValuesOfType(QgsProcessingParameterMatrix)
 | |
|             for v in values:
 | |
|                 self.combobox.addItem(self.dialog.resolveValueDescription(v), v)
 | |
|             return self.combobox
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             self.widget.setValue(value)
 | |
|         else:
 | |
|             self.setComboValue(value, combobox=self.combobox)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             return self.widget.table
 | |
|         else:
 | |
|             return self.comboValue(combobox=self.combobox)
 | |
| 
 | |
| 
 | |
| class MultipleLayerWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def _getOptions(self):
 | |
|         if (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeVectorAnyGeometry
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeVector
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|                 [QgsProcessing.SourceType.TypeVector],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeVectorPoint
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|                 [
 | |
|                     QgsProcessing.SourceType.TypeVectorPoint,
 | |
|                     QgsProcessing.SourceType.TypeVectorAnyGeometry,
 | |
|                 ],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeVectorLine
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|                 [
 | |
|                     QgsProcessing.SourceType.TypeVectorLine,
 | |
|                     QgsProcessing.SourceType.TypeVectorAnyGeometry,
 | |
|                 ],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeVectorPolygon
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|                 [
 | |
|                     QgsProcessing.SourceType.TypeVectorPolygon,
 | |
|                     QgsProcessing.SourceType.TypeVectorAnyGeometry,
 | |
|                 ],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeRaster
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterRasterLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputRasterLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType() == QgsProcessing.SourceType.TypeMesh
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (QgsProcessingParameterMeshLayer, QgsProcessingParameterMultipleLayers),
 | |
|                 [],
 | |
|             )
 | |
|         elif (
 | |
|             self.parameterDefinition().layerType()
 | |
|             == QgsProcessing.SourceType.TypeMapLayer
 | |
|         ):
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterRasterLayer,
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                     QgsProcessingParameterMeshLayer,
 | |
|                     QgsProcessingParameterMultipleLayers,
 | |
|                 ),
 | |
|                 [
 | |
|                     QgsProcessingOutputRasterLayer,
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputMultipleLayers,
 | |
|                 ],
 | |
|             )
 | |
|         else:
 | |
|             options = self.dialog.getAvailableValuesOfType(
 | |
|                 QgsProcessingParameterFile, QgsProcessingOutputFile
 | |
|             )
 | |
|         options = sorted(
 | |
|             options, key=lambda opt: self.dialog.resolveValueDescription(opt)
 | |
|         )
 | |
|         return options
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if (
 | |
|                 self.parameterDefinition().layerType()
 | |
|                 == QgsProcessing.SourceType.TypeFile
 | |
|             ):
 | |
|                 return MultipleInputPanel(datatype=QgsProcessing.SourceType.TypeFile)
 | |
|             else:
 | |
|                 if (
 | |
|                     self.parameterDefinition().layerType()
 | |
|                     == QgsProcessing.SourceType.TypeRaster
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleRasterLayers(
 | |
|                         QgsProject.instance(), False
 | |
|                     )
 | |
|                 elif (
 | |
|                     self.parameterDefinition().layerType()
 | |
|                     == QgsProcessing.SourceType.TypeMesh
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleMeshLayers(
 | |
|                         QgsProject.instance(), False
 | |
|                     )
 | |
|                 elif self.parameterDefinition().layerType() in (
 | |
|                     QgsProcessing.SourceType.TypeVectorAnyGeometry,
 | |
|                     QgsProcessing.SourceType.TypeVector,
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                         QgsProject.instance(), [], False
 | |
|                     )
 | |
|                 elif (
 | |
|                     self.parameterDefinition().layerType()
 | |
|                     == QgsProcessing.SourceType.TypeMapLayer
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                         QgsProject.instance(), [], False
 | |
|                     )
 | |
|                     options.extend(
 | |
|                         QgsProcessingUtils.compatibleRasterLayers(
 | |
|                             QgsProject.instance(), False
 | |
|                         )
 | |
|                     )
 | |
|                     options.extend(
 | |
|                         QgsProcessingUtils.compatibleMeshLayers(
 | |
|                             QgsProject.instance(), False
 | |
|                         )
 | |
|                     )
 | |
|                 else:
 | |
|                     options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                         QgsProject.instance(),
 | |
|                         [self.parameterDefinition().layerType()],
 | |
|                         False,
 | |
|                     )
 | |
|                 opts = [getExtendedLayerName(opt) for opt in options]
 | |
|                 return MultipleInputPanel(
 | |
|                     opts, datatype=self.parameterDefinition().layerType()
 | |
|                 )
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             widget = BatchInputSelectionPanel(
 | |
|                 self.parameterDefinition(), self.row, self.col, self.dialog
 | |
|             )
 | |
|             widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             options = [
 | |
|                 self.dialog.resolveValueDescription(opt) for opt in self._getOptions()
 | |
|             ]
 | |
|             return MultipleInputPanel(
 | |
|                 options, datatype=self.parameterDefinition().layerType()
 | |
|             )
 | |
| 
 | |
|     def refresh(self):
 | |
|         if self.parameterDefinition().layerType() != QgsProcessing.SourceType.TypeFile:
 | |
|             if (
 | |
|                 self.parameterDefinition().layerType()
 | |
|                 == QgsProcessing.SourceType.TypeRaster
 | |
|             ):
 | |
|                 options = QgsProcessingUtils.compatibleRasterLayers(
 | |
|                     QgsProject.instance(), False
 | |
|                 )
 | |
|             elif (
 | |
|                 self.parameterDefinition().layerType()
 | |
|                 == QgsProcessing.SourceType.TypeMesh
 | |
|             ):
 | |
|                 options = QgsProcessingUtils.compatibleMeshLayers(
 | |
|                     QgsProject.instance(), False
 | |
|                 )
 | |
|             elif self.parameterDefinition().layerType() in (
 | |
|                 QgsProcessing.SourceType.TypeVectorAnyGeometry,
 | |
|                 QgsProcessing.SourceType.TypeVector,
 | |
|             ):
 | |
|                 options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                     QgsProject.instance(), [], False
 | |
|                 )
 | |
|             elif (
 | |
|                 self.parameterDefinition().layerType()
 | |
|                 == QgsProcessing.SourceType.TypeMapLayer
 | |
|             ):
 | |
|                 options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                     QgsProject.instance(), [], False
 | |
|                 )
 | |
|                 options.extend(
 | |
|                     QgsProcessingUtils.compatibleRasterLayers(
 | |
|                         QgsProject.instance(), False
 | |
|                     )
 | |
|                 )
 | |
|                 options.extend(
 | |
|                     QgsProcessingUtils.compatibleMeshLayers(
 | |
|                         QgsProject.instance(), False
 | |
|                     )
 | |
|                 )
 | |
|             else:
 | |
|                 options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                     QgsProject.instance(),
 | |
|                     [self.parameterDefinition().layerType()],
 | |
|                     False,
 | |
|                 )
 | |
|             opts = [getExtendedLayerName(opt) for opt in options]
 | |
|             self.widget.updateForOptions(opts)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             pass  # TODO
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.setValue(value)
 | |
|         else:
 | |
|             options = self._getOptions()
 | |
| 
 | |
|             if not isinstance(value, (tuple, list)):
 | |
|                 value = [value]
 | |
| 
 | |
|             selected_options = []
 | |
|             for sel in value:
 | |
|                 if sel in options:
 | |
|                     selected_options.append(options.index(sel))
 | |
|                 elif isinstance(sel, QgsProcessingModelChildParameterSource):
 | |
|                     selected_options.append(sel.staticValue())
 | |
|                 else:
 | |
|                     selected_options.append(sel)
 | |
| 
 | |
|             self.widget.setSelectedItems(selected_options)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if (
 | |
|                 self.parameterDefinition().layerType()
 | |
|                 == QgsProcessing.SourceType.TypeFile
 | |
|             ):
 | |
|                 return self.widget.selectedoptions
 | |
|             else:
 | |
|                 if (
 | |
|                     self.parameterDefinition().layerType()
 | |
|                     == QgsProcessing.SourceType.TypeRaster
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleRasterLayers(
 | |
|                         QgsProject.instance(), False
 | |
|                     )
 | |
|                 elif (
 | |
|                     self.parameterDefinition().layerType()
 | |
|                     == QgsProcessing.SourceType.TypeMesh
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleMeshLayers(
 | |
|                         QgsProject.instance(), False
 | |
|                     )
 | |
|                 elif self.parameterDefinition().layerType() in (
 | |
|                     QgsProcessing.SourceType.TypeVectorAnyGeometry,
 | |
|                     QgsProcessing.SourceType.TypeVector,
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                         QgsProject.instance(), [], False
 | |
|                     )
 | |
|                 elif (
 | |
|                     self.parameterDefinition().layerType()
 | |
|                     == QgsProcessing.SourceType.TypeMapLayer
 | |
|                 ):
 | |
|                     options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                         QgsProject.instance(), [], False
 | |
|                     )
 | |
|                     options.extend(
 | |
|                         QgsProcessingUtils.compatibleRasterLayers(
 | |
|                             QgsProject.instance(), False
 | |
|                         )
 | |
|                     )
 | |
|                     options.extend(
 | |
|                         QgsProcessingUtils.compatibleMeshLayers(
 | |
|                             QgsProject.instance(), False
 | |
|                         )
 | |
|                     )
 | |
|                 else:
 | |
|                     options = QgsProcessingUtils.compatibleVectorLayers(
 | |
|                         QgsProject.instance(),
 | |
|                         [self.parameterDefinition().layerType()],
 | |
|                         False,
 | |
|                     )
 | |
|                 return [
 | |
|                     options[i] if isinstance(i, int) else i
 | |
|                     for i in self.widget.selectedoptions
 | |
|                 ]
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
|             options = self._getOptions()
 | |
|             values = [
 | |
|                 (
 | |
|                     options[i]
 | |
|                     if isinstance(i, int)
 | |
|                     else QgsProcessingModelChildParameterSource.fromStaticValue(i)
 | |
|                 )
 | |
|                 for i in self.widget.selectedoptions
 | |
|             ]
 | |
|             if (
 | |
|                 len(values) == 0
 | |
|                 and not self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 raise InvalidParameterValue()
 | |
|             return values
 | |
| 
 | |
| 
 | |
| class NumberWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "NumberWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             widget = NumberInputPanel(self.parameterDefinition())
 | |
|             widget.hasChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             return ModelerNumberInputPanel(self.parameterDefinition(), self.dialog)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         self.widget.setValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         return self.widget.getValue()
 | |
| 
 | |
|     def postInitialize(self, wrappers):
 | |
|         if (
 | |
|             self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH)
 | |
|             and self.parameterDefinition().isDynamic()
 | |
|         ):
 | |
|             for wrapper in wrappers:
 | |
|                 if (
 | |
|                     wrapper.parameterDefinition().name()
 | |
|                     == self.parameterDefinition().dynamicLayerParameterName()
 | |
|                 ):
 | |
|                     self.widget.setDynamicLayer(wrapper.parameterValue())
 | |
|                     wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
 | |
|                     break
 | |
| 
 | |
|     def parentLayerChanged(self, wrapper):
 | |
|         self.widget.setDynamicLayer(wrapper.parameterValue())
 | |
| 
 | |
| 
 | |
| class DistanceWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "DistanceWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             widget = DistanceInputPanel(self.parameterDefinition())
 | |
|             widget.hasChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             return ModelerNumberInputPanel(self.parameterDefinition(), self.dialog)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         self.widget.setValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         return self.widget.getValue()
 | |
| 
 | |
|     def postInitialize(self, wrappers):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             for wrapper in wrappers:
 | |
|                 if (
 | |
|                     wrapper.parameterDefinition().name()
 | |
|                     == self.parameterDefinition().dynamicLayerParameterName()
 | |
|                 ):
 | |
|                     self.widget.setDynamicLayer(wrapper.parameterValue())
 | |
|                     wrapper.widgetValueHasChanged.connect(self.dynamicLayerChanged)
 | |
|                 if (
 | |
|                     wrapper.parameterDefinition().name()
 | |
|                     == self.parameterDefinition().parentParameterName()
 | |
|                 ):
 | |
|                     self.widget.setUnitParameterValue(wrapper.parameterValue())
 | |
|                     wrapper.widgetValueHasChanged.connect(self.parentParameterChanged)
 | |
| 
 | |
|     def dynamicLayerChanged(self, wrapper):
 | |
|         self.widget.setDynamicLayer(wrapper.parameterValue())
 | |
| 
 | |
|     def parentParameterChanged(self, wrapper):
 | |
|         self.widget.setUnitParameterValue(wrapper.parameterValue())
 | |
| 
 | |
| 
 | |
| class RangeWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "RangeWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         widget = RangePanel(self.parameterDefinition())
 | |
|         widget.hasChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|         return widget
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         self.widget.setValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         return self.widget.getValue()
 | |
| 
 | |
| 
 | |
| class MapLayerWidgetWrapper(WidgetWrapper):
 | |
|     NOT_SELECTED = "[Not selected]"
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.14
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "MapLayerWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             self.combo = QgsProcessingMapLayerComboBox(self.parameterDefinition())
 | |
|             self.context = dataobjects.createContext()
 | |
| 
 | |
|             try:
 | |
|                 if (
 | |
|                     self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 ):
 | |
|                     self.combo.setValue(
 | |
|                         self.parameterDefinition().defaultValue(), self.context
 | |
|                     )
 | |
|                 else:
 | |
|                     if self.parameterDefinition().defaultValue():
 | |
|                         self.combo.setValue(
 | |
|                             self.parameterDefinition().defaultValue(), self.context
 | |
|                         )
 | |
|                     else:
 | |
|                         self.combo.setLayer(iface.activeLayer())
 | |
|             except:
 | |
|                 pass
 | |
| 
 | |
|             self.combo.valueChanged.connect(
 | |
|                 lambda: self.widgetValueHasChanged.emit(self)
 | |
|             )
 | |
|             return self.combo
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             widget = BatchInputSelectionPanel(
 | |
|                 self.parameterDefinition(), self.row, self.col, self.dialog
 | |
|             )
 | |
|             widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             self.combo = QComboBox()
 | |
|             layers = self.getAvailableLayers()
 | |
|             self.combo.setEditable(True)
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 self.combo.addItem(self.NOT_SELECTED, self.NOT_SET_OPTION)
 | |
|             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(6)
 | |
|             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
 | |
| 
 | |
|     def getAvailableLayers(self):
 | |
|         return self.dialog.getAvailableValuesOfType(
 | |
|             [
 | |
|                 QgsProcessingParameterRasterLayer,
 | |
|                 QgsProcessingParameterMeshLayer,
 | |
|                 QgsProcessingParameterVectorLayer,
 | |
|                 QgsProcessingParameterMapLayer,
 | |
|                 QgsProcessingParameterString,
 | |
|             ],
 | |
|             [
 | |
|                 QgsProcessingOutputRasterLayer,
 | |
|                 QgsProcessingOutputVectorLayer,
 | |
|                 QgsProcessingOutputMapLayer,
 | |
|                 QgsProcessingOutputString,
 | |
|                 QgsProcessingOutputFile,
 | |
|             ],
 | |
|         )
 | |
| 
 | |
|     def selectFile(self):
 | |
|         filename, selected_filter = self.getFileName(self.combo.currentText())
 | |
|         if filename:
 | |
|             if isinstance(self.combo, QgsProcessingMapLayerComboBox):
 | |
|                 self.combo.setValue(filename, self.context)
 | |
|             elif isinstance(self.combo, QgsMapLayerComboBox):
 | |
|                 items = self.combo.additionalItems()
 | |
|                 items.append(filename)
 | |
|                 self.combo.setAdditionalItems(items)
 | |
|                 self.combo.setCurrentIndex(self.combo.findText(filename))
 | |
|             else:
 | |
|                 self.combo.setEditText(filename)
 | |
|             self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if isinstance(value, str):
 | |
|                 layer = QgsProject.instance().mapLayer(value)
 | |
|                 if layer is not None:
 | |
|                     value = layer
 | |
|             self.combo.setValue(value, self.context)
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             self.widget.setValue(value)
 | |
|         else:
 | |
|             self.setComboValue(value, combobox=self.combo)
 | |
|         self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             return self.combo.value()
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
| 
 | |
|             def validator(v):
 | |
|                 if not bool(v):
 | |
|                     return (
 | |
|                         self.parameterDefinition().flags()
 | |
|                         & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                     )
 | |
|                 else:
 | |
|                     return os.path.exists(v)
 | |
| 
 | |
|             return self.comboValue(validator, combobox=self.combo)
 | |
| 
 | |
| 
 | |
| class RasterWidgetWrapper(MapLayerWidgetWrapper):
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.14
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "RasterWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
| 
 | |
|     def getAvailableLayers(self):
 | |
|         return self.dialog.getAvailableValuesOfType(
 | |
|             (QgsProcessingParameterRasterLayer, QgsProcessingParameterString),
 | |
|             (
 | |
|                 QgsProcessingOutputRasterLayer,
 | |
|                 QgsProcessingOutputFile,
 | |
|                 QgsProcessingOutputString,
 | |
|             ),
 | |
|         )
 | |
| 
 | |
|     def selectFile(self):
 | |
|         filename, selected_filter = self.getFileName(self.combo.currentText())
 | |
|         if filename:
 | |
|             filename = dataobjects.getRasterSublayer(
 | |
|                 filename, self.parameterDefinition()
 | |
|             )
 | |
|             if isinstance(self.combo, QgsProcessingMapLayerComboBox):
 | |
|                 self.combo.setValue(filename, self.context)
 | |
|             elif isinstance(self.combo, QgsMapLayerComboBox):
 | |
|                 items = self.combo.additionalItems()
 | |
|                 items.append(filename)
 | |
|                 self.combo.setAdditionalItems(items)
 | |
|                 self.combo.setCurrentIndex(self.combo.findText(filename))
 | |
|             else:
 | |
|                 self.combo.setEditText(filename)
 | |
|             self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
| 
 | |
| class MeshWidgetWrapper(MapLayerWidgetWrapper):
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.14
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "MeshWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
| 
 | |
|     def getAvailableLayers(self):
 | |
|         return self.dialog.getAvailableValuesOfType(
 | |
|             (QgsProcessingParameterMeshLayer, QgsProcessingParameterString), ()
 | |
|         )
 | |
| 
 | |
|     def selectFile(self):
 | |
|         filename, selected_filter = self.getFileName(self.combo.currentText())
 | |
|         if filename:
 | |
|             if isinstance(self.combo, QgsProcessingMapLayerComboBox):
 | |
|                 self.combo.setValue(filename, self.context)
 | |
|             elif isinstance(self.combo, QgsMapLayerComboBox):
 | |
|                 items = self.combo.additionalItems()
 | |
|                 items.append(filename)
 | |
|                 self.combo.setAdditionalItems(items)
 | |
|                 self.combo.setCurrentIndex(self.combo.findText(filename))
 | |
|             else:
 | |
|                 self.combo.setEditText(filename)
 | |
|             self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
| 
 | |
| class EnumWidgetWrapper(WidgetWrapper):
 | |
|     NOT_SELECTED = "[Not selected]"
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "EnumWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self, useCheckBoxes=False, columns=1):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             self._useCheckBoxes = useCheckBoxes
 | |
|             if self._useCheckBoxes and not self.dialogType == DIALOG_BATCH:
 | |
|                 return CheckboxesPanel(
 | |
|                     options=self.parameterDefinition().options(),
 | |
|                     multiple=self.parameterDefinition().allowMultiple(),
 | |
|                     columns=columns,
 | |
|                 )
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 return MultipleInputPanel(options=self.parameterDefinition().options())
 | |
|             else:
 | |
|                 widget = QComboBox()
 | |
|                 for i, option in enumerate(self.parameterDefinition().options()):
 | |
|                     widget.addItem(option, i)
 | |
|                 if self.parameterDefinition().defaultValue():
 | |
|                     widget.setCurrentIndex(
 | |
|                         widget.findData(self.parameterDefinition().defaultValue())
 | |
|                     )
 | |
|                 return widget
 | |
|         else:
 | |
|             self.combobox = QComboBox()
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 self.combobox.addItem(self.NOT_SELECTED, self.NOT_SET_OPTION)
 | |
|             for i, option in enumerate(self.parameterDefinition().options()):
 | |
|                 self.combobox.addItem(option, i)
 | |
|             values = self.dialog.getAvailableValuesOfType(QgsProcessingParameterEnum)
 | |
|             for v in values:
 | |
|                 self.combobox.addItem(self.dialog.resolveValueDescription(v), v)
 | |
|             return self.combobox
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self._useCheckBoxes and not self.dialogType == DIALOG_BATCH:
 | |
|                 self.widget.setValue(value)
 | |
|                 return
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 self.widget.setSelectedItems(value)
 | |
|             else:
 | |
|                 self.widget.setCurrentIndex(self.widget.findData(value))
 | |
|         else:
 | |
|             self.setComboValue(value, combobox=self.combobox)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self._useCheckBoxes and not self.dialogType == DIALOG_BATCH:
 | |
|                 return self.widget.value()
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 return self.widget.selectedoptions
 | |
|             else:
 | |
|                 return self.widget.currentData()
 | |
|         else:
 | |
|             return self.comboValue(combobox=self.combobox)
 | |
| 
 | |
| 
 | |
| class FeatureSourceWidgetWrapper(WidgetWrapper):
 | |
|     NOT_SELECTED = "[Not selected]"
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "FeatureSourceWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
|         self.map_layer_combo = None
 | |
|         super().__init__(*args, **kwargs)
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             self.map_layer_combo = QgsProcessingMapLayerComboBox(
 | |
|                 self.parameterDefinition()
 | |
|             )
 | |
|             self.context = dataobjects.createContext()
 | |
| 
 | |
|             try:
 | |
|                 if iface.activeLayer().type() == QgsMapLayerType.VectorLayer:
 | |
|                     self.map_layer_combo.setLayer(iface.activeLayer())
 | |
|             except:
 | |
|                 pass
 | |
| 
 | |
|             self.map_layer_combo.valueChanged.connect(
 | |
|                 lambda: self.widgetValueHasChanged.emit(self)
 | |
|             )
 | |
| 
 | |
|             return self.map_layer_combo
 | |
| 
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             widget = BatchInputSelectionPanel(
 | |
|                 self.parameterDefinition(), self.row, self.col, self.dialog
 | |
|             )
 | |
|             widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             self.combo = QComboBox()
 | |
|             layers = self.dialog.getAvailableValuesOfType(
 | |
|                 (
 | |
|                     QgsProcessingParameterFeatureSource,
 | |
|                     QgsProcessingParameterVectorLayer,
 | |
|                 ),
 | |
|                 (
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputString,
 | |
|                     QgsProcessingOutputFile,
 | |
|                 ),
 | |
|                 self.parameterDefinition().dataTypes(),
 | |
|             )
 | |
|             self.combo.setEditable(True)
 | |
|             for layer in layers:
 | |
|                 self.combo.addItem(self.dialog.resolveValueDescription(layer), layer)
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 self.combo.setEditText("")
 | |
| 
 | |
|             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
 | |
| 
 | |
|     def setWidgetContext(self, context):
 | |
|         if self.map_layer_combo:
 | |
|             self.map_layer_combo.setWidgetContext(context)
 | |
|         super().setWidgetContext(context)
 | |
| 
 | |
|     def selectFile(self):
 | |
|         filename, selected_filter = self.getFileName(self.combo.currentText())
 | |
|         if filename:
 | |
|             if isinstance(self.combo, QgsProcessingMapLayerComboBox):
 | |
|                 self.combo.setValue(filename, self.context)
 | |
|             elif isinstance(self.combo, QgsMapLayerComboBox):
 | |
|                 items = self.combo.additionalItems()
 | |
|                 items.append(filename)
 | |
|                 self.combo.setAdditionalItems(items)
 | |
|                 self.combo.setCurrentIndex(self.combo.findText(filename))
 | |
|             else:
 | |
|                 self.combo.setEditText(filename)
 | |
|             self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if isinstance(value, str):
 | |
|                 layer = QgsProject.instance().mapLayer(value)
 | |
|                 if layer is not None:
 | |
|                     value = layer
 | |
|             self.map_layer_combo.setValue(value, self.context)
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             self.widget.setValue(value)
 | |
|         else:
 | |
|             self.setComboValue(value, combobox=self.combo)
 | |
|         self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             return self.map_layer_combo.value()
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
| 
 | |
|             def validator(v):
 | |
|                 if not bool(v):
 | |
|                     return (
 | |
|                         self.parameterDefinition().flags()
 | |
|                         & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                     )
 | |
|                 else:
 | |
|                     return os.path.exists(v)
 | |
| 
 | |
|             if self.combo.currentText():
 | |
|                 return self.comboValue(validator, combobox=self.combo)
 | |
|             else:
 | |
|                 return None
 | |
| 
 | |
| 
 | |
| class StringWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         super().__init__(*args, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "StringWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if self.parameterDefinition().multiLine():
 | |
|                 widget = QPlainTextEdit()
 | |
|             else:
 | |
|                 self._lineedit = QLineEdit()
 | |
|                 widget = self._lineedit
 | |
| 
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             widget = QLineEdit()
 | |
| 
 | |
|         else:
 | |
|             # strings, numbers, files and table fields are all allowed input types
 | |
|             strings = self.dialog.getAvailableValuesOfType(
 | |
|                 [
 | |
|                     QgsProcessingParameterString,
 | |
|                     QgsProcessingParameterNumber,
 | |
|                     QgsProcessingParameterDistance,
 | |
|                     QgsProcessingParameterFile,
 | |
|                     QgsProcessingParameterField,
 | |
|                     QgsProcessingParameterExpression,
 | |
|                 ],
 | |
|                 [QgsProcessingOutputString, QgsProcessingOutputFile],
 | |
|             )
 | |
|             options = [(self.dialog.resolveValueDescription(s), s) for s in strings]
 | |
|             if self.parameterDefinition().multiLine():
 | |
|                 widget = MultilineTextPanel(options)
 | |
|             else:
 | |
|                 widget = QComboBox()
 | |
|                 widget.setEditable(True)
 | |
|                 for desc, val in options:
 | |
|                     widget.addItem(desc, val)
 | |
|         return widget
 | |
| 
 | |
|     def showExpressionsBuilder(self):
 | |
|         context = dataobjects.createExpressionContext()
 | |
|         value = self.value()
 | |
|         if not isinstance(value, str):
 | |
|             value = ""
 | |
|         dlg = QgsExpressionBuilderDialog(None, value, self.widget, "generic", context)
 | |
|         dlg.setWindowTitle(self.tr("Expression based input"))
 | |
|         if dlg.exec() == QDialog.DialogCode.Accepted:
 | |
|             exp = QgsExpression(dlg.expressionText())
 | |
|             if not exp.hasParserError():
 | |
|                 if self.dialogType == DIALOG_STANDARD:
 | |
|                     self.setValue(str(exp.evaluate(context)))
 | |
|                 else:
 | |
|                     self.setValue(dlg.expressionText())
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if self.parameterDefinition().multiLine():
 | |
|                 self.widget.setPlainText(value)
 | |
|             else:
 | |
|                 self._lineedit.setText(value)
 | |
| 
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             self.widget.setText(value)
 | |
| 
 | |
|         else:
 | |
|             if self.parameterDefinition().multiLine():
 | |
|                 self.widget.setValue(value)
 | |
|             else:
 | |
|                 self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if self.parameterDefinition().multiLine():
 | |
|                 text = self.widget.toPlainText()
 | |
|             else:
 | |
|                 text = self._lineedit.text()
 | |
|             return text
 | |
| 
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.text()
 | |
| 
 | |
|         else:
 | |
|             if self.parameterDefinition().multiLine():
 | |
|                 value = self.widget.getValue()
 | |
|                 option = self.widget.getOption()
 | |
|                 if option == MultilineTextPanel.USE_TEXT:
 | |
|                     if value == "":
 | |
|                         if (
 | |
|                             self.parameterDefinition().flags()
 | |
|                             & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                         ):
 | |
|                             return None
 | |
|                         else:
 | |
|                             raise InvalidParameterValue()
 | |
|                     else:
 | |
|                         return value
 | |
|                 else:
 | |
|                     return value
 | |
|             else:
 | |
| 
 | |
|                 def validator(v):
 | |
|                     return (
 | |
|                         bool(v)
 | |
|                         or self.parameterDefinition().flags()
 | |
|                         & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                     )
 | |
| 
 | |
|                 return self.comboValue(validator)
 | |
| 
 | |
| 
 | |
| class ExpressionWidgetWrapper(WidgetWrapper):
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.4
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "StringWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
|         self.context = dataobjects.createContext()
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().parentLayerParameterName():
 | |
|                 widget = QgsFieldExpressionWidget()
 | |
|             else:
 | |
|                 widget = QgsExpressionLineEdit()
 | |
|             if self.parameterDefinition().defaultValue():
 | |
|                 widget.setExpression(self.parameterDefinition().defaultValue())
 | |
|         else:
 | |
|             strings = self.dialog.getAvailableValuesOfType(
 | |
|                 [
 | |
|                     QgsProcessingParameterExpression,
 | |
|                     QgsProcessingParameterString,
 | |
|                     QgsProcessingParameterNumber,
 | |
|                     QgsProcessingParameterDistance,
 | |
|                 ],
 | |
|                 (QgsProcessingOutputString, QgsProcessingOutputNumber),
 | |
|             )
 | |
|             options = [(self.dialog.resolveValueDescription(s), s) for s in strings]
 | |
|             widget = QComboBox()
 | |
|             widget.setEditable(True)
 | |
|             for desc, val in options:
 | |
|                 widget.addItem(desc, val)
 | |
|             widget.setEditText(self.parameterDefinition().defaultValue() or "")
 | |
|         return widget
 | |
| 
 | |
|     def postInitialize(self, wrappers):
 | |
|         for wrapper in wrappers:
 | |
|             if (
 | |
|                 wrapper.parameterDefinition().name()
 | |
|                 == self.parameterDefinition().parentLayerParameterName()
 | |
|             ):
 | |
|                 if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|                     self.setLayer(wrapper.parameterValue())
 | |
|                     wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
 | |
|                 break
 | |
| 
 | |
|     def parentLayerChanged(self, wrapper):
 | |
|         self.setLayer(wrapper.parameterValue())
 | |
| 
 | |
|     def setLayer(self, layer):
 | |
|         if isinstance(layer, QgsProcessingFeatureSourceDefinition):
 | |
|             layer, ok = layer.source.valueAsString(self.context.expressionContext())
 | |
|         if isinstance(layer, str):
 | |
|             layer = QgsProcessingUtils.mapLayerFromString(layer, self.context)
 | |
|         self.widget.setLayer(layer)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             self.widget.setExpression(value)
 | |
|         else:
 | |
|             self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             try:
 | |
|                 return self.widget.asExpression()
 | |
|             except:
 | |
|                 return self.widget.expression()
 | |
|         else:
 | |
| 
 | |
|             def validator(v):
 | |
|                 return (
 | |
|                     bool(v)
 | |
|                     or self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 )
 | |
| 
 | |
|             return self.comboValue(validator)
 | |
| 
 | |
| 
 | |
| class VectorLayerWidgetWrapper(WidgetWrapper):
 | |
|     NOT_SELECTED = "[Not selected]"
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.14
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "VectorLayerWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
| 
 | |
|     def createWidget(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             self.combo = QgsProcessingMapLayerComboBox(self.parameterDefinition())
 | |
|             self.context = dataobjects.createContext()
 | |
| 
 | |
|             try:
 | |
|                 if iface.activeLayer().type() == QgsMapLayerType.VectorLayer:
 | |
|                     self.combo.setLayer(iface.activeLayer())
 | |
|             except:
 | |
|                 pass
 | |
| 
 | |
|             self.combo.valueChanged.connect(
 | |
|                 lambda: self.widgetValueHasChanged.emit(self)
 | |
|             )
 | |
|             return self.combo
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             widget = BatchInputSelectionPanel(
 | |
|                 self.parameterDefinition(), self.row, self.col, self.dialog
 | |
|             )
 | |
|             widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             self.combo = QComboBox()
 | |
|             self.combo.setEditable(True)
 | |
|             tables = self.dialog.getAvailableValuesOfType(
 | |
|                 (QgsProcessingParameterVectorLayer, QgsProcessingParameterString),
 | |
|                 (
 | |
|                     QgsProcessingOutputVectorLayer,
 | |
|                     QgsProcessingOutputMapLayer,
 | |
|                     QgsProcessingOutputFile,
 | |
|                     QgsProcessingOutputString,
 | |
|                 ),
 | |
|             )
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 self.combo.addItem(self.NOT_SELECTED, self.NOT_SET_OPTION)
 | |
|             for table in tables:
 | |
|                 self.combo.addItem(self.dialog.resolveValueDescription(table), table)
 | |
| 
 | |
|             widget = QWidget()
 | |
|             layout = QHBoxLayout()
 | |
|             layout.setMargin(0)
 | |
|             layout.setContentsMargins(0, 0, 0, 0)
 | |
|             layout.setSpacing(6)
 | |
|             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
 | |
| 
 | |
|     def selectFile(self):
 | |
|         filename, selected_filter = self.getFileName(self.combo.currentText())
 | |
|         if filename:
 | |
|             filename = dataobjects.getRasterSublayer(
 | |
|                 filename, self.parameterDefinition()
 | |
|             )
 | |
|             if isinstance(self.combo, QgsProcessingMapLayerComboBox):
 | |
|                 self.combo.setValue(filename, self.context)
 | |
|             elif isinstance(self.combo, QgsMapLayerComboBox):
 | |
|                 items = self.combo.additionalItems()
 | |
|                 items.append(filename)
 | |
|                 self.combo.setAdditionalItems(items)
 | |
|                 self.combo.setCurrentIndex(self.combo.findText(filename))
 | |
|             else:
 | |
|                 self.combo.setEditText(filename)
 | |
|             self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             if isinstance(value, str):
 | |
|                 layer = QgsProject.instance().mapLayer(value)
 | |
|                 if layer is not None:
 | |
|                     value = layer
 | |
|             self.combo.setValue(value, self.context)
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.setValue(value)
 | |
|         else:
 | |
|             self.setComboValue(value, combobox=self.combo)
 | |
|         self.widgetValueHasChanged.emit(self)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType == DIALOG_STANDARD:
 | |
|             return self.combo.value()
 | |
|         elif self.dialogType == DIALOG_BATCH:
 | |
|             return self.widget.getValue()
 | |
|         else:
 | |
| 
 | |
|             def validator(v):
 | |
|                 return (
 | |
|                     bool(v)
 | |
|                     or self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 )
 | |
| 
 | |
|             return self.comboValue(validator, combobox=self.combo)
 | |
| 
 | |
| 
 | |
| class TableFieldWidgetWrapper(WidgetWrapper):
 | |
|     NOT_SET = "[Not set]"
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
|         """
 | |
|         .. deprecated:: 3.12
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "TableFieldWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         self.context = dataobjects.createContext()
 | |
| 
 | |
|     def createWidget(self):
 | |
|         self._layer = None
 | |
|         self.parent_file_based_layers = {}
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 return MultipleInputPanel(options=[])
 | |
|             else:
 | |
|                 widget = QgsFieldComboBox()
 | |
|                 widget.setAllowEmptyFieldName(
 | |
|                     self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 )
 | |
|                 widget.fieldChanged.connect(
 | |
|                     lambda: self.widgetValueHasChanged.emit(self)
 | |
|                 )
 | |
|                 if (
 | |
|                     self.parameterDefinition().dataType()
 | |
|                     == QgsProcessingParameterField.DataType.Numeric
 | |
|                 ):
 | |
|                     widget.setFilters(QgsFieldProxyModel.Filter.Numeric)
 | |
|                 elif (
 | |
|                     self.parameterDefinition().dataType()
 | |
|                     == QgsProcessingParameterField.DataType.String
 | |
|                 ):
 | |
|                     widget.setFilters(QgsFieldProxyModel.Filter.String)
 | |
|                 elif (
 | |
|                     self.parameterDefinition().dataType()
 | |
|                     == QgsProcessingParameterField.DataType.DateTime
 | |
|                 ):
 | |
|                     widget.setFilters(
 | |
|                         QgsFieldProxyModel.Filter.Date | QgsFieldProxyModel.Filter.Time
 | |
|                     )
 | |
|                 return widget
 | |
|         else:
 | |
|             widget = QComboBox()
 | |
|             widget.setEditable(True)
 | |
|             fields = self.dialog.getAvailableValuesOfType(
 | |
|                 [QgsProcessingParameterField, QgsProcessingParameterString],
 | |
|                 [QgsProcessingOutputString],
 | |
|             )
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 widget.addItem(self.NOT_SET, self.NOT_SET_OPTION)
 | |
|             for f in fields:
 | |
|                 widget.addItem(self.dialog.resolveValueDescription(f), f)
 | |
|             widget.setToolTip(
 | |
|                 self.tr(
 | |
|                     "Input parameter, or name of field (separate field names with ; for multiple field parameters)"
 | |
|                 )
 | |
|             )
 | |
|             return widget
 | |
| 
 | |
|     def postInitialize(self, wrappers):
 | |
|         for wrapper in wrappers:
 | |
|             if (
 | |
|                 wrapper.parameterDefinition().name()
 | |
|                 == self.parameterDefinition().parentLayerParameterName()
 | |
|             ):
 | |
|                 if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|                     self.setLayer(wrapper.parameterValue())
 | |
|                     wrapper.widgetValueHasChanged.connect(self.parentValueChanged)
 | |
|                 break
 | |
| 
 | |
|     def parentValueChanged(self, wrapper):
 | |
|         value = wrapper.parameterValue()
 | |
|         if isinstance(value, str) and value in self.parent_file_based_layers:
 | |
|             self.setLayer(self.parent_file_based_layers[value])
 | |
|         else:
 | |
|             self.setLayer(value)
 | |
|             if isinstance(value, str):
 | |
|                 self.parent_file_based_layers[value] = self._layer
 | |
| 
 | |
|     def setLayer(self, layer):
 | |
|         if isinstance(layer, QgsProcessingFeatureSourceDefinition):
 | |
|             layer, ok = layer.source.valueAsString(self.context.expressionContext())
 | |
|         if isinstance(layer, str):
 | |
|             if not layer:  # empty string
 | |
|                 layer = None
 | |
|             else:
 | |
|                 layer = QgsProcessingUtils.mapLayerFromString(layer, self.context)
 | |
|                 if not isinstance(layer, QgsVectorLayer) or not layer.isValid():
 | |
|                     self.dialog.messageBar().clearWidgets()
 | |
|                     self.dialog.messageBar().pushMessage(
 | |
|                         "",
 | |
|                         self.tr(
 | |
|                             "Could not load selected layer/table. Dependent field could not be populated"
 | |
|                         ),
 | |
|                         level=Qgis.MessageLevel.Warning,
 | |
|                         duration=5,
 | |
|                     )
 | |
|                     return
 | |
| 
 | |
|         self._layer = layer
 | |
| 
 | |
|         self.refreshItems()
 | |
| 
 | |
|         if (
 | |
|             self.parameterDefinition().allowMultiple()
 | |
|             and self.parameterDefinition().defaultToAllFields()
 | |
|         ):
 | |
|             self.setValue(self.getFields())
 | |
| 
 | |
|     def refreshItems(self):
 | |
|         if self.parameterDefinition().allowMultiple():
 | |
|             self.widget.updateForOptions(self.getFields())
 | |
|         else:
 | |
|             self.widget.setLayer(self._layer)
 | |
|             self.widget.setCurrentIndex(0)
 | |
|         if self.parameterDefinition().defaultValue() is not None:
 | |
|             self.setValue(self.parameterDefinition().defaultValue())
 | |
| 
 | |
|     def getFields(self):
 | |
|         if self._layer is None:
 | |
|             return []
 | |
|         fieldTypes = []
 | |
|         if (
 | |
|             self.parameterDefinition().dataType()
 | |
|             == QgsProcessingParameterField.DataType.String
 | |
|         ):
 | |
|             fieldTypes = [QVariant.String]
 | |
|         elif (
 | |
|             self.parameterDefinition().dataType()
 | |
|             == QgsProcessingParameterField.DataType.Numeric
 | |
|         ):
 | |
|             fieldTypes = [
 | |
|                 QVariant.Int,
 | |
|                 QVariant.Double,
 | |
|                 QVariant.LongLong,
 | |
|                 QVariant.UInt,
 | |
|                 QVariant.ULongLong,
 | |
|             ]
 | |
|         elif (
 | |
|             self.parameterDefinition().dataType()
 | |
|             == QgsProcessingParameterField.DataType.DateTime
 | |
|         ):
 | |
|             fieldTypes = [QVariant.Date, QVariant.Time, QVariant.DateTime]
 | |
| 
 | |
|         fieldNames = []
 | |
|         for field in self._layer.fields():
 | |
|             if not fieldTypes or field.type() in fieldTypes:
 | |
|                 fieldNames.append(str(field.name()))
 | |
|         return fieldNames
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 options = self.widget.options
 | |
|                 selected = []
 | |
|                 if isinstance(value, str):
 | |
|                     value = value.split(";")
 | |
| 
 | |
|                 for v in value:
 | |
|                     for i, opt in enumerate(options):
 | |
|                         if opt == v:
 | |
|                             selected.append(i)
 | |
|                         # case insensitive check - only do if matching case value is not present
 | |
|                         elif v not in options and opt.lower() == v.lower():
 | |
|                             selected.append(i)
 | |
| 
 | |
|                 self.widget.setSelectedItems(selected)
 | |
|             else:
 | |
|                 self.widget.setField(value)
 | |
|         else:
 | |
|             self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 return [self.widget.options[i] for i in self.widget.selectedoptions]
 | |
|             else:
 | |
|                 f = self.widget.currentField()
 | |
|                 if (
 | |
|                     self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                     and not f
 | |
|                 ):
 | |
|                     return None
 | |
|                 return f
 | |
|         else:
 | |
| 
 | |
|             def validator(v):
 | |
|                 return (
 | |
|                     bool(v)
 | |
|                     or self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 )
 | |
| 
 | |
|             return self.comboValue(validator)
 | |
| 
 | |
| 
 | |
| class BandWidgetWrapper(WidgetWrapper):
 | |
|     NOT_SET = "[Not set]"
 | |
| 
 | |
|     def __init__(self, param, dialog, row=0, col=0, **kwargs):
 | |
|         """
 | |
|         .. deprecated:: 3.14
 | |
|         Do not use, will be removed in QGIS 4.0
 | |
|         """
 | |
| 
 | |
|         from warnings import warn
 | |
| 
 | |
|         warn(
 | |
|             "BandWidgetWrapper is deprecated and will be removed in QGIS 4.0",
 | |
|             DeprecationWarning,
 | |
|         )
 | |
| 
 | |
|         super().__init__(param, dialog, row, col, **kwargs)
 | |
|         self.context = dataobjects.createContext()
 | |
| 
 | |
|     def createWidget(self):
 | |
|         self._layer = None
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 return MultipleInputPanel(options=[])
 | |
|             widget = QgsRasterBandComboBox()
 | |
|             widget.setShowNotSetOption(
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             )
 | |
|             widget.bandChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
 | |
|             return widget
 | |
|         else:
 | |
|             widget = QComboBox()
 | |
|             widget.setEditable(True)
 | |
|             fields = self.dialog.getAvailableValuesOfType(
 | |
|                 [
 | |
|                     QgsProcessingParameterBand,
 | |
|                     QgsProcessingParameterDistance,
 | |
|                     QgsProcessingParameterNumber,
 | |
|                 ],
 | |
|                 [QgsProcessingOutputNumber],
 | |
|             )
 | |
|             if (
 | |
|                 self.parameterDefinition().flags()
 | |
|                 & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|             ):
 | |
|                 widget.addItem(self.NOT_SET, self.NOT_SET_OPTION)
 | |
|             for f in fields:
 | |
|                 widget.addItem(self.dialog.resolveValueDescription(f), f)
 | |
|             return widget
 | |
| 
 | |
|     def postInitialize(self, wrappers):
 | |
|         for wrapper in wrappers:
 | |
|             if (
 | |
|                 wrapper.parameterDefinition().name()
 | |
|                 == self.parameterDefinition().parentLayerParameterName()
 | |
|             ):
 | |
|                 if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|                     self.setLayer(wrapper.parameterValue())
 | |
|                     wrapper.widgetValueHasChanged.connect(self.parentValueChanged)
 | |
|                 break
 | |
| 
 | |
|     def parentValueChanged(self, wrapper):
 | |
|         self.setLayer(wrapper.parameterValue())
 | |
| 
 | |
|     def setLayer(self, layer):
 | |
|         if isinstance(layer, QgsProcessingParameterRasterLayer):
 | |
|             layer, ok = layer.source.valueAsString(self.context.expressionContext())
 | |
|         if isinstance(layer, str):
 | |
|             layer = QgsProcessingUtils.mapLayerFromString(layer, self.context)
 | |
|         self._layer = layer
 | |
|         self.refreshItems()
 | |
| 
 | |
|     def getBands(self):
 | |
|         bands = []
 | |
| 
 | |
|         if self._layer is not None:
 | |
|             provider = self._layer.dataProvider()
 | |
|             for band in range(1, provider.bandCount() + 1):
 | |
|                 name = provider.generateBandName(band)
 | |
|                 interpretation = provider.colorInterpretationName(band)
 | |
|                 if interpretation != "Undefined":
 | |
|                     name = name + f" ({interpretation})"
 | |
|                 bands.append(name)
 | |
|         return bands
 | |
| 
 | |
|     def refreshItems(self):
 | |
|         if self.param.allowMultiple():
 | |
|             self.widget.setSelectedItems([])
 | |
|             self.widget.updateForOptions(self.getBands())
 | |
|         else:
 | |
|             self.widget.setLayer(self._layer)
 | |
|             self.widget.setCurrentIndex(0)
 | |
| 
 | |
|     def setValue(self, value):
 | |
|         if value is None or value == NULL:
 | |
|             return
 | |
| 
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 options = self.widget.options
 | |
|                 selected = []
 | |
|                 if isinstance(value, str):
 | |
|                     value = value.split(";")
 | |
| 
 | |
|                 for v in value:
 | |
|                     for i, opt in enumerate(options):
 | |
|                         match = re.search(f"(?:\\A|[^0-9]){v}(?:\\Z|[^0-9]|)", opt)
 | |
|                         if match:
 | |
|                             selected.append(i)
 | |
| 
 | |
|                 self.widget.setSelectedItems(selected)
 | |
|             else:
 | |
|                 self.widget.setBand(value)
 | |
|         else:
 | |
|             self.setComboValue(value)
 | |
| 
 | |
|     def value(self):
 | |
|         if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
 | |
|             if self.parameterDefinition().allowMultiple():
 | |
|                 bands = []
 | |
|                 for i in self.widget.selectedoptions:
 | |
|                     match = re.search(
 | |
|                         "(?:\\A|[^0-9])([0-9]+)(?:\\Z|[^0-9]|)", self.widget.options[i]
 | |
|                     )
 | |
|                     if match:
 | |
|                         bands.append(match.group(1))
 | |
|                 return bands
 | |
|             else:
 | |
|                 f = self.widget.currentBand()
 | |
|                 if (
 | |
|                     self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                     and not f
 | |
|                 ):
 | |
|                     return None
 | |
|             return f
 | |
|         else:
 | |
| 
 | |
|             def validator(v):
 | |
|                 return (
 | |
|                     bool(v)
 | |
|                     or self.parameterDefinition().flags()
 | |
|                     & QgsProcessingParameterDefinition.Flag.FlagOptional
 | |
|                 )
 | |
| 
 | |
|             return self.comboValue(validator)
 | |
| 
 | |
| 
 | |
| class WidgetWrapperFactory:
 | |
|     """
 | |
|     Factory for parameter widget wrappers
 | |
|     """
 | |
| 
 | |
|     @staticmethod
 | |
|     def create_wrapper(param, dialog, row=0, col=0):
 | |
|         wrapper_metadata = param.metadata().get("widget_wrapper", None)
 | |
|         # VERY messy logic here to avoid breaking 3.0 API which allowed metadata "widget_wrapper" value to be either
 | |
|         # a string name of a class OR a dict.
 | |
|         # TODO QGIS 4.0 -- require widget_wrapper to be a dict.
 | |
|         if wrapper_metadata and (
 | |
|             not isinstance(wrapper_metadata, dict)
 | |
|             or wrapper_metadata.get("class", None) is not None
 | |
|         ):
 | |
|             return WidgetWrapperFactory.create_wrapper_from_metadata(
 | |
|                 param, dialog, row, col
 | |
|             )
 | |
|         else:
 | |
|             # try from c++ registry first
 | |
|             class_type = dialog.__class__.__name__
 | |
|             if class_type == "ModelerParametersDialog":
 | |
|                 wrapper = QgsGui.processingGuiRegistry().createModelerParameterWidget(
 | |
|                     dialog.model, dialog.childId, param, dialog.context
 | |
|                 )
 | |
|             else:
 | |
|                 dialog_type = dialogTypes.get(
 | |
|                     class_type, QgsProcessingGui.WidgetType.Standard
 | |
|                 )
 | |
|                 wrapper = QgsGui.processingGuiRegistry().createParameterWidgetWrapper(
 | |
|                     param, dialog_type
 | |
|                 )
 | |
|             if wrapper is not None:
 | |
|                 wrapper.setDialog(dialog)
 | |
|                 return wrapper
 | |
| 
 | |
|             # fallback to Python registry
 | |
|             return WidgetWrapperFactory.create_wrapper_from_class(
 | |
|                 param, dialog, row, col
 | |
|             )
 | |
| 
 | |
|     @staticmethod
 | |
|     def create_wrapper_from_metadata(param, dialog, row=0, col=0):
 | |
|         wrapper = param.metadata().get("widget_wrapper", None)
 | |
|         params = {}
 | |
|         # wrapper metadata should be a dict with class key
 | |
|         if isinstance(wrapper, dict):
 | |
|             params = deepcopy(wrapper)
 | |
|             wrapper = params.pop("class")
 | |
|         # wrapper metadata should be a class path
 | |
|         if isinstance(wrapper, str):
 | |
|             tokens = wrapper.split(".")
 | |
|             mod = __import__(".".join(tokens[:-1]), fromlist=[tokens[-1]])
 | |
|             wrapper = getattr(mod, tokens[-1])
 | |
|         # or directly a class object
 | |
|         if isclass(wrapper):
 | |
|             wrapper = wrapper(param, dialog, row, col, **params)
 | |
|         # or a wrapper instance
 | |
|         return wrapper
 | |
| 
 | |
|     @staticmethod
 | |
|     def create_wrapper_from_class(param, dialog, row=0, col=0):
 | |
|         wrapper = None
 | |
|         if param.type() == "boolean":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = BooleanWidgetWrapper
 | |
|         elif param.type() == "crs":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = CrsWidgetWrapper
 | |
|         elif param.type() == "extent":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = ExtentWidgetWrapper
 | |
|         elif param.type() == "point":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = PointWidgetWrapper
 | |
|         elif param.type() == "file":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = FileWidgetWrapper
 | |
|         elif param.type() == "multilayer":
 | |
|             wrapper = MultipleLayerWidgetWrapper
 | |
|         elif param.type() == "number":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = NumberWidgetWrapper
 | |
|         elif param.type() == "distance":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = DistanceWidgetWrapper
 | |
|         elif param.type() == "raster":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = RasterWidgetWrapper
 | |
|         elif param.type() == "enum":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = EnumWidgetWrapper
 | |
|         elif param.type() == "string":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = StringWidgetWrapper
 | |
|         elif param.type() == "expression":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = ExpressionWidgetWrapper
 | |
|         elif param.type() == "vector":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = VectorLayerWidgetWrapper
 | |
|         elif param.type() == "field":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = TableFieldWidgetWrapper
 | |
|         elif param.type() == "source":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = FeatureSourceWidgetWrapper
 | |
|         elif param.type() == "band":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = BandWidgetWrapper
 | |
|         elif param.type() == "layer":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = MapLayerWidgetWrapper
 | |
|         elif param.type() == "range":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = RangeWidgetWrapper
 | |
|         elif param.type() == "matrix":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = FixedTableWidgetWrapper
 | |
|         elif param.type() == "mesh":
 | |
|             # deprecated, moved to c++
 | |
|             wrapper = MeshWidgetWrapper
 | |
|         else:
 | |
|             assert False, param.type()
 | |
|         return wrapper(param, dialog, row, col)
 |