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

265 lines
11 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'
2012-09-15 18:25:25 +03:00
import os
import warnings
from functools import partial
from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingParameterExtent,
QgsProcessingParameterPoint,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterRasterDestination,
2017-06-22 18:21:33 +10:00
QgsProcessingParameterFeatureSink,
QgsProcessingParameterVectorDestination,
QgsProject,
QgsProcessingModelAlgorithm)
2018-09-20 08:26:42 +10:00
from qgis.gui import (QgsProcessingContextGenerator,
QgsProcessingParameterWidgetContext)
from qgis.utils import iface
2016-04-29 11:39:26 +02:00
from qgis.PyQt import uic
from qgis.PyQt.QtCore import QCoreApplication, Qt
2017-03-04 19:41:23 +01:00
from qgis.PyQt.QtWidgets import (QWidget, QHBoxLayout, QToolButton,
QLabel, QCheckBox, QSizePolicy)
2016-04-22 10:38:48 +02:00
from qgis.PyQt.QtGui import QIcon
from processing.gui.DestinationSelectionPanel import DestinationSelectionPanel
from processing.gui.wrappers import WidgetWrapperFactory, WidgetWrapper
from processing.tools.dataobjects import createContext
2012-09-15 18:25:25 +03:00
pluginPath = os.path.split(os.path.dirname(__file__))[0]\
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
WIDGET, BASE = uic.loadUiType(
os.path.join(pluginPath, 'ui', 'widgetParametersPanel.ui'))
2015-05-18 21:04:20 +03:00
class ParametersPanel(BASE, WIDGET):
2012-09-15 18:25:25 +03:00
NOT_SELECTED = QCoreApplication.translate('ParametersPanel', '[Not selected]')
2012-09-15 18:25:25 +03:00
2018-07-23 13:58:11 +10:00
def __init__(self, parent, alg, in_place=False):
2015-05-18 21:04:20 +03:00
super(ParametersPanel, self).__init__(None)
self.setupUi(self)
2018-07-23 13:58:11 +10:00
self.in_place = in_place
self.grpAdvanced.hide()
self.scrollAreaWidgetContents.setContentsMargins(4, 4, 4, 4)
self.layoutMain = self.scrollAreaWidgetContents.layout()
self.layoutAdvanced = self.grpAdvanced.layout()
2012-09-15 18:25:25 +03:00
self.parent = parent
self.alg = alg
self.wrappers = {}
self.outputWidgets = {}
2012-09-15 18:25:25 +03:00
self.checkBoxes = {}
self.dependentItems = {}
self.iterateButtons = {}
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 formatParameterTooltip(self, parameter):
2017-08-11 17:26:38 +02:00
return '<p><b>{}</b></p><p>{}</p>'.format(
parameter.description(),
QCoreApplication.translate('ParametersPanel', 'Python identifier: {}').format('<i>{}</i>'.format(parameter.name()))
2017-08-11 17:26:38 +02:00
)
def initWidgets(self):
# If there are advanced parameters — show corresponding groupbox
for param in self.alg.parameterDefinitions():
if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
self.grpAdvanced.show()
break
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())
if isinstance(self.alg, QgsProcessingModelAlgorithm):
widget_context.setModel(self.alg)
2018-09-20 08:26:42 +10:00
# Create widgets and put them in layouts
for param in self.alg.parameterDefinitions():
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue
if param.isDestination():
continue
else:
wrapper = WidgetWrapperFactory.create_wrapper(param, self.parent)
wrapper.setWidgetContext(widget_context)
wrapper.registerProcessingContextGenerator(self.context_generator)
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)
if not is_python_wrapper:
widget = wrapper.createWrappedWidget(self.processing_context)
else:
widget = wrapper.widget
if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
# don't show the input/output parameter widgets in in-place mode
# we still need to CREATE them, because other wrappers may need to interact
# with them (e.g. those parameters which need the input layer for field
# selections/crs properties/etc)
continue
if widget is not None:
if is_python_wrapper:
widget.setToolTip(param.toolTip())
if isinstance(param, QgsProcessingParameterFeatureSource):
layout = QHBoxLayout()
layout.setSpacing(6)
layout.setMargin(0)
layout.addWidget(widget)
button = QToolButton()
icon = QIcon(os.path.join(pluginPath, 'images', 'iterate.png'))
button.setIcon(icon)
button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
button.setToolTip(self.tr('Iterate over this layer, creating a separate output for every feature in the layer'))
button.setCheckable(True)
layout.addWidget(button)
layout.setAlignment(button, Qt.AlignTop)
self.iterateButtons[param.name()] = button
button.toggled.connect(self.buttonToggled)
widget = QWidget()
widget.setLayout(layout)
label = None
if not is_python_wrapper:
label = wrapper.createWrappedLabel()
else:
label = wrapper.label
if label is not None:
if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
self.layoutAdvanced.addWidget(label)
else:
self.layoutMain.insertWidget(
self.layoutMain.count() - 2, label)
elif is_python_wrapper:
desc = param.description()
if isinstance(param, QgsProcessingParameterExtent):
desc += self.tr(' (xmin, xmax, ymin, ymax)')
if isinstance(param, QgsProcessingParameterPoint):
desc += self.tr(' (x, y)')
if param.flags() & QgsProcessingParameterDefinition.FlagOptional:
desc += self.tr(' [optional]')
widget.setText(desc)
if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
self.layoutAdvanced.addWidget(widget)
else:
self.layoutMain.insertWidget(
self.layoutMain.count() - 2, widget)
for output in self.alg.destinationParameterDefinitions():
if output.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue
2018-07-23 13:58:11 +10:00
if self.in_place and param.name() in ('INPUT', 'OUTPUT'):
continue
label = QLabel(output.description())
widget = DestinationSelectionPanel(output, self.alg)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
if isinstance(output, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)):
check = QCheckBox()
2018-03-11 11:29:07 +02:00
check.setText(QCoreApplication.translate('ParametersPanel', 'Open output file after running algorithm'))
def skipOutputChanged(checkbox, skipped):
checkbox.setEnabled(not skipped)
if skipped:
checkbox.setChecked(False)
check.setChecked(not widget.outputIsSkipped())
check.setEnabled(not widget.outputIsSkipped())
widget.skipOutputChanged.connect(partial(skipOutputChanged, check))
self.layoutMain.insertWidget(self.layoutMain.count() - 1, check)
self.checkBoxes[output.name()] = check
widget.setToolTip(param.toolTip())
self.outputWidgets[output.name()] = widget
2016-09-27 19:51:06 +02:00
for wrapper in list(self.wrappers.values()):
wrapper.postInitialize(list(self.wrappers.values()))
def setParameters(self, parameters):
for param in self.alg.parameterDefinitions():
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue
if not param.name() in parameters:
continue
if not param.isDestination():
value = parameters[param.name()]
wrapper = self.wrappers[param.name()]
wrapper.setParameterValue(value, self.processing_context)
else:
dest_widget = self.outputWidgets[param.name()]
dest_widget.setValue(parameters[param.name()])
2012-09-15 18:25:25 +03:00
def buttonToggled(self, value):
if value:
sender = self.sender()
2016-09-21 18:24:26 +02:00
for button in list(self.iterateButtons.values()):
2012-09-15 18:25:25 +03:00
if button is not sender:
button.setChecked(False)