mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
278 lines
12 KiB
Python
278 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
***************************************************************************
|
|
ParametersPanel.py
|
|
---------------------
|
|
Date : August 2012
|
|
Copyright : (C) 2012 by Victor Olaya
|
|
(C) 2013 by CS Systemes d'information (CS SI)
|
|
Email : volayaf at gmail dot com
|
|
otb at c-s dot fr (CS SI)
|
|
Contributors : Victor Olaya
|
|
|
|
***************************************************************************
|
|
* *
|
|
* 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__ = 'Victor Olaya'
|
|
__date__ = 'August 2012'
|
|
__copyright__ = '(C) 2012, Victor Olaya'
|
|
|
|
from qgis.core import (QgsProcessingParameterDefinition,
|
|
QgsProcessingParameterExtent,
|
|
QgsProject,
|
|
QgsProcessingModelAlgorithm,
|
|
QgsProcessingOutputLayerDefinition)
|
|
from qgis.gui import (QgsProcessingContextGenerator,
|
|
QgsProcessingParameterWidgetContext,
|
|
QgsProcessingParametersWidget,
|
|
QgsGui,
|
|
QgsProcessingGui,
|
|
QgsProcessingParametersGenerator,
|
|
QgsProcessingHiddenWidgetWrapper)
|
|
from qgis.utils import iface
|
|
|
|
from processing.gui.wrappers import WidgetWrapperFactory, WidgetWrapper
|
|
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
|
|
from processing.tools.dataobjects import createContext
|
|
|
|
|
|
class ParametersPanel(QgsProcessingParametersWidget):
|
|
|
|
def __init__(self, parent, alg, in_place=False, active_layer=None):
|
|
super().__init__(alg, parent)
|
|
self.in_place = in_place
|
|
self.active_layer = active_layer
|
|
|
|
self.wrappers = {}
|
|
|
|
self.extra_parameters = {}
|
|
|
|
self.processing_context = createContext()
|
|
|
|
class ContextGenerator(QgsProcessingContextGenerator):
|
|
|
|
def __init__(self, context):
|
|
super().__init__()
|
|
self.processing_context = context
|
|
|
|
def processingContext(self):
|
|
return self.processing_context
|
|
|
|
self.context_generator = ContextGenerator(self.processing_context)
|
|
|
|
self.initWidgets()
|
|
|
|
QgsProject.instance().layerWasAdded.connect(self.layerRegistryChanged)
|
|
QgsProject.instance().layersWillBeRemoved.connect(self.layerRegistryChanged)
|
|
|
|
def layerRegistryChanged(self, layers):
|
|
for wrapper in list(self.wrappers.values()):
|
|
try:
|
|
wrapper.refresh()
|
|
except AttributeError:
|
|
pass
|
|
|
|
def initWidgets(self):
|
|
super().initWidgets()
|
|
|
|
widget_context = QgsProcessingParameterWidgetContext()
|
|
widget_context.setProject(QgsProject.instance())
|
|
if iface is not None:
|
|
widget_context.setMapCanvas(iface.mapCanvas())
|
|
widget_context.setBrowserModel(iface.browserModel())
|
|
widget_context.setActiveLayer(iface.activeLayer())
|
|
|
|
widget_context.setMessageBar(self.parent().messageBar())
|
|
if isinstance(self.algorithm(), QgsProcessingModelAlgorithm):
|
|
widget_context.setModel(self.algorithm())
|
|
|
|
in_place_input_parameter_name = 'INPUT'
|
|
if hasattr(self.algorithm(), 'inputParameterName'):
|
|
in_place_input_parameter_name = self.algorithm().inputParameterName()
|
|
|
|
# Create widgets and put them in layouts
|
|
for param in self.algorithm().parameterDefinitions():
|
|
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
|
|
continue
|
|
|
|
if param.isDestination():
|
|
continue
|
|
else:
|
|
if self.in_place and param.name() in (in_place_input_parameter_name, 'OUTPUT'):
|
|
# don't show the input/output parameter widgets in in-place mode
|
|
# we still need to CREATE them, because other wrappers may need to interact
|
|
# with them (e.g. those parameters which need the input layer for field
|
|
# selections/crs properties/etc)
|
|
self.wrappers[param.name()] = QgsProcessingHiddenWidgetWrapper(param, QgsProcessingGui.Standard, self)
|
|
self.wrappers[param.name()].setLinkedVectorLayer(self.active_layer)
|
|
continue
|
|
|
|
wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent())
|
|
wrapper.setWidgetContext(widget_context)
|
|
wrapper.registerProcessingContextGenerator(self.context_generator)
|
|
wrapper.registerProcessingParametersGenerator(self)
|
|
self.wrappers[param.name()] = wrapper
|
|
|
|
# For compatibility with 3.x API, we need to check whether the wrapper is
|
|
# the deprecated WidgetWrapper class. If not, it's the newer
|
|
# QgsAbstractProcessingParameterWidgetWrapper class
|
|
# TODO QGIS 4.0 - remove
|
|
is_python_wrapper = issubclass(wrapper.__class__, WidgetWrapper)
|
|
stretch = 0
|
|
if not is_python_wrapper:
|
|
widget = wrapper.createWrappedWidget(self.processing_context)
|
|
stretch = wrapper.stretch()
|
|
else:
|
|
widget = wrapper.widget
|
|
|
|
if widget is not None:
|
|
if is_python_wrapper:
|
|
widget.setToolTip(param.toolTip())
|
|
|
|
label = None
|
|
if not is_python_wrapper:
|
|
label = wrapper.createWrappedLabel()
|
|
else:
|
|
label = wrapper.label
|
|
|
|
if label is not None:
|
|
self.addParameterLabel(param, label)
|
|
elif is_python_wrapper:
|
|
desc = param.description()
|
|
if isinstance(param, QgsProcessingParameterExtent):
|
|
desc += self.tr(' (xmin, xmax, ymin, ymax)')
|
|
if param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
|
desc += self.tr(' [optional]')
|
|
widget.setText(desc)
|
|
|
|
self.addParameterWidget(param, widget, stretch)
|
|
|
|
for output in self.algorithm().destinationParameterDefinitions():
|
|
if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
|
|
continue
|
|
|
|
if self.in_place and output.name() in (in_place_input_parameter_name, 'OUTPUT'):
|
|
continue
|
|
|
|
wrapper = QgsGui.processingGuiRegistry().createParameterWidgetWrapper(output, QgsProcessingGui.Standard)
|
|
wrapper.setWidgetContext(widget_context)
|
|
wrapper.registerProcessingContextGenerator(self.context_generator)
|
|
wrapper.registerProcessingParametersGenerator(self)
|
|
self.wrappers[output.name()] = wrapper
|
|
|
|
label = wrapper.createWrappedLabel()
|
|
if label is not None:
|
|
self.addOutputLabel(label)
|
|
|
|
widget = wrapper.createWrappedWidget(self.processing_context)
|
|
self.addOutputWidget(widget, wrapper.stretch())
|
|
|
|
# def skipOutputChanged(widget, checkbox, skipped):
|
|
# TODO
|
|
# enabled = not skipped
|
|
#
|
|
# # Do not try to open formats that are write-only.
|
|
# value = widget.value()
|
|
# if value and isinstance(value, QgsProcessingOutputLayerDefinition) and isinstance(output, (
|
|
# QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)):
|
|
# filename = value.sink.staticValue()
|
|
# if filename not in ('memory:', ''):
|
|
# path, ext = os.path.splitext(filename)
|
|
# format = QgsVectorFileWriter.driverForExtension(ext)
|
|
# drv = gdal.GetDriverByName(format)
|
|
# if drv:
|
|
# if drv.GetMetadataItem(gdal.DCAP_OPEN) is None:
|
|
# enabled = False
|
|
#
|
|
# checkbox.setEnabled(enabled)
|
|
# checkbox.setChecked(enabled)
|
|
|
|
for wrapper in list(self.wrappers.values()):
|
|
wrapper.postInitialize(list(self.wrappers.values()))
|
|
|
|
def createProcessingParameters(self, flags=QgsProcessingParametersGenerator.Flags()):
|
|
include_default = not (flags & QgsProcessingParametersGenerator.Flag.SkipDefaultValueParameters)
|
|
parameters = {}
|
|
for p, v in self.extra_parameters.items():
|
|
parameters[p] = v
|
|
|
|
for param in self.algorithm().parameterDefinitions():
|
|
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
|
|
continue
|
|
if not param.isDestination():
|
|
try:
|
|
wrapper = self.wrappers[param.name()]
|
|
except KeyError:
|
|
continue
|
|
|
|
# For compatibility with 3.x API, we need to check whether the wrapper is
|
|
# the deprecated WidgetWrapper class. If not, it's the newer
|
|
# QgsAbstractProcessingParameterWidgetWrapper class
|
|
# TODO QGIS 4.0 - remove
|
|
if issubclass(wrapper.__class__, WidgetWrapper):
|
|
widget = wrapper.widget
|
|
else:
|
|
widget = wrapper.wrappedWidget()
|
|
|
|
if not isinstance(wrapper, QgsProcessingHiddenWidgetWrapper) and widget is None:
|
|
continue
|
|
|
|
value = wrapper.parameterValue()
|
|
if param.defaultValue() != value or include_default:
|
|
parameters[param.name()] = value
|
|
|
|
if not param.checkValueIsAcceptable(value):
|
|
raise AlgorithmDialogBase.InvalidParameterValue(param, widget)
|
|
else:
|
|
if self.in_place and param.name() == 'OUTPUT':
|
|
parameters[param.name()] = 'memory:'
|
|
continue
|
|
|
|
try:
|
|
wrapper = self.wrappers[param.name()]
|
|
except KeyError:
|
|
continue
|
|
|
|
widget = wrapper.wrappedWidget()
|
|
value = wrapper.parameterValue()
|
|
|
|
dest_project = None
|
|
if wrapper.customProperties().get('OPEN_AFTER_RUNNING'):
|
|
dest_project = QgsProject.instance()
|
|
|
|
if value and isinstance(value, QgsProcessingOutputLayerDefinition):
|
|
value.destinationProject = dest_project
|
|
if value and (param.defaultValue() != value or include_default):
|
|
parameters[param.name()] = value
|
|
|
|
context = createContext()
|
|
ok, error = param.isSupportedOutputValue(value, context)
|
|
if not ok:
|
|
raise AlgorithmDialogBase.InvalidOutputExtension(widget, error)
|
|
|
|
return self.algorithm().preprocessParameters(parameters)
|
|
|
|
def setParameters(self, parameters):
|
|
self.extra_parameters = {}
|
|
for param in self.algorithm().parameterDefinitions():
|
|
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
|
|
if param.name() in parameters:
|
|
self.extra_parameters[param.name()] = parameters[param.name()]
|
|
continue
|
|
|
|
if not param.name() in parameters:
|
|
continue
|
|
|
|
value = parameters[param.name()]
|
|
|
|
wrapper = self.wrappers[param.name()]
|
|
wrapper.setParameterValue(value, self.processing_context)
|