2016-08-23 10:46:22 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
***************************************************************************
|
2017-02-09 16:05:54 +01:00
|
|
|
wrappers.py - Standard parameters widget wrappers
|
2016-08-23 10:46:22 +02:00
|
|
|
---------------------
|
|
|
|
Date : May 2016
|
2016-09-07 14:30:20 +02:00
|
|
|
Copyright : (C) 2016 by Arnaud Morvan, Victor Olaya
|
2016-08-23 10:46:22 +02:00
|
|
|
Email : arnaud dot morvan at camptocamp dot com
|
2016-09-07 14:30:20 +02:00
|
|
|
volayaf at gmail dot com
|
2016-08-23 10:46:22 +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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************
|
|
|
|
"""
|
|
|
|
|
2016-09-18 23:25:25 +02:00
|
|
|
|
2016-08-23 10:46:22 +02:00
|
|
|
__author__ = 'Arnaud Morvan'
|
|
|
|
__date__ = 'May 2016'
|
|
|
|
__copyright__ = '(C) 2016, Arnaud Morvan'
|
|
|
|
|
|
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
|
|
|
|
|
|
|
__revision__ = '$Format:%H$'
|
|
|
|
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
import locale
|
2016-09-18 23:25:25 +02:00
|
|
|
import os
|
2016-09-19 14:35:33 +02:00
|
|
|
from functools import cmp_to_key
|
2017-05-15 16:02:45 +10:00
|
|
|
from inspect import isclass
|
|
|
|
from copy import deepcopy
|
2016-08-23 10:46:22 +02:00
|
|
|
|
2017-02-09 16:06:34 +01:00
|
|
|
from qgis.core import (
|
|
|
|
QgsApplication,
|
|
|
|
QgsCoordinateReferenceSystem,
|
|
|
|
QgsExpression,
|
2017-06-09 15:05:25 +10:00
|
|
|
QgsExpressionContextGenerator,
|
2017-04-19 14:49:35 +02:00
|
|
|
QgsFieldProxyModel,
|
2017-02-09 16:06:34 +01:00
|
|
|
QgsMapLayerProxyModel,
|
|
|
|
QgsWkbTypes,
|
2017-03-16 10:42:53 -05:00
|
|
|
QgsSettings,
|
2017-03-21 10:26:58 +10:00
|
|
|
QgsProject,
|
2017-04-05 14:37:06 +10:00
|
|
|
QgsMapLayer,
|
2017-07-08 14:43:07 +10:00
|
|
|
QgsProcessing,
|
2017-05-15 16:02:45 +10:00
|
|
|
QgsProcessingUtils,
|
|
|
|
QgsProcessingParameterDefinition,
|
|
|
|
QgsProcessingParameterBoolean,
|
|
|
|
QgsProcessingParameterCrs,
|
|
|
|
QgsProcessingParameterExtent,
|
|
|
|
QgsProcessingParameterPoint,
|
|
|
|
QgsProcessingParameterFile,
|
|
|
|
QgsProcessingParameterMultipleLayers,
|
|
|
|
QgsProcessingParameterNumber,
|
|
|
|
QgsProcessingParameterRasterLayer,
|
|
|
|
QgsProcessingParameterEnum,
|
|
|
|
QgsProcessingParameterString,
|
|
|
|
QgsProcessingParameterExpression,
|
2017-06-21 22:13:16 +10:00
|
|
|
QgsProcessingParameterVectorLayer,
|
|
|
|
QgsProcessingParameterField,
|
2017-06-05 16:37:14 +10:00
|
|
|
QgsProcessingParameterFeatureSource,
|
2017-06-13 15:51:40 +10:00
|
|
|
QgsProcessingFeatureSourceDefinition,
|
|
|
|
QgsProcessingOutputRasterLayer,
|
|
|
|
QgsProcessingOutputVectorLayer,
|
|
|
|
QgsProcessingOutputString,
|
2017-06-13 16:05:59 +10:00
|
|
|
QgsProcessingOutputNumber,
|
|
|
|
QgsProcessingModelAlgorithm)
|
2017-05-15 16:02:45 +10:00
|
|
|
|
2017-02-09 16:06:34 +01:00
|
|
|
from qgis.PyQt.QtWidgets import (
|
|
|
|
QCheckBox,
|
|
|
|
QComboBox,
|
|
|
|
QDialog,
|
|
|
|
QFileDialog,
|
|
|
|
QHBoxLayout,
|
2017-06-05 16:37:14 +10:00
|
|
|
QVBoxLayout,
|
2017-02-09 16:06:34 +01:00
|
|
|
QLineEdit,
|
|
|
|
QPlainTextEdit,
|
|
|
|
QToolButton,
|
|
|
|
QWidget,
|
|
|
|
)
|
|
|
|
from qgis.gui import (
|
|
|
|
QgsExpressionLineEdit,
|
|
|
|
QgsExpressionBuilderDialog,
|
|
|
|
QgsFieldComboBox,
|
|
|
|
QgsFieldExpressionWidget,
|
2017-02-27 16:58:04 +10:00
|
|
|
QgsProjectionSelectionDialog,
|
2017-02-09 16:06:34 +01:00
|
|
|
QgsMapLayerComboBox,
|
|
|
|
QgsProjectionSelectionWidget,
|
|
|
|
)
|
2017-07-03 09:13:30 +02:00
|
|
|
from qgis.PyQt.QtCore import pyqtSignal, QObject, QVariant, Qt
|
2017-03-21 10:26:58 +10:00
|
|
|
from qgis.utils import iface
|
2016-08-23 10:46:22 +02:00
|
|
|
|
2016-11-11 11:02:42 +10:00
|
|
|
from processing.gui.NumberInputPanel import NumberInputPanel, ModellerNumberInputPanel
|
2016-09-07 14:30:20 +02:00
|
|
|
from processing.modeler.MultilineTextPanel import MultilineTextPanel
|
|
|
|
from processing.gui.PointSelectionPanel import PointSelectionPanel
|
2016-11-03 16:37:00 +10:00
|
|
|
from processing.core.parameters import (ParameterBoolean,
|
|
|
|
ParameterPoint,
|
|
|
|
ParameterFile,
|
|
|
|
ParameterRaster,
|
|
|
|
ParameterVector,
|
|
|
|
ParameterNumber,
|
|
|
|
ParameterString,
|
|
|
|
ParameterExpression,
|
|
|
|
ParameterTable,
|
|
|
|
ParameterTableField,
|
|
|
|
ParameterExtent,
|
|
|
|
ParameterFixedTable,
|
2017-05-17 07:41:31 +10:00
|
|
|
ParameterCrs)
|
2016-09-07 14:30:20 +02:00
|
|
|
from processing.core.ProcessingConfig import ProcessingConfig
|
|
|
|
from processing.gui.FileSelectionPanel import FileSelectionPanel
|
2017-03-03 20:44:03 +01:00
|
|
|
from processing.core.outputs import (OutputFile, OutputRaster, OutputVector,
|
2016-09-19 11:52:31 +03:00
|
|
|
OutputString, OutputTable, OutputExtent)
|
2016-09-07 14:30:20 +02:00
|
|
|
from processing.tools import dataobjects
|
|
|
|
from processing.gui.MultipleInputPanel import MultipleInputPanel
|
|
|
|
from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
|
|
|
|
from processing.gui.FixedTablePanel import FixedTablePanel
|
|
|
|
from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel
|
2017-06-05 17:22:04 +10:00
|
|
|
from processing.gui.ParameterGuiUtils import getFileFilter
|
2016-08-23 10:46:22 +02:00
|
|
|
DIALOG_STANDARD = 'standard'
|
|
|
|
DIALOG_BATCH = 'batch'
|
|
|
|
DIALOG_MODELER = 'modeler'
|
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class InvalidParameterValue(Exception):
|
|
|
|
pass
|
2016-08-23 10:46:22 +02:00
|
|
|
|
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
dialogTypes = {"AlgorithmDialog": DIALOG_STANDARD,
|
|
|
|
"ModelerParametersDialog": DIALOG_MODELER,
|
2016-09-07 14:30:20 +02:00
|
|
|
"BatchAlgorithmDialog": DIALOG_BATCH}
|
2016-08-23 10:46:22 +02:00
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def getExtendedLayerName(layer):
|
|
|
|
authid = layer.crs().authid()
|
|
|
|
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF) and authid is not None:
|
|
|
|
return u'{} [{}]'.format(layer.name(), authid)
|
|
|
|
else:
|
|
|
|
return layer.name()
|
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class WidgetWrapper(QObject):
|
2016-08-23 10:46:22 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
widgetValueHasChanged = pyqtSignal(object)
|
2016-08-23 10:46:22 +02:00
|
|
|
|
2017-02-09 16:05:54 +01:00
|
|
|
def __init__(self, param, dialog, row=0, col=0, **kwargs):
|
2016-09-07 14:30:20 +02:00
|
|
|
QObject.__init__(self)
|
2016-08-23 10:46:22 +02:00
|
|
|
self.param = param
|
|
|
|
self.dialog = dialog
|
2016-09-07 14:30:20 +02:00
|
|
|
self.row = row
|
|
|
|
self.col = col
|
2016-09-14 07:26:45 +02:00
|
|
|
self.dialogType = dialogTypes.get(dialog.__class__.__name__, DIALOG_STANDARD)
|
2017-02-09 16:05:54 +01:00
|
|
|
self.widget = self.createWidget(**kwargs)
|
2017-05-15 16:02:45 +10:00
|
|
|
if param.defaultValue() is not None:
|
|
|
|
self.setValue(param.defaultValue())
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-11-13 19:05:28 +10:00
|
|
|
def comboValue(self, validator=None, combobox=None):
|
2016-11-16 15:28:27 +10:00
|
|
|
if combobox is None:
|
2016-11-13 19:05:28 +10:00
|
|
|
combobox = self.widget
|
|
|
|
idx = combobox.findText(combobox.currentText())
|
2016-09-07 14:30:20 +02:00
|
|
|
if idx < 0:
|
2016-11-13 19:05:28 +10:00
|
|
|
v = combobox.currentText().strip()
|
2016-09-07 14:30:20 +02:00
|
|
|
if validator is not None and not validator(v):
|
|
|
|
raise InvalidParameterValue()
|
|
|
|
return v
|
2017-01-25 03:28:53 +01:00
|
|
|
return combobox.currentData()
|
2016-09-03 02:25:30 +02:00
|
|
|
|
2017-02-09 16:05:54 +01:00
|
|
|
def createWidget(self, **kwargs):
|
2016-08-23 10:46:22 +02:00
|
|
|
pass
|
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
pass
|
|
|
|
|
2016-11-13 19:05:28 +10:00
|
|
|
def setComboValue(self, value, combobox=None):
|
2016-11-16 15:28:27 +10:00
|
|
|
if combobox is None:
|
2016-11-13 19:05:28 +10:00
|
|
|
combobox = self.widget
|
2016-09-07 14:30:20 +02:00
|
|
|
if isinstance(value, list):
|
2017-07-08 15:58:44 +10:00
|
|
|
if value:
|
|
|
|
value = value[0]
|
|
|
|
else:
|
|
|
|
value = None
|
2016-11-13 19:05:28 +10:00
|
|
|
values = [combobox.itemData(i) for i in range(combobox.count())]
|
2016-09-03 02:25:30 +02:00
|
|
|
try:
|
|
|
|
idx = values.index(value)
|
2016-11-13 19:05:28 +10:00
|
|
|
combobox.setCurrentIndex(idx)
|
2016-09-08 09:57:18 +02:00
|
|
|
return
|
2016-09-03 02:25:30 +02:00
|
|
|
except ValueError:
|
|
|
|
pass
|
2016-11-13 19:05:28 +10:00
|
|
|
if combobox.isEditable():
|
2016-09-07 14:30:20 +02:00
|
|
|
if value is not None:
|
2016-11-13 19:05:28 +10:00
|
|
|
combobox.setEditText(str(value))
|
2016-09-08 09:57:18 +02:00
|
|
|
else:
|
2016-11-13 19:05:28 +10:00
|
|
|
combobox.setCurrentIndex(0)
|
2016-09-03 02:25:30 +02:00
|
|
|
|
2016-08-23 10:46:22 +02:00
|
|
|
def value(self):
|
|
|
|
pass
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def postInitialize(self, wrappers):
|
|
|
|
pass
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def refresh(self):
|
|
|
|
pass
|
2016-08-23 10:46:22 +02:00
|
|
|
|
2016-11-16 14:50:10 +10:00
|
|
|
def getFileName(self, initial_value=''):
|
|
|
|
"""Shows a file open dialog"""
|
2017-03-03 20:39:17 +01:00
|
|
|
settings = QgsSettings()
|
2016-11-16 14:50:10 +10:00
|
|
|
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 = ''
|
|
|
|
|
|
|
|
filename, selected_filter = QFileDialog.getOpenFileName(self.widget, self.tr('Select file'),
|
|
|
|
path, self.tr(
|
2017-06-05 17:22:04 +10:00
|
|
|
'All files (*.*);;') + getFileFilter(self.param))
|
2016-11-16 14:50:10 +10:00
|
|
|
if filename:
|
|
|
|
settings.setValue('/Processing/LastInputPath',
|
|
|
|
os.path.dirname(str(filename)))
|
|
|
|
return filename, selected_filter
|
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2017-02-09 16:07:24 +01:00
|
|
|
class ExpressionWidgetWrapperMixin():
|
2017-02-09 16:06:34 +01:00
|
|
|
|
2017-02-09 16:07:24 +01:00
|
|
|
def wrapWithExpressionButton(self, basewidget):
|
2017-02-09 16:06:34 +01:00
|
|
|
expr_button = QToolButton()
|
|
|
|
expr_button.clicked.connect(self.showExpressionsBuilder)
|
|
|
|
expr_button.setText('...')
|
|
|
|
|
|
|
|
layout = QHBoxLayout()
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
layout.addWidget(basewidget)
|
|
|
|
layout.addWidget(expr_button)
|
|
|
|
|
|
|
|
widget = QWidget()
|
|
|
|
widget.setLayout(layout)
|
|
|
|
|
|
|
|
return widget
|
|
|
|
|
|
|
|
def showExpressionsBuilder(self):
|
2017-05-17 07:50:01 +10:00
|
|
|
context = dataobjects.createExpressionContext()
|
2017-02-09 16:06:34 +01:00
|
|
|
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.Accepted:
|
|
|
|
exp = QgsExpression(dlg.expressionText())
|
|
|
|
if not exp.hasParserError():
|
|
|
|
self.setValue(dlg.expressionText())
|
|
|
|
|
|
|
|
|
2016-09-09 08:25:03 +02:00
|
|
|
class BasicWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
return QLineEdit()
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-09 08:25:03 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
self.widget.setText(value)
|
|
|
|
|
|
|
|
def value(self):
|
|
|
|
return self.widget.text()
|
|
|
|
|
2016-08-23 10:46:22 +02:00
|
|
|
|
|
|
|
class BooleanWidgetWrapper(WidgetWrapper):
|
|
|
|
|
2016-09-03 02:25:30 +02:00
|
|
|
def createWidget(self):
|
2016-09-07 14:30:20 +02:00
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-08-23 10:46:22 +02:00
|
|
|
return QCheckBox()
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
widget = QComboBox()
|
2017-02-08 17:23:33 +01:00
|
|
|
widget.addItem(self.tr('Yes'), True)
|
|
|
|
widget.addItem(self.tr('No'), False)
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
|
|
|
else:
|
2016-08-23 10:46:22 +02:00
|
|
|
widget = QComboBox()
|
2017-02-08 17:23:33 +01:00
|
|
|
widget.addItem(self.tr('Yes'), True)
|
|
|
|
widget.addItem(self.tr('No'), False)
|
2017-06-13 15:51:40 +10:00
|
|
|
bools = self.dialog.getAvailableValuesOfType(QgsProcessingParameterBoolean, None)
|
2016-09-07 14:30:20 +02:00
|
|
|
for b in bools:
|
|
|
|
widget.addItem(self.dialog.resolveValueDescription(b), b)
|
2016-08-23 10:46:22 +02:00
|
|
|
return widget
|
|
|
|
|
|
|
|
def setValue(self, value):
|
2016-09-07 14:30:20 +02:00
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-08-23 10:46:22 +02:00
|
|
|
self.widget.setChecked(value)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-09-03 02:25:30 +02:00
|
|
|
self.setComboValue(value)
|
2016-08-23 10:46:22 +02:00
|
|
|
|
|
|
|
def value(self):
|
2016-09-07 14:30:20 +02:00
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-08-23 10:46:22 +02:00
|
|
|
return self.widget.isChecked()
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-09-03 02:25:30 +02:00
|
|
|
return self.comboValue()
|
2016-08-24 15:23:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
class CrsWidgetWrapper(WidgetWrapper):
|
|
|
|
|
2016-09-03 02:25:30 +02:00
|
|
|
def createWidget(self):
|
2016-09-08 09:57:18 +02:00
|
|
|
if self.dialogType == DIALOG_MODELER:
|
2016-11-13 19:05:28 +10:00
|
|
|
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)
|
2017-06-13 15:51:40 +10:00
|
|
|
crss = self.dialog.getAvailableValuesOfType(QgsProcessingParameterCrs)
|
2016-09-08 09:57:18 +02:00
|
|
|
for crs in crss:
|
2016-11-13 19:05:28 +10:00
|
|
|
self.combo.addItem(self.dialog.resolveValueDescription(crs), crs)
|
2017-06-13 15:51:40 +10:00
|
|
|
raster = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer)
|
|
|
|
vector = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer)
|
2016-09-08 09:57:18 +02:00
|
|
|
for r in raster:
|
2016-11-13 19:05:28 +10:00
|
|
|
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(r), r)
|
2016-09-08 09:57:18 +02:00
|
|
|
for v in vector:
|
2016-11-13 19:05:28 +10:00
|
|
|
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(v), v)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.defaultValue():
|
|
|
|
self.combo.setEditText(self.param.defaultValue())
|
2016-09-08 09:57:18 +02:00
|
|
|
return widget
|
|
|
|
else:
|
2016-11-11 19:46:42 +10:00
|
|
|
widget = QgsProjectionSelectionWidget()
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-11 19:46:42 +10:00
|
|
|
widget.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, True)
|
|
|
|
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.defaultValue():
|
|
|
|
if self.param.defaultValue() == 'ProjectCrs':
|
2017-03-16 10:42:53 -05:00
|
|
|
crs = QgsProject.instance().crs()
|
|
|
|
else:
|
2017-05-15 16:02:45 +10:00
|
|
|
crs = QgsCoordinateReferenceSystem(self.param.defaultValue())
|
2016-11-11 19:46:42 +10:00
|
|
|
widget.setCrs(crs)
|
2017-02-10 17:39:45 +02:00
|
|
|
else:
|
|
|
|
widget.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, True)
|
2016-11-11 19:46:42 +10:00
|
|
|
|
|
|
|
return widget
|
2016-08-24 15:23:25 +02:00
|
|
|
|
2016-11-13 19:05:28 +10:00
|
|
|
def selectProjection(self):
|
2017-02-27 16:58:04 +10:00
|
|
|
dialog = QgsProjectionSelectionDialog(self.widget)
|
2016-11-13 19:05:28 +10:00
|
|
|
current_crs = QgsCoordinateReferenceSystem(self.combo.currentText())
|
|
|
|
if current_crs.isValid():
|
2017-02-27 16:58:04 +10:00
|
|
|
dialog.setCrs(current_crs)
|
2016-11-13 19:05:28 +10:00
|
|
|
|
|
|
|
if dialog.exec_():
|
2017-02-27 16:58:04 +10:00
|
|
|
self.setValue(dialog.crs().authid())
|
2016-11-13 19:05:28 +10:00
|
|
|
|
2016-08-24 15:23:25 +02:00
|
|
|
def setValue(self, value):
|
2016-09-08 09:57:18 +02:00
|
|
|
if self.dialogType == DIALOG_MODELER:
|
2016-11-13 19:05:28 +10:00
|
|
|
self.setComboValue(value, self.combo)
|
2017-03-16 10:42:53 -05:00
|
|
|
elif value == 'ProjectCrs':
|
|
|
|
self.widget.setCrs(QgsProject.instance().crs())
|
2016-08-24 15:23:25 +02:00
|
|
|
else:
|
2016-11-11 19:46:42 +10:00
|
|
|
self.widget.setCrs(QgsCoordinateReferenceSystem(value))
|
2016-08-24 15:23:25 +02:00
|
|
|
|
|
|
|
def value(self):
|
2016-09-08 09:57:18 +02:00
|
|
|
if self.dialogType == DIALOG_MODELER:
|
2016-11-13 19:05:28 +10:00
|
|
|
return self.comboValue(combobox=self.combo)
|
2016-09-08 09:57:18 +02:00
|
|
|
else:
|
2016-11-11 19:46:42 +10:00
|
|
|
crs = self.widget.crs()
|
|
|
|
if crs.isValid():
|
|
|
|
return self.widget.crs().authid()
|
|
|
|
else:
|
|
|
|
return None
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class ExtentWidgetWrapper(WidgetWrapper):
|
|
|
|
|
2016-09-08 09:57:18 +02:00
|
|
|
USE_MIN_COVERING_EXTENT = "[Use min covering extent]"
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
|
|
|
return ExtentSelectionPanel(self.dialog, self.param)
|
|
|
|
else:
|
|
|
|
widget = QComboBox()
|
|
|
|
widget.setEditable(True)
|
2017-06-13 15:51:40 +10:00
|
|
|
extents = self.dialog.getAvailableValuesOfType(QgsProcessingParameterExtent, OutputExtent)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-09-07 14:30:20 +02:00
|
|
|
widget.addItem(self.USE_MIN_COVERING_EXTENT, None)
|
2017-06-13 15:51:40 +10:00
|
|
|
raster = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer)
|
|
|
|
vector = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer)
|
2016-09-07 14:30:20 +02:00
|
|
|
for ex in extents:
|
|
|
|
widget.addItem(self.dialog.resolveValueDescription(ex), ex)
|
2016-09-08 09:57:18 +02:00
|
|
|
for r in raster:
|
|
|
|
widget.addItem("Extent of " + self.dialog.resolveValueDescription(r), r)
|
|
|
|
for v in vector:
|
|
|
|
widget.addItem("Extent of " + self.dialog.resolveValueDescription(v), v)
|
2017-05-15 16:02:45 +10:00
|
|
|
if not self.param.defaultValue():
|
|
|
|
widget.setEditText(self.param.defaultValue())
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
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:
|
2016-09-27 19:51:06 +02:00
|
|
|
s = str(self.widget.currentText()).strip()
|
2016-09-07 14:30:20 +02:00
|
|
|
if s:
|
|
|
|
try:
|
|
|
|
tokens = s.split(',')
|
|
|
|
if len(tokens) != 4:
|
|
|
|
raise InvalidParameterValue()
|
|
|
|
for token in tokens:
|
|
|
|
float(token)
|
|
|
|
except:
|
|
|
|
raise InvalidParameterValue()
|
2017-05-15 16:02:45 +10:00
|
|
|
elif self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-09-07 14:30:20 +02:00
|
|
|
s = None
|
|
|
|
else:
|
|
|
|
raise InvalidParameterValue()
|
|
|
|
return s
|
|
|
|
else:
|
2017-01-25 03:28:53 +01:00
|
|
|
return self.widget.currentData()
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
class PointWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2017-05-15 16:02:45 +10:00
|
|
|
return PointSelectionPanel(self.dialog, self.param.defaultValue())
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
|
|
|
item = QComboBox()
|
|
|
|
item.setEditable(True)
|
2017-06-13 15:51:40 +10:00
|
|
|
points = self.dialog.getAvailableValuesOfType(QgsProcessingParameterPoint)
|
2016-09-07 14:30:20 +02:00
|
|
|
for p in points:
|
|
|
|
item.addItem(self.dialog.resolveValueDescription(p), p)
|
2017-05-15 16:02:45 +10:00
|
|
|
item.setEditText(str(self.param.defaultValue()))
|
2016-09-18 13:24:38 +02:00
|
|
|
return item
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
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:
|
2016-09-27 19:51:06 +02:00
|
|
|
s = str(self.widget.currentText()).strip()
|
2016-09-07 14:30:20 +02:00
|
|
|
if s:
|
|
|
|
try:
|
|
|
|
tokens = s.split(',')
|
|
|
|
if len(tokens) != 2:
|
|
|
|
raise InvalidParameterValue()
|
|
|
|
for token in tokens:
|
|
|
|
float(token)
|
|
|
|
except:
|
|
|
|
raise InvalidParameterValue()
|
2017-05-15 16:02:45 +10:00
|
|
|
elif self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-09-07 14:30:20 +02:00
|
|
|
s = None
|
|
|
|
else:
|
|
|
|
raise InvalidParameterValue()
|
|
|
|
return s
|
|
|
|
else:
|
2017-01-25 03:28:53 +01:00
|
|
|
return self.widget.currentData()
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
class FileWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2017-05-15 16:02:45 +10:00
|
|
|
return FileSelectionPanel(self.param.behavior() == QgsProcessingParameterFile.Folder, self.param.extension())
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
|
|
|
widget = QComboBox()
|
|
|
|
widget.setEditable(True)
|
2017-06-13 15:51:40 +10:00
|
|
|
files = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFile, OutputFile)
|
2016-09-07 14:30:20 +02:00
|
|
|
for f in files:
|
|
|
|
widget.addItem(self.dialog.resolveValueDescription(f), f)
|
|
|
|
return widget
|
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
|
|
|
self.widget.setText(value)
|
|
|
|
else:
|
|
|
|
self.setComboValue(value)
|
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
|
|
|
return self.widget.getValue()
|
|
|
|
else:
|
|
|
|
return self.comboValue()
|
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class FixedTableWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
return FixedTablePanel(self.param)
|
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType == DIALOG_MODELER:
|
|
|
|
table = self.widget.table
|
2017-05-15 16:02:45 +10:00
|
|
|
if not bool(table) and not self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-09-07 14:30:20 +02:00
|
|
|
raise InvalidParameterValue()
|
|
|
|
return ParameterFixedTable.tableToString(table)
|
|
|
|
else:
|
|
|
|
return self.widget.table
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
class MultipleInputWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def _getOptions(self):
|
2017-07-08 14:43:07 +10:00
|
|
|
if self.param.layerType() == QgsProcessing.TypeVectorAny:
|
2017-06-13 15:51:40 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer)
|
2017-07-08 14:43:07 +10:00
|
|
|
elif self.param.layerType() == QgsProcessing.TypeVectorPoint:
|
2017-06-13 15:51:40 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer,
|
2017-07-08 14:43:07 +10:00
|
|
|
[QgsProcessing.TypeVectorPoint, QgsProcessing.TypeVectorAny])
|
|
|
|
elif self.param.layerType() == QgsProcessing.TypeVectorLine:
|
2017-06-13 15:51:40 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer,
|
2017-07-08 14:43:07 +10:00
|
|
|
[QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorAny])
|
|
|
|
elif self.param.layerType() == QgsProcessing.TypeVectorPolygon:
|
2017-06-13 15:51:40 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer,
|
2017-07-08 14:43:07 +10:00
|
|
|
[QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorAny])
|
|
|
|
elif self.param.layerType() == QgsProcessing.TypeRaster:
|
2017-06-13 15:51:40 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer)
|
2017-07-08 14:43:07 +10:00
|
|
|
elif self.param.layerType() == QgsProcessing.TypeTable:
|
2017-06-21 22:13:16 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterVectorLayer, OutputTable)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2017-06-13 15:51:40 +10:00
|
|
|
options = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFile, OutputFile)
|
2016-09-21 11:27:08 +02:00
|
|
|
options = sorted(options, key=lambda opt: self.dialog.resolveValueDescription(opt))
|
2016-09-07 14:30:20 +02:00
|
|
|
return options
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2017-07-08 14:43:07 +10:00
|
|
|
if self.param.layerType() == QgsProcessing.TypeFile:
|
2016-09-07 14:30:20 +02:00
|
|
|
return MultipleInputPanel(datatype=dataobjects.TYPE_FILE)
|
|
|
|
else:
|
2017-07-08 14:43:07 +10:00
|
|
|
if self.param.layerType() == QgsProcessing.TypeRaster:
|
2017-04-05 14:37:06 +10:00
|
|
|
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
|
2017-07-08 14:43:07 +10:00
|
|
|
elif self.param.layerType() in (QgsProcessing.TypeVectorAny, QgsProcessing.TypeTable):
|
2017-04-05 14:37:06 +10:00
|
|
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2017-05-15 16:02:45 +10:00
|
|
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
2016-09-07 14:30:20 +02:00
|
|
|
opts = [getExtendedLayerName(opt) for opt in options]
|
|
|
|
return MultipleInputPanel(opts)
|
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-19 21:52:59 +02:00
|
|
|
widget = BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
|
|
|
|
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
|
|
|
return widget
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
|
|
|
options = [self.dialog.resolveValueDescription(opt) for opt in self._getOptions()]
|
|
|
|
return MultipleInputPanel(options)
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def refresh(self):
|
2017-07-08 14:43:07 +10:00
|
|
|
if self.param.layerType() != QgsProcessing.TypeFile:
|
|
|
|
if self.param.layerType() == QgsProcessing.TypeRaster:
|
2017-04-05 14:37:06 +10:00
|
|
|
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
|
2017-07-08 14:43:07 +10:00
|
|
|
elif self.param.layerType() in (QgsProcessing.TypeVectorAny, QgsProcessing.TypeTable):
|
2017-04-05 14:37:06 +10:00
|
|
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2017-05-15 16:02:45 +10:00
|
|
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
2016-12-20 14:20:46 +07:00
|
|
|
opts = [getExtendedLayerName(opt) for opt in options]
|
2016-09-07 14:30:20 +02:00
|
|
|
self.widget.updateForOptions(opts)
|
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
|
|
|
pass # TODO
|
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
return self.widget.setText(value)
|
|
|
|
else:
|
|
|
|
options = self._getOptions()
|
|
|
|
selected = []
|
|
|
|
for i, opt in enumerate(options):
|
|
|
|
if opt in value:
|
|
|
|
selected.append(i)
|
|
|
|
self.widget.setSelectedItems(selected)
|
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2017-07-08 14:43:07 +10:00
|
|
|
if self.param.layerType() == QgsProcessing.TypeFile:
|
2016-09-07 14:30:20 +02:00
|
|
|
return self.param.setValue(self.widget.selectedoptions)
|
|
|
|
else:
|
2017-07-08 14:43:07 +10:00
|
|
|
if self.param.layerType() == QgsProcessing.TypeRaster:
|
2017-04-05 14:37:06 +10:00
|
|
|
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
|
2017-07-08 14:43:07 +10:00
|
|
|
elif self.param.layerType() in (QgsProcessing.TypeVectorAny, QgsProcessing.TypeTable):
|
2017-04-05 14:37:06 +10:00
|
|
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2017-05-15 16:02:45 +10:00
|
|
|
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.layerType()], False)
|
2016-09-09 10:48:51 +02:00
|
|
|
return [options[i] for i in self.widget.selectedoptions]
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
return self.widget.getText()
|
|
|
|
else:
|
|
|
|
options = self._getOptions()
|
|
|
|
values = [options[i] for i in self.widget.selectedoptions]
|
2017-07-08 14:43:07 +10:00
|
|
|
if len(values) == 0 and not self.param.flags() & QgsProcessing.FlagOptional:
|
2016-09-07 14:30:20 +02:00
|
|
|
raise InvalidParameterValue()
|
|
|
|
return values
|
|
|
|
|
|
|
|
|
|
|
|
class NumberWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2016-12-07 11:59:35 +10:00
|
|
|
widget = NumberInputPanel(self.param)
|
|
|
|
widget.hasChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
|
|
|
return widget
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-11-11 11:02:42 +10:00
|
|
|
return ModellerNumberInputPanel(self.param, self.dialog)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def setValue(self, value):
|
2016-09-12 06:17:23 +02:00
|
|
|
self.widget.setValue(value)
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def value(self):
|
2016-09-12 06:17:23 +02:00
|
|
|
return self.widget.getValue()
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class RasterWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
NOT_SELECTED = '[Not selected]'
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-11-16 14:50:10 +10:00
|
|
|
widget = QWidget()
|
|
|
|
layout = QHBoxLayout()
|
|
|
|
layout.setMargin(0)
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
layout.setSpacing(2)
|
|
|
|
self.combo = QgsMapLayerComboBox()
|
|
|
|
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)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-16 14:50:10 +10:00
|
|
|
self.combo.setAllowEmptyLayer(True)
|
|
|
|
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF):
|
|
|
|
self.combo.setShowCrs(True)
|
|
|
|
|
|
|
|
self.combo.setFilters(QgsMapLayerProxyModel.RasterLayer)
|
|
|
|
self.combo.setExcludedProviders(['grass'])
|
2017-03-21 10:26:58 +10:00
|
|
|
try:
|
|
|
|
if iface.activeLayer().type() == QgsMapLayer.RasterLayer:
|
|
|
|
self.combo.setLayer(iface.activeLayer())
|
|
|
|
except:
|
|
|
|
pass
|
2016-11-16 14:50:10 +10:00
|
|
|
|
|
|
|
self.combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
|
|
|
self.combo.currentTextChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
|
|
|
return widget
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
return BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
|
|
|
|
else:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo = QComboBox()
|
2017-06-13 15:51:40 +10:00
|
|
|
layers = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer)
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo.setEditable(True)
|
|
|
|
for layer in layers:
|
|
|
|
self.combo.addItem(self.dialog.resolveValueDescription(layer), layer)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-16 15:28:27 +10:00
|
|
|
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)
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
|
|
|
|
2016-11-16 14:50:10 +10:00
|
|
|
def selectFile(self):
|
|
|
|
filename, selected_filter = self.getFileName(self.combo.currentText())
|
|
|
|
if filename:
|
|
|
|
filename = dataobjects.getRasterSublayer(filename, self.param)
|
2016-11-16 15:28:27 +10:00
|
|
|
if 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)
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
|
|
|
pass # TODO
|
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-12 07:54:55 +02:00
|
|
|
self.widget.setText(value)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.setComboValue(value, combobox=self.combo)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-11-16 14:50:10 +10:00
|
|
|
try:
|
|
|
|
layer = self.combo.currentLayer()
|
|
|
|
if layer:
|
|
|
|
return layer
|
|
|
|
else:
|
|
|
|
return self.combo.currentText()
|
|
|
|
except:
|
|
|
|
return self.combo.currentText()
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
return self.widget.getText()
|
|
|
|
else:
|
2016-09-12 07:54:55 +02:00
|
|
|
def validator(v):
|
2016-09-18 23:25:25 +02:00
|
|
|
if not bool(v):
|
2017-05-15 16:02:45 +10:00
|
|
|
return self.param.flags() & QgsProcessingParameterDefinition.FlagOptional
|
2016-09-18 23:25:25 +02:00
|
|
|
else:
|
|
|
|
return os.path.exists(v)
|
2016-11-16 15:28:27 +10:00
|
|
|
return self.comboValue(validator, combobox=self.combo)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
class SelectionWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
|
|
|
return MultipleInputPanel(options=self.param.options())
|
2016-09-16 12:04:12 +02:00
|
|
|
else:
|
|
|
|
widget = QComboBox()
|
2017-05-15 19:01:15 +10:00
|
|
|
for i, option in enumerate(self.param.options()):
|
|
|
|
widget.addItem(option, i)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.defaultValue():
|
|
|
|
widget.setCurrentIndex(widget.findData(self.param.defaultValue()))
|
2016-09-16 12:04:12 +02:00
|
|
|
return widget
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def setValue(self, value):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
2016-09-16 12:04:12 +02:00
|
|
|
self.widget.setSelectedItems(value)
|
|
|
|
else:
|
2016-11-05 21:14:26 +01:00
|
|
|
self.widget.setCurrentIndex(self.widget.findData(value))
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def value(self):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
2016-09-19 11:52:31 +03:00
|
|
|
return self.widget.selectedoptions
|
2016-09-16 12:04:12 +02:00
|
|
|
else:
|
2016-11-05 21:14:26 +01:00
|
|
|
return self.widget.currentData()
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
class VectorWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
NOT_SELECTED = '[Not selected]'
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-11-16 14:50:10 +10:00
|
|
|
widget = QWidget()
|
|
|
|
layout = QHBoxLayout()
|
|
|
|
layout.setMargin(0)
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
layout.setSpacing(2)
|
|
|
|
self.combo = QgsMapLayerComboBox()
|
|
|
|
layout.addWidget(self.combo)
|
2017-07-03 09:13:30 +02:00
|
|
|
layout.setAlignment(self.combo, Qt.AlignTop)
|
2016-11-16 14:50:10 +10:00
|
|
|
btn = QToolButton()
|
|
|
|
btn.setText('...')
|
|
|
|
btn.setToolTip(self.tr("Select file"))
|
|
|
|
btn.clicked.connect(self.selectFile)
|
|
|
|
layout.addWidget(btn)
|
2017-07-03 09:13:30 +02:00
|
|
|
layout.setAlignment(btn, Qt.AlignTop)
|
2016-11-16 14:50:10 +10:00
|
|
|
|
2017-06-05 16:37:14 +10:00
|
|
|
vl = QVBoxLayout()
|
|
|
|
vl.setMargin(0)
|
|
|
|
vl.setContentsMargins(0, 0, 0, 0)
|
|
|
|
vl.setSpacing(2)
|
|
|
|
vl.addLayout(layout)
|
|
|
|
|
|
|
|
self.use_selection_checkbox = QCheckBox(self.tr('Selected features only'))
|
|
|
|
self.use_selection_checkbox.setChecked(False)
|
|
|
|
self.use_selection_checkbox.setEnabled(False)
|
|
|
|
vl.addWidget(self.use_selection_checkbox)
|
|
|
|
|
|
|
|
widget.setLayout(vl)
|
2016-11-16 14:50:10 +10:00
|
|
|
|
|
|
|
filters = QgsMapLayerProxyModel.Filters()
|
2017-07-08 14:43:07 +10:00
|
|
|
if QgsProcessing.TypeVectorAny in self.param.dataTypes() or len(self.param.dataTypes()) == 0:
|
2016-11-16 14:50:10 +10:00
|
|
|
filters = QgsMapLayerProxyModel.HasGeometry
|
2017-07-08 14:43:07 +10:00
|
|
|
if QgsProcessing.TypeVectorPoint in self.param.dataTypes():
|
2016-11-16 14:50:10 +10:00
|
|
|
filters |= QgsMapLayerProxyModel.PointLayer
|
2017-07-08 14:43:07 +10:00
|
|
|
if QgsProcessing.TypeVectorLine in self.param.dataTypes():
|
2016-11-16 14:50:10 +10:00
|
|
|
filters |= QgsMapLayerProxyModel.LineLayer
|
2017-07-08 14:43:07 +10:00
|
|
|
if QgsProcessing.TypeVectorPolygon in self.param.dataTypes():
|
2016-11-16 14:50:10 +10:00
|
|
|
filters |= QgsMapLayerProxyModel.PolygonLayer
|
|
|
|
|
2017-03-21 10:26:58 +10:00
|
|
|
try:
|
|
|
|
if iface.activeLayer().type() == QgsMapLayer.VectorLayer:
|
|
|
|
self.combo.setLayer(iface.activeLayer())
|
2017-06-05 16:37:14 +10:00
|
|
|
self.use_selection_checkbox.setEnabled(iface.activeLayer().selectedFeatureCount() > 0)
|
|
|
|
|
2017-03-21 10:26:58 +10:00
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-16 14:50:10 +10:00
|
|
|
self.combo.setAllowEmptyLayer(True)
|
|
|
|
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF):
|
|
|
|
self.combo.setShowCrs(True)
|
|
|
|
|
2017-05-22 16:14:58 +10:00
|
|
|
if filters:
|
|
|
|
self.combo.setFilters(filters)
|
2016-11-16 14:50:10 +10:00
|
|
|
self.combo.setExcludedProviders(['grass'])
|
|
|
|
|
2017-06-05 16:37:14 +10:00
|
|
|
self.combo.layerChanged.connect(self.layerChanged)
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
2016-11-16 14:50:10 +10:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-18 16:07:32 +02:00
|
|
|
widget = BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
|
|
|
|
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
|
|
|
return widget
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo = QComboBox()
|
2017-06-13 15:51:40 +10:00
|
|
|
layers = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource, QgsProcessingOutputVectorLayer)
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo.setEditable(True)
|
2016-09-07 14:30:20 +02:00
|
|
|
for layer in layers:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo.addItem(self.dialog.resolveValueDescription(layer), layer)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-16 15:28:27 +10:00
|
|
|
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)
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2017-06-05 16:37:14 +10:00
|
|
|
def layerChanged(self, layer):
|
|
|
|
if not layer or layer.type() != QgsMapLayer.VectorLayer or layer.selectedFeatureCount() == 0:
|
|
|
|
self.use_selection_checkbox.setChecked(False)
|
|
|
|
self.use_selection_checkbox.setEnabled(False)
|
|
|
|
else:
|
|
|
|
self.use_selection_checkbox.setEnabled(True)
|
|
|
|
self.widgetValueHasChanged.emit(self)
|
|
|
|
|
2016-11-16 14:50:10 +10:00
|
|
|
def selectFile(self):
|
|
|
|
filename, selected_filter = self.getFileName(self.combo.currentText())
|
|
|
|
if filename:
|
|
|
|
filename = dataobjects.getRasterSublayer(filename, self.param)
|
2016-11-16 15:28:27 +10:00
|
|
|
if 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)
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
|
|
|
pass # TODO
|
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-18 16:07:32 +02:00
|
|
|
self.widget.setValue(value)
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.setComboValue(value, combobox=self.combo)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2017-06-05 16:37:14 +10:00
|
|
|
use_selected_features = self.use_selection_checkbox.isChecked()
|
2016-09-07 14:30:20 +02:00
|
|
|
try:
|
2016-11-16 14:50:10 +10:00
|
|
|
layer = self.combo.currentLayer()
|
2017-06-26 16:16:26 +10:00
|
|
|
if layer is not None:
|
2017-06-05 16:37:14 +10:00
|
|
|
return QgsProcessingFeatureSourceDefinition(layer.id(), use_selected_features)
|
2016-11-16 14:50:10 +10:00
|
|
|
else:
|
2017-06-12 10:38:40 +10:00
|
|
|
if self.combo.currentText():
|
|
|
|
return QgsProcessingFeatureSourceDefinition(self.combo.currentText(), use_selected_features)
|
|
|
|
else:
|
|
|
|
return None
|
2016-09-07 14:30:20 +02:00
|
|
|
except:
|
2017-06-05 16:37:14 +10:00
|
|
|
return QgsProcessingFeatureSourceDefinition(self.combo.currentText(), use_selected_features)
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-18 16:07:32 +02:00
|
|
|
return self.widget.value()
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-09-12 07:54:55 +02:00
|
|
|
def validator(v):
|
2016-09-18 23:25:25 +02:00
|
|
|
if not bool(v):
|
2017-05-15 16:02:45 +10:00
|
|
|
return self.param.flags() & QgsProcessingParameterDefinition.FlagOptional
|
2016-09-18 23:25:25 +02:00
|
|
|
else:
|
|
|
|
return os.path.exists(v)
|
2016-11-16 15:28:27 +10:00
|
|
|
return self.comboValue(validator, combobox=self.combo)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2017-02-10 10:10:32 +01:00
|
|
|
class StringWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin):
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.multiLine():
|
2016-09-07 14:30:20 +02:00
|
|
|
widget = QPlainTextEdit()
|
|
|
|
else:
|
2017-02-10 10:10:32 +01:00
|
|
|
self._lineedit = QLineEdit()
|
|
|
|
return self.wrapWithExpressionButton(self._lineedit)
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-19 11:52:31 +03:00
|
|
|
widget = QLineEdit()
|
2017-02-10 10:10:32 +01:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-11-09 13:45:08 +10:00
|
|
|
# strings, numbers, files and table fields are all allowed input types
|
2017-06-13 15:51:40 +10:00
|
|
|
strings = self.dialog.getAvailableValuesOfType([QgsProcessingParameterString, QgsProcessingParameterNumber, QgsProcessingParameterFile,
|
2017-07-03 19:42:29 +10:00
|
|
|
QgsProcessingParameterField, QgsProcessingParameterExpression], [QgsProcessingOutputString])
|
2016-09-07 14:30:20 +02:00
|
|
|
options = [(self.dialog.resolveValueDescription(s), s) for s in strings]
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.multiLine():
|
2016-09-07 14:30:20 +02:00
|
|
|
widget = MultilineTextPanel(options)
|
|
|
|
else:
|
|
|
|
widget = QComboBox()
|
|
|
|
widget.setEditable(True)
|
|
|
|
for desc, val in options:
|
|
|
|
widget.addItem(desc, val)
|
|
|
|
return widget
|
|
|
|
|
2017-06-06 12:36:10 +10:00
|
|
|
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.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())
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.multiLine():
|
2017-02-10 10:10:32 +01:00
|
|
|
self.widget.setPlainText(value)
|
|
|
|
else:
|
|
|
|
self._lineedit.setText(value)
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
self.widget.setText(value)
|
2017-02-10 10:10:32 +01:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.multiLine():
|
2016-09-07 14:30:20 +02:00
|
|
|
self.widget.setValue(value)
|
|
|
|
else:
|
|
|
|
self.setComboValue(value)
|
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType in DIALOG_STANDARD:
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.multiLine():
|
2016-09-07 14:30:20 +02:00
|
|
|
text = self.widget.toPlainText()
|
|
|
|
else:
|
2017-02-10 10:10:32 +01:00
|
|
|
text = self._lineedit.text()
|
2016-09-07 14:30:20 +02:00
|
|
|
return text
|
2017-02-10 10:10:32 +01:00
|
|
|
|
2016-11-17 12:06:24 +01:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-09-18 17:14:50 +02:00
|
|
|
return self.widget.text()
|
2017-02-10 10:10:32 +01:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.multiLine():
|
2016-09-07 14:30:20 +02:00
|
|
|
value = self.widget.getValue()
|
|
|
|
option = self.widget.getOption()
|
|
|
|
if option == MultilineTextPanel.USE_TEXT:
|
|
|
|
if value == '':
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-09-07 14:30:20 +02:00
|
|
|
return None
|
|
|
|
else:
|
|
|
|
raise InvalidParameterValue()
|
|
|
|
else:
|
|
|
|
return value
|
|
|
|
else:
|
|
|
|
return value
|
|
|
|
else:
|
|
|
|
def validator(v):
|
2017-05-15 16:02:45 +10:00
|
|
|
return bool(v) or self.param.flags() & QgsProcessingParameterDefinition.FlagOptional
|
2016-09-07 14:30:20 +02:00
|
|
|
return self.comboValue(validator)
|
|
|
|
|
|
|
|
|
2016-11-03 16:37:00 +10:00
|
|
|
class ExpressionWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.parentLayerParameter():
|
2016-11-11 12:03:33 +10:00
|
|
|
widget = QgsFieldExpressionWidget()
|
|
|
|
else:
|
|
|
|
widget = QgsExpressionLineEdit()
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.defaultValue():
|
|
|
|
widget.setExpression(self.param.defaultValue())
|
2016-11-03 16:37:00 +10:00
|
|
|
else:
|
2017-06-13 15:51:40 +10:00
|
|
|
strings = self.dialog.getAvailableValuesOfType([QgsProcessingParameterExpression, QgsProcessingParameterString, QgsProcessingParameterNumber], QgsProcessingOutputString)
|
2016-11-03 16:37:00 +10:00
|
|
|
options = [(self.dialog.resolveValueDescription(s), s) for s in strings]
|
|
|
|
widget = QComboBox()
|
|
|
|
widget.setEditable(True)
|
|
|
|
for desc, val in options:
|
|
|
|
widget.addItem(desc, val)
|
2017-06-13 15:51:40 +10:00
|
|
|
widget.setEditText(self.param.defaultValue() or "")
|
2016-11-03 16:37:00 +10:00
|
|
|
return widget
|
|
|
|
|
|
|
|
def postInitialize(self, wrappers):
|
|
|
|
for wrapper in wrappers:
|
2017-05-15 16:02:45 +10:00
|
|
|
if wrapper.param.name() == self.param.parentLayerParameter():
|
2016-11-03 16:37:00 +10:00
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
|
|
|
self.setLayer(wrapper.value())
|
|
|
|
wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
|
|
|
|
break
|
|
|
|
|
|
|
|
def parentLayerChanged(self, wrapper):
|
|
|
|
self.setLayer(wrapper.value())
|
|
|
|
|
|
|
|
def setLayer(self, layer):
|
2017-05-01 17:40:47 +10:00
|
|
|
context = dataobjects.createContext()
|
2017-06-09 15:05:25 +10:00
|
|
|
if isinstance(layer, QgsProcessingFeatureSourceDefinition):
|
|
|
|
layer, ok = layer.source.valueAsString(context.expressionContext())
|
2016-11-03 16:37:00 +10:00
|
|
|
if isinstance(layer, str):
|
2017-05-17 07:41:31 +10:00
|
|
|
layer = QgsProcessingUtils.mapLayerFromString(layer, context)
|
2016-11-03 16:37:00 +10:00
|
|
|
self.widget.setLayer(layer)
|
|
|
|
|
|
|
|
def setValue(self, value):
|
|
|
|
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):
|
2016-11-11 20:12:58 +10:00
|
|
|
try:
|
|
|
|
return self.widget.asExpression()
|
|
|
|
except:
|
|
|
|
return self.widget.expression()
|
2016-11-03 16:37:00 +10:00
|
|
|
else:
|
|
|
|
def validator(v):
|
2017-05-15 16:02:45 +10:00
|
|
|
return bool(v) or self.param.flags() & QgsProcessingParameterDefinition.FlagOptional
|
2016-11-03 16:37:00 +10:00
|
|
|
return self.comboValue(validator)
|
|
|
|
|
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class TableWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
NOT_SELECTED = '[Not selected]'
|
|
|
|
|
|
|
|
def createWidget(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
2016-11-16 14:50:10 +10:00
|
|
|
widget = QWidget()
|
|
|
|
layout = QHBoxLayout()
|
|
|
|
layout.setMargin(0)
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
layout.setSpacing(2)
|
|
|
|
self.combo = QgsMapLayerComboBox()
|
|
|
|
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)
|
|
|
|
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-16 14:50:10 +10:00
|
|
|
self.combo.setAllowEmptyLayer(True)
|
|
|
|
|
2017-07-27 14:30:04 +10:00
|
|
|
filters = QgsMapLayerProxyModel.Filters()
|
|
|
|
if QgsProcessing.TypeVectorAny in self.param.dataTypes() or len(self.param.dataTypes()) == 0:
|
|
|
|
filters = QgsMapLayerProxyModel.VectorLayer
|
|
|
|
if QgsProcessing.TypeVectorPoint in self.param.dataTypes():
|
|
|
|
filters |= QgsMapLayerProxyModel.PointLayer
|
|
|
|
if QgsProcessing.TypeVectorLine in self.param.dataTypes():
|
|
|
|
filters |= QgsMapLayerProxyModel.LineLayer
|
|
|
|
if QgsProcessing.TypeVectorPolygon in self.param.dataTypes():
|
|
|
|
filters |= QgsMapLayerProxyModel.PolygonLayer
|
|
|
|
self.combo.setFilters(filters)
|
|
|
|
|
2016-11-16 14:50:10 +10:00
|
|
|
self.combo.setExcludedProviders(['grass'])
|
2017-03-21 10:26:58 +10:00
|
|
|
try:
|
|
|
|
if iface.activeLayer().type() == QgsMapLayer.VectorLayer:
|
|
|
|
self.combo.setLayer(iface.activeLayer())
|
|
|
|
except:
|
|
|
|
pass
|
2016-11-16 14:50:10 +10:00
|
|
|
|
|
|
|
self.combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
|
|
|
self.combo.currentTextChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
2016-11-16 14:50:10 +10:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
return BatchInputSelectionPanel(self.param, self.row, self.col, self.dialog)
|
|
|
|
else:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo = QComboBox()
|
|
|
|
self.combo.setEditable(True)
|
2017-06-27 13:16:46 +10:00
|
|
|
tables = self.dialog.getAvailableValuesOfType(QgsProcessingParameterVectorLayer, QgsProcessingOutputVectorLayer)
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo.addItem(self.NOT_SELECTED, None)
|
2016-09-07 14:30:20 +02:00
|
|
|
for table in tables:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.combo.addItem(self.dialog.resolveValueDescription(table), table)
|
|
|
|
|
|
|
|
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)
|
2016-09-07 14:30:20 +02:00
|
|
|
return widget
|
|
|
|
|
2016-11-16 14:50:10 +10:00
|
|
|
def selectFile(self):
|
|
|
|
filename, selected_filter = self.getFileName(self.combo.currentText())
|
|
|
|
if filename:
|
|
|
|
filename = dataobjects.getRasterSublayer(filename, self.param)
|
2016-11-16 15:28:27 +10:00
|
|
|
if 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)
|
2016-11-16 14:50:10 +10:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def setValue(self, value):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
|
|
|
pass # TODO
|
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
|
|
|
return self.widget.setText(value)
|
|
|
|
else:
|
2016-11-16 15:28:27 +10:00
|
|
|
self.setComboValue(value, combobox=self.combo)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def value(self):
|
|
|
|
if self.dialogType == DIALOG_STANDARD:
|
|
|
|
try:
|
2016-11-16 14:50:10 +10:00
|
|
|
layer = self.combo.currentLayer()
|
|
|
|
if layer:
|
|
|
|
return layer
|
|
|
|
else:
|
|
|
|
return self.combo.currentText()
|
2016-09-07 14:30:20 +02:00
|
|
|
except:
|
2016-11-16 14:50:10 +10:00
|
|
|
return self.combo.currentText()
|
2016-09-07 14:30:20 +02:00
|
|
|
elif self.dialogType == DIALOG_BATCH:
|
2016-11-06 13:05:32 +01:00
|
|
|
return self.widget.value()
|
2016-09-07 14:30:20 +02:00
|
|
|
else:
|
2016-09-12 07:54:55 +02:00
|
|
|
def validator(v):
|
2017-05-15 16:02:45 +10:00
|
|
|
return bool(v) or self.param.flags() & QgsProcessingParameterDefinition.FlagOptional
|
2016-11-16 15:28:27 +10:00
|
|
|
return self.comboValue(validator, combobox=self.combo)
|
2016-09-12 07:54:55 +02:00
|
|
|
|
2016-09-19 11:52:31 +03:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
class TableFieldWidgetWrapper(WidgetWrapper):
|
|
|
|
|
|
|
|
NOT_SET = '[Not set]'
|
|
|
|
|
|
|
|
def createWidget(self):
|
2016-09-18 16:07:32 +02:00
|
|
|
self._layer = None
|
|
|
|
|
2016-10-31 11:41:40 +10:00
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
2016-09-18 16:07:32 +02:00
|
|
|
return MultipleInputPanel(options=[])
|
2016-09-09 10:48:51 +02:00
|
|
|
else:
|
2016-11-14 12:36:12 +10:00
|
|
|
widget = QgsFieldComboBox()
|
2017-05-15 16:02:45 +10:00
|
|
|
widget.setAllowEmptyFieldName(self.param.flags() & QgsProcessingParameterDefinition.FlagOptional)
|
2016-12-07 11:59:35 +10:00
|
|
|
widget.fieldChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
2017-06-21 22:13:16 +10:00
|
|
|
if self.param.dataType() == QgsProcessingParameterField.Numeric:
|
2016-11-14 12:36:12 +10:00
|
|
|
widget.setFilters(QgsFieldProxyModel.Numeric)
|
2017-06-21 22:13:16 +10:00
|
|
|
elif self.param.dataType() == QgsProcessingParameterField.String:
|
2016-11-14 12:36:12 +10:00
|
|
|
widget.setFilters(QgsFieldProxyModel.String)
|
2017-06-21 22:13:16 +10:00
|
|
|
elif self.param.dataType() == QgsProcessingParameterField.DateTime:
|
2016-11-30 15:04:21 +10:00
|
|
|
widget.setFilters(QgsFieldProxyModel.Date | QgsFieldProxyModel.Time)
|
2016-09-09 10:48:51 +02:00
|
|
|
return widget
|
2016-10-31 11:41:40 +10:00
|
|
|
else:
|
|
|
|
widget = QComboBox()
|
|
|
|
widget.setEditable(True)
|
2017-06-21 22:13:16 +10:00
|
|
|
fields = self.dialog.getAvailableValuesOfType([QgsProcessingParameterField, QgsProcessingParameterString], [QgsProcessingOutputString])
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
|
2016-10-31 11:41:40 +10:00
|
|
|
widget.addItem(self.NOT_SET, None)
|
|
|
|
for f in fields:
|
|
|
|
widget.addItem(self.dialog.resolveValueDescription(f), f)
|
|
|
|
return widget
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def postInitialize(self, wrappers):
|
|
|
|
for wrapper in wrappers:
|
2017-05-15 16:02:45 +10:00
|
|
|
if wrapper.param.name() == self.param.parentLayerParameter():
|
2016-09-18 16:07:32 +02:00
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
|
|
|
self.setLayer(wrapper.value())
|
|
|
|
wrapper.widgetValueHasChanged.connect(self.parentValueChanged)
|
2016-09-07 14:30:20 +02:00
|
|
|
break
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-18 16:07:32 +02:00
|
|
|
def parentValueChanged(self, wrapper):
|
|
|
|
self.setLayer(wrapper.value())
|
|
|
|
|
|
|
|
def setLayer(self, layer):
|
2017-05-01 17:40:47 +10:00
|
|
|
context = dataobjects.createContext()
|
2017-06-06 15:21:09 +10:00
|
|
|
if isinstance(layer, QgsProcessingFeatureSourceDefinition):
|
|
|
|
layer, ok = layer.source.valueAsString(context.expressionContext())
|
2016-09-27 19:51:06 +02:00
|
|
|
if isinstance(layer, str):
|
2017-05-17 07:41:31 +10:00
|
|
|
layer = QgsProcessingUtils.mapLayerFromString(layer, context)
|
2016-09-18 16:07:32 +02:00
|
|
|
self._layer = layer
|
|
|
|
self.refreshItems()
|
|
|
|
|
|
|
|
def refreshItems(self):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
2016-09-18 16:07:32 +02:00
|
|
|
self.widget.updateForOptions(self.getFields())
|
|
|
|
else:
|
2016-11-14 12:36:12 +10:00
|
|
|
self.widget.setLayer(self._layer)
|
|
|
|
self.widget.setCurrentIndex(0)
|
2016-09-18 16:07:32 +02:00
|
|
|
|
|
|
|
def getFields(self):
|
|
|
|
if self._layer is None:
|
|
|
|
return []
|
2016-09-07 14:30:20 +02:00
|
|
|
fieldTypes = []
|
2017-06-21 22:13:16 +10:00
|
|
|
if self.param.dataType() == QgsProcessingParameterField.String:
|
2016-09-07 14:30:20 +02:00
|
|
|
fieldTypes = [QVariant.String]
|
2017-06-21 22:13:16 +10:00
|
|
|
elif self.param.dataType() == QgsProcessingParameterField.Numeric:
|
2016-09-07 14:30:20 +02:00
|
|
|
fieldTypes = [QVariant.Int, QVariant.Double, QVariant.LongLong,
|
|
|
|
QVariant.UInt, QVariant.ULongLong]
|
2017-06-21 22:13:16 +10:00
|
|
|
elif self.param.dataType() == QgsProcessingParameterField.DateTime:
|
2016-11-30 15:04:21 +10:00
|
|
|
fieldTypes = [QVariant.Date, QVariant.Time, QVariant.DateTime]
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
fieldNames = set()
|
2016-09-18 16:07:32 +02:00
|
|
|
for field in self._layer.fields():
|
2016-09-07 14:30:20 +02:00
|
|
|
if not fieldTypes or field.type() in fieldTypes:
|
2016-09-27 19:51:06 +02:00
|
|
|
fieldNames.add(str(field.name()))
|
2016-09-19 14:35:33 +02:00
|
|
|
return sorted(list(fieldNames), key=cmp_to_key(locale.strcoll))
|
2016-09-16 12:04:12 +02:00
|
|
|
|
2016-09-07 14:30:20 +02:00
|
|
|
def setValue(self, value):
|
2016-11-14 12:36:12 +10:00
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
2016-09-09 10:48:51 +02:00
|
|
|
options = self.widget.options
|
|
|
|
selected = []
|
|
|
|
for i, opt in enumerate(options):
|
|
|
|
if opt in value:
|
|
|
|
selected.append(i)
|
|
|
|
self.widget.setSelectedItems(selected)
|
|
|
|
else:
|
2016-11-14 12:36:12 +10:00
|
|
|
self.widget.setField(value)
|
2016-10-31 11:41:40 +10:00
|
|
|
else:
|
|
|
|
self.setComboValue(value)
|
2016-09-07 14:30:20 +02:00
|
|
|
|
|
|
|
def value(self):
|
2016-10-31 11:41:40 +10:00
|
|
|
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.allowMultiple():
|
2016-09-19 11:52:31 +03:00
|
|
|
return [self.widget.options[i] for i in self.widget.selectedoptions]
|
2016-09-09 10:48:51 +02:00
|
|
|
else:
|
2016-11-17 12:48:20 +10:00
|
|
|
f = self.widget.currentField()
|
2017-05-15 16:02:45 +10:00
|
|
|
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional and not f:
|
2016-09-09 10:48:51 +02:00
|
|
|
return None
|
2016-11-14 12:36:12 +10:00
|
|
|
return f
|
2016-10-31 11:41:40 +10:00
|
|
|
else:
|
|
|
|
def validator(v):
|
2017-05-15 16:02:45 +10:00
|
|
|
return bool(v) or self.param.flags() & QgsProcessingParameterDefinition.FlagOptional
|
2016-10-31 11:41:40 +10:00
|
|
|
return self.comboValue(validator)
|
2017-05-15 16:02:45 +10:00
|
|
|
|
|
|
|
|
|
|
|
class WidgetWrapperFactory:
|
2017-05-17 07:41:31 +10:00
|
|
|
|
2017-05-15 16:02:45 +10:00
|
|
|
"""
|
|
|
|
Factory for parameter widget wrappers
|
|
|
|
"""
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def create_wrapper(param, dialog, row=0, col=0):
|
|
|
|
|
2017-06-22 18:19:26 +10:00
|
|
|
if param.metadata().get('widget_wrapper', None) is not None:
|
2017-05-15 16:02:45 +10:00
|
|
|
return WidgetWrapperFactory.create_wrapper_from_metadata(param, dialog, row, col)
|
|
|
|
else:
|
|
|
|
return WidgetWrapperFactory.create_wrapper_from_class(param, dialog, row, col)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def create_wrapper_from_metadata(param, dialog, row=0, col=0):
|
2017-06-22 18:19:26 +10:00
|
|
|
wrapper = param.metadata().get('widget_wrapper', None)
|
2017-05-15 16:02:45 +10:00
|
|
|
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':
|
|
|
|
wrapper = BooleanWidgetWrapper
|
|
|
|
elif param.type() == 'crs':
|
|
|
|
wrapper = CrsWidgetWrapper
|
|
|
|
elif param.type() == 'extent':
|
|
|
|
wrapper = ExtentWidgetWrapper
|
|
|
|
elif param.type() == 'point':
|
|
|
|
wrapper = PointWidgetWrapper
|
|
|
|
elif param.type() == 'file':
|
|
|
|
wrapper = FileWidgetWrapper
|
|
|
|
elif param.type() == 'multilayer':
|
|
|
|
wrapper = MultipleInputWidgetWrapper
|
|
|
|
elif param.type() == 'number':
|
|
|
|
wrapper = NumberWidgetWrapper
|
|
|
|
elif param.type() == 'raster':
|
|
|
|
wrapper = RasterWidgetWrapper
|
|
|
|
elif param.type() == 'enum':
|
|
|
|
wrapper = SelectionWidgetWrapper
|
|
|
|
elif param.type() == 'string':
|
|
|
|
wrapper = StringWidgetWrapper
|
|
|
|
elif param.type() == 'expression':
|
|
|
|
wrapper = ExpressionWidgetWrapper
|
2017-06-21 22:14:39 +10:00
|
|
|
elif param.type() == 'vector':
|
2017-05-15 16:02:45 +10:00
|
|
|
wrapper = TableWidgetWrapper
|
|
|
|
elif param.type() == 'field':
|
|
|
|
wrapper = TableFieldWidgetWrapper
|
2017-06-05 11:15:17 +10:00
|
|
|
elif param.type() == 'source':
|
2017-05-15 16:02:45 +10:00
|
|
|
wrapper = VectorWidgetWrapper
|
|
|
|
else:
|
|
|
|
assert False, param.type()
|
|
|
|
return wrapper(param, dialog, row, col)
|