QGIS/python/plugins/processing/gui/ParametersPanel.py

278 lines
12 KiB
Python
Raw Normal View History

2012-10-05 23:28:47 +02:00
# -*- coding: utf-8 -*-
"""
***************************************************************************
ParametersPanel.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
(C) 2013 by CS Systemes d'information (CS SI)
2012-10-05 23:28:47 +02:00
Email : volayaf at gmail dot com
otb at c-s dot fr (CS SI)
2014-04-06 12:27:51 +02:00
Contributors : Victor Olaya
2012-10-05 23:28:47 +02:00
***************************************************************************
* *
* 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)
2018-09-20 08:26:42 +10:00
from qgis.gui import (QgsProcessingContextGenerator,
QgsProcessingParameterWidgetContext,
QgsProcessingParametersWidget,
QgsGui,
QgsProcessingGui,
QgsProcessingParametersGenerator,
QgsProcessingHiddenWidgetWrapper)
2018-09-20 08:26:42 +10:00
from qgis.utils import iface
from processing.gui.wrappers import WidgetWrapperFactory, WidgetWrapper
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
from processing.tools.dataobjects import createContext
2012-09-15 18:25:25 +03:00
2020-04-07 10:06:59 +10:00
class ParametersPanel(QgsProcessingParametersWidget):
2012-09-15 18:25:25 +03:00
def __init__(self, parent, alg, in_place=False, active_layer=None):
super().__init__(alg, parent)
2018-07-23 13:58:11 +10:00
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):
2016-09-27 19:51:06 +02:00
for wrapper in list(self.wrappers.values()):
try:
wrapper.refresh()
except AttributeError:
pass
def initWidgets(self):
super().initWidgets()
2018-09-20 08:26:42 +10:00
widget_context = QgsProcessingParameterWidgetContext()
widget_context.setProject(QgsProject.instance())
2018-09-21 14:55:03 +10:00
if iface is not None:
widget_context.setMapCanvas(iface.mapCanvas())
2020-03-16 16:59:40 +10:00
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())
2018-09-20 08:26:42 +10:00
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'):
2018-07-23 13:58:11 +10:00
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)
2016-09-27 19:51:06 +02:00
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()
2020-12-14 08:08:08 -05:00
if param.defaultValue() != value or include_default:
2020-12-13 17:36:51 -05:00
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
2020-12-14 08:08:08 -05:00
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)