diff --git a/python/plugins/processing/core/GeoAlgorithm.py b/python/plugins/processing/core/GeoAlgorithm.py index d76f7dde53d..bb10aa110c5 100644 --- a/python/plugins/processing/core/GeoAlgorithm.py +++ b/python/plugins/processing/core/GeoAlgorithm.py @@ -199,7 +199,7 @@ class GeoAlgorithm(object): self.setOutputCRS() self.resolveTemporaryOutputs() self.resolveDataObjects() - self.resolveMinCoveringExtent() + self.evaluateParameterValues() self.checkOutputFileExtensions() self.runPreExecutionScript(progress) self.processAlgorithm(progress) @@ -207,7 +207,7 @@ class GeoAlgorithm(object): self.convertUnsupportedFormats(progress) self.runPostExecutionScript(progress) except GeoAlgorithmExecutionException as gaee: - lines = [self.tr('Uncaught error while executing algorithm')] + lines = [self.tr('Error while executing algorithm')] lines.append(traceback.format_exc()) ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, gaee.msg) raise GeoAlgorithmExecutionException(gaee.msg, lines, gaee) @@ -340,11 +340,9 @@ class GeoAlgorithm(object): if not os.path.isabs(out.value): continue if isinstance(out, OutputRaster): - exts = \ - dataobjects.getSupportedOutputRasterLayerExtensions() + exts = dataobjects.getSupportedOutputRasterLayerExtensions() elif isinstance(out, OutputVector): - exts = \ - dataobjects.getSupportedOutputVectorLayerExtensions() + exts = dataobjects.getSupportedOutputVectorLayerExtensions() elif isinstance(out, OutputTable): exts = dataobjects.getSupportedOutputTableExtensions() elif isinstance(out, OutputHTML): @@ -360,60 +358,12 @@ class GeoAlgorithm(object): out.value = out.value + '.' + exts[0] - def canUseAutoExtent(self): + def evaluateParameterValues(self): for param in self.parameters: - if isinstance(param, (ParameterRaster, ParameterVector)): - return True - if isinstance(param, ParameterMultipleInput): - return True - return False - - def resolveMinCoveringExtent(self): - for param in self.parameters: - if isinstance(param, ParameterExtent): - if param.value is None: - param.value = self.getMinCoveringExtent() - - def getMinCoveringExtent(self): - first = True - found = False - for param in self.parameters: - if param.value: - if isinstance(param, (ParameterRaster, ParameterVector)): - if isinstance(param.value, (QgsRasterLayer, - QgsVectorLayer)): - layer = param.value - else: - layer = dataobjects.getObject(param.value) - if layer: - found = True - self.addToRegion(layer, first) - first = False - elif isinstance(param, ParameterMultipleInput): - layers = param.value.split(';') - for layername in layers: - layer = dataobjects.getObject(layername) - if layer: - found = True - self.addToRegion(layer, first) - first = False - if found: - return '{},{},{},{}'.format( - self.xmin, self.xmax, self.ymin, self.ymax) - else: - return None - - def addToRegion(self, layer, first): - if first: - self.xmin = layer.extent().xMinimum() - self.xmax = layer.extent().xMaximum() - self.ymin = layer.extent().yMinimum() - self.ymax = layer.extent().yMaximum() - else: - self.xmin = min(self.xmin, layer.extent().xMinimum()) - self.xmax = max(self.xmax, layer.extent().xMaximum()) - self.ymin = min(self.ymin, layer.extent().yMinimum()) - self.ymax = max(self.ymax, layer.extent().yMaximum()) + try: + param.evaluate(self) + except ValueError, e: + raise GeoAlgorithmExecutionException(str(e)) def resolveTemporaryOutputs(self): """Sets temporary outputs (output.value = None) with a diff --git a/python/plugins/processing/core/parameters.py b/python/plugins/processing/core/parameters.py index c53aaa4f0fd..d38bc933155 100644 --- a/python/plugins/processing/core/parameters.py +++ b/python/plugins/processing/core/parameters.py @@ -33,11 +33,12 @@ import os from inspect import isclass from copy import deepcopy - +from qgis.utils import iface from qgis.PyQt.QtCore import QCoreApplication -from qgis.core import QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsCoordinateReferenceSystem +from qgis.core import (QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsCoordinateReferenceSystem, + QgsExpressionContext, QgsExpressionContextUtils, QgsExpression, QgsExpressionContextScope) + from processing.tools.vector import resolveFieldIndex, features -from processing.tools.system import isWindows from processing.tools import dataobjects def parseBool(s): @@ -58,7 +59,47 @@ def _splitParameterOptions(line): def _createDescriptiveName(s): return s.replace('_', ' ') -class Parameter(object): +def _expressionContext(): + context = QgsExpressionContext() + context.appendScope(QgsExpressionContextUtils.globalScope()) + context.appendScope(QgsExpressionContextUtils.projectScope()) + processingScope = QgsExpressionContextScope() + layers = dataobjects.getAllLayers() + for layer in layers: + name = layer.name() + processingScope.setVariable('%s_minx' % name, layer.extent().xMinimum()) + processingScope.setVariable('%s_miny' % name, layer.extent().yMinimum()) + processingScope.setVariable('%s_maxx' % name, layer.extent().xMaximum()) + processingScope.setVariable('%s_maxy' % name, layer.extent().yMaximum()) + if isinstance(layer, QgsRasterLayer): + cellsize = (layer.extent().xMaximum() + - layer.extent().xMinimum()) / layer.width() + processingScope.setVariable('%s_cellsize' % name, cellsize) + + layers = dataobjects.getRasterLayers() + for layer in layers: + for i in range(layer.bandCount()): + stats = layer.dataProvider().bandStatistics(i + 1) + processingScope.setVariable('%s_band%i_avg' % (name, i + 1), stats.mean) + processingScope.setVariable('%s_band%i_stddev' % (name, i + 1), stats.stdDev) + processingScope.setVariable('%s_band%i_min' % (name, i + 1), stats.minimumValue) + processingScope.setVariable('%s_band%i_max' % (name, i + 1), stats.maximumValue) + + extent = iface.mapCanvas().extent() + processingScope.setVariable('canvasextent_minx', extent.xMinimum()) + processingScope.setVariable('canvasextent_miny', extent.yMinimum()) + processingScope.setVariable('canvasextent_maxx', extent.xMaximum()) + processingScope.setVariable('canvasextent_maxy', extent.yMaximum()) + + extent = iface.mapCanvas().fullExtent() + processingScope.setVariable('fullextent_minx', extent.xMinimum()) + processingScope.setVariable('fullextent_miny', extent.yMinimum()) + processingScope.setVariable('fullextent_maxx', extent.xMaximum()) + processingScope.setVariable('fullextent_maxy', extent.yMaximum()) + context.appendScope(processingScope) + return context + +class Parameter: """ Base class for all parameters that a geoalgorithm might @@ -148,6 +189,9 @@ class Parameter(object): wrapper = wrapper(self, dialog, row, col) # or a wrapper instance return wrapper + + def evaluate(self, alg): + pass class ParameterBoolean(Parameter): @@ -330,6 +374,51 @@ class ParameterExtent(Parameter): default = definition.strip()[len('extent') + 1:] or None return ParameterExtent(name, descName, default, isOptional) + def evaluate(self, alg): + if self.optional and not bool(self.value): + self.value = self.getMinCoveringExtent() + + def getMinCoveringExtent(self, alg): + first = True + found = False + for param in alg.parameters: + if param.value: + if isinstance(param, (ParameterRaster, ParameterVector)): + if isinstance(param.value, (QgsRasterLayer, + QgsVectorLayer)): + layer = param.value + else: + layer = dataobjects.getObject(param.value) + if layer: + found = True + self.addToRegion(layer, first) + first = False + elif isinstance(param, ParameterMultipleInput): + layers = param.value.split(';') + for layername in layers: + layer = dataobjects.getObject(layername) + if layer: + found = True + self.addToRegion(layer, first) + first = False + if found: + return '{},{},{},{}'.format( + self.xmin, self.xmax, self.ymin, self.ymax) + else: + return None + + def addToRegion(self, layer, first): + if first: + self.xmin = layer.extent().xMinimum() + self.xmax = layer.extent().xMaximum() + self.ymin = layer.extent().yMinimum() + self.ymax = layer.extent().yMaximum() + else: + self.xmin = min(self.xmin, layer.extent().xMinimum()) + self.xmax = max(self.xmax, layer.extent().xMaximum()) + self.ymin = min(self.ymin, layer.extent().yMinimum()) + self.ymax = max(self.ymax, layer.extent().yMaximum()) + class ParameterPoint(Parameter): @@ -715,21 +804,30 @@ class ParameterNumber(Parameter): self.value = None return True - try: - if float(n) - int(float(n)) == 0: - value = int(float(n)) - else: - value = float(n) - if self.min is not None: - if value < self.min: - return False - if self.max is not None: - if value > self.max: - return False - self.value = value - return True - except: - return False + if isinstance(n, basestring): + try: + v = self._evaluate(n) + float(v) + self.value = n + return True + except: + return False + else: + try: + if float(n) - int(float(n)) == 0: + value = int(float(n)) + else: + value = float(n) + if self.min is not None: + if value < self.min: + return False + if self.max is not None: + if value > self.max: + return False + self.value = value + return True + except: + return False def getAsScriptCode(self): param_type = '' @@ -745,6 +843,31 @@ class ParameterNumber(Parameter): if definition.lower().strip().startswith('number'): default = definition.strip()[len('number') + 1:] or None return ParameterNumber(name, descName, default=default, optional=isOptional) + + def _evaluate(self, v): + exp = QgsExpression(v) + if exp.hasParserError(): + raise ValueError(self.tr("Error in parameter expression: ") + exp.parserErrorString()) + result = exp.evaluate(_expressionContext()) + if exp.hasEvalError(): + raise ValueError("Error evaluating parameter expression: " + exp.evalErrorString()) + return result + + def evaluate(self, alg): + if isinstance(self.value, basestring): + self.value = self._evaluate(self.value) + + def expressionContext(self): + return _expressionContext() + + def getValueAsCommandLineParameter(self): + if self.value is None: + return str(None) + if isinstance(self.value, basestring): + return '"%s"' % self.value + return str(self.value) + + class ParameterRange(Parameter): @@ -919,6 +1042,13 @@ class ParameterSelection(Parameter): return ParameterSelection(name, descName, options, optional=isOptional) +class ParameterEvaluationException(Exception): + + def __init__(self, param, msg): + Exception.__init__(msg) + self.param = param + + class ParameterString(Parameter): default_metadata = { @@ -976,6 +1106,18 @@ class ParameterString(Parameter): return ParameterString(name, descName, default, multiline=True, optional=isOptional) else: return ParameterString(name, descName, multiline=True, optional=isOptional) + + def evaluate(self, alg): + exp = QgsExpression(self.value) + if exp.hasParserError(): + raise ValueError(self.tr("Error in parameter expression: ") + exp.parserErrorString()) + result = exp.evaluate(_expressionContext()) + if exp.hasEvalError(): + raise ValueError("Error evaluating parameter expression: " + exp.evalErrorString()) + self.value = result + + def expressionContext(self): + return _expressionContext() class ParameterTable(ParameterDataObject): diff --git a/python/plugins/processing/gui/AlgorithmDialog.py b/python/plugins/processing/gui/AlgorithmDialog.py index 7ad7a0df4c2..c2d400d5a41 100644 --- a/python/plugins/processing/gui/AlgorithmDialog.py +++ b/python/plugins/processing/gui/AlgorithmDialog.py @@ -31,7 +31,7 @@ from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QMessageBox, QApplication, QPushButton, QWidget, QVBoxLayout from qgis.PyQt.QtGui import QCursor, QColor, QPalette -from qgis.core import QgsMapLayerRegistry, QgsExpressionContext, QgsExpressionContextUtils, QgsExpression +from qgis.core import QgsMapLayerRegistry from processing.core.ProcessingLog import ProcessingLog from processing.core.ProcessingConfig import ProcessingConfig @@ -62,8 +62,6 @@ from processing.core.outputs import OutputRaster from processing.core.outputs import OutputVector from processing.core.outputs import OutputTable -from processing.tools import dataobjects - class AlgorithmDialog(AlgorithmDialogBase): @@ -114,18 +112,6 @@ class AlgorithmDialog(AlgorithmDialogBase): return True - def evaluateExpression(self, text): - context = QgsExpressionContext() - context.appendScope(QgsExpressionContextUtils.globalScope()) - context.appendScope(QgsExpressionContextUtils.projectScope()) - exp = QgsExpression(text) - if exp.hasParserError(): - raise Exception(exp.parserErrorString()) - result = exp.evaluate(context) - if exp.hasEvalError(): - raise ValueError(exp.evalErrorString()) - return result - def setParamValue(self, param, wrapper, alg=None): return param.setValue(wrapper.value()) diff --git a/python/plugins/processing/gui/NumberInputDialog.py b/python/plugins/processing/gui/NumberInputDialog.py deleted file mode 100644 index cc35eaacf81..00000000000 --- a/python/plugins/processing/gui/NumberInputDialog.py +++ /dev/null @@ -1,153 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -*************************************************************************** - NumberInputDialog.py - --------------------- - Date : August 2012 - Copyright : (C) 2012 by Victor Olaya - Email : volayaf at gmail dot com -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -*************************************************************************** -""" -from builtins import str -from builtins import range - -__author__ = 'Victor Olaya' -__date__ = 'August 2012' -__copyright__ = '(C) 2012, Victor Olaya' - -# This will get replaced with a git SHA1 when you do a git archive - -__revision__ = '$Format:%H$' - -import os - -from qgis.PyQt import uic -from qgis.PyQt.QtWidgets import QDialog, QTreeWidgetItem, QMessageBox -from qgis.core import QgsRasterLayer - -from qgis.utils import iface -from processing.tools import dataobjects - -pluginPath = os.path.split(os.path.dirname(__file__))[0] -WIDGET, BASE = uic.loadUiType( - os.path.join(pluginPath, 'ui', 'DlgNumberInput.ui')) - - -class NumberInputDialog(BASE, WIDGET): - - def __init__(self, isInteger): - super(NumberInputDialog, self).__init__(None) - self.setupUi(self) - - if hasattr(self.leFormula, 'setPlaceholderText'): - self.leFormula.setPlaceholderText( - self.tr('[Enter your formula here]')) - - self.treeValues.doubleClicked.connect(self.addValue) - - self.value = None - self.isInteger = isInteger - - if not self.isInteger: - self.lblWarning.hide() - - self.fillTree() - - def fillTree(self): - layersItem = QTreeWidgetItem() - layersItem.setText(0, self.tr('Values from data layers extents')) - self.treeValues.addTopLevelItem(layersItem) - layers = dataobjects.getAllLayers() - for layer in layers: - layerItem = QTreeWidgetItem() - layerItem.setText(0, str(layer.name())) - layerItem.addChild(TreeValueItem(self.tr('Min X'), - layer.extent().xMinimum())) - layerItem.addChild(TreeValueItem(self.tr('Max X'), - layer.extent().xMaximum())) - layerItem.addChild(TreeValueItem(self.tr('Min Y'), - layer.extent().yMinimum())) - layerItem.addChild(TreeValueItem(self.tr('Max Y'), - layer.extent().yMaximum())) - if isinstance(layer, QgsRasterLayer): - cellsize = (layer.extent().xMaximum() - - layer.extent().xMinimum()) / layer.width() - layerItem.addChild(TreeValueItem(self.tr('Cellsize'), - cellsize)) - layersItem.addChild(layerItem) - - layersItem = QTreeWidgetItem() - layersItem.setText(0, self.tr('Values from raster layers statistics')) - self.treeValues.addTopLevelItem(layersItem) - layers = dataobjects.getRasterLayers() - for layer in layers: - for i in range(layer.bandCount()): - stats = layer.dataProvider().bandStatistics(i + 1) - layerItem = QTreeWidgetItem() - layerItem.setText(0, str(layer.name())) - layerItem.addChild(TreeValueItem(self.tr('Mean'), stats.mean)) - layerItem.addChild(TreeValueItem(self.tr('Std. deviation'), - stats.stdDev)) - layerItem.addChild(TreeValueItem(self.tr('Max value'), - stats.maximumValue)) - layerItem.addChild(TreeValueItem(self.tr('Min value'), - stats.minimumValue)) - layersItem.addChild(layerItem) - - canvasItem = QTreeWidgetItem() - canvasItem.setText(0, self.tr('Values from QGIS map canvas')) - self.treeValues.addTopLevelItem(canvasItem) - extent = iface.mapCanvas().extent() - extentItem = QTreeWidgetItem() - extentItem.setText(0, self.tr('Current extent')) - extentItem.addChild(TreeValueItem(self.tr('Min X'), extent.xMinimum())) - extentItem.addChild(TreeValueItem(self.tr('Max X'), extent.xMaximum())) - extentItem.addChild(TreeValueItem(self.tr('Min Y'), extent.yMinimum())) - extentItem.addChild(TreeValueItem(self.tr('Max Y'), extent.yMaximum())) - canvasItem.addChild(extentItem) - - extent = iface.mapCanvas().fullExtent() - extentItem = QTreeWidgetItem() - extentItem.setText(0, - self.tr('Full extent of all layers in map canvas')) - extentItem.addChild(TreeValueItem(self.tr('Min X'), extent.xMinimum())) - extentItem.addChild(TreeValueItem(self.tr('Max X'), extent.xMaximum())) - extentItem.addChild(TreeValueItem(self.tr('Min Y'), extent.yMinimum())) - extentItem.addChild(TreeValueItem(self.tr('Max Y'), extent.yMaximum())) - canvasItem.addChild(extentItem) - - def addValue(self): - item = self.treeValues.currentItem() - if isinstance(item, TreeValueItem): - formula = self.leFormula.text() + ' ' + str(item.value) - self.leFormula.setText(formula.strip()) - - def accept(self): - try: - self.value = float(eval(str(self.leFormula.text()))) - if self.isInteger: - self.value = int(round(self.value)) - QDialog.accept(self) - except: - QMessageBox.critical(self, self.tr('Wrong expression'), - self.tr('The expression entered is not correct')) - - def reject(self): - self.value = None - QDialog.reject(self) - - -class TreeValueItem(QTreeWidgetItem): - - def __init__(self, name, value): - QTreeWidgetItem.__init__(self) - self.value = value - self.setText(0, name + ': ' + str(value)) diff --git a/python/plugins/processing/gui/NumberInputPanel.py b/python/plugins/processing/gui/NumberInputPanel.py index 3c3c55a3472..d00a3f2bde6 100644 --- a/python/plugins/processing/gui/NumberInputPanel.py +++ b/python/plugins/processing/gui/NumberInputPanel.py @@ -32,131 +32,44 @@ from qgis.PyQt import uic from qgis.PyQt.QtCore import pyqtSignal from qgis.PyQt.QtWidgets import QDialog -from math import log10, floor from qgis.core import (QgsDataSourceUri, QgsCredentials, - QgsExpressionContext, - QgsExpressionContextUtils, QgsExpression, - QgsRasterLayer, - QgsExpressionContextScope) + QgsRasterLayer) from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog from qgis.utils import iface -from processing.tools import dataobjects pluginPath = os.path.split(os.path.dirname(__file__))[0] WIDGET, BASE = uic.loadUiType( - os.path.join(pluginPath, 'ui', 'widgetNumberSelector.ui')) + os.path.join(pluginPath, 'ui', 'widgetBaseSelector.ui')) class NumberInputPanel(BASE, WIDGET): hasChanged = pyqtSignal() - def __init__(self, number, minimum, maximum, isInteger): + def __init__(self, param): super(NumberInputPanel, self).__init__(None) self.setupUi(self) - self.spnValue.setExpressionsEnabled(True) - self.isInteger = isInteger - if self.isInteger: - self.spnValue.setDecimals(0) - else: - # Guess reasonable step value - if (maximum == 0 or maximum) and (minimum == 0 or minimum): - self.spnValue.setSingleStep(self.calculateStep(minimum, maximum)) + self.param = param + self.text = param.default - if maximum == 0 or maximum: - self.spnValue.setMaximum(maximum) - else: - self.spnValue.setMaximum(99999999) - if minimum == 0 or minimum: - self.spnValue.setMinimum(minimum) - else: - self.spnValue.setMinimum(-99999999) - - # Set default value - if number == 0 or number: - self.spnValue.setValue(float(number)) - self.spnValue.setClearValue(float(number)) - elif minimum == 0 or minimum: - self.spnValue.setValue(float(minimum)) - self.spnValue.setClearValue(float(minimum)) - else: - self.spnValue.setValue(0) - self.spnValue.setClearValue(0) - - self.btnCalc.setFixedHeight(self.spnValue.height()) - - self.btnCalc.clicked.connect(self.showExpressionsBuilder) - - self.spnValue.valueChanged.connect(lambda: self.hasChanged.emit()) + self.btnSelect.clicked.connect(self.showExpressionsBuilder) + self.leText.textChanged.connect(lambda: self.hasChanged.emit()) def showExpressionsBuilder(self): - context = self.expressionContext() - dlg = QgsExpressionBuilderDialog(None, self.spnValue.text(), self, 'generic', context) + context = self.param.expressionContext() + dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, 'generic', context) dlg.setWindowTitle(self.tr('Expression based input')) if dlg.exec_() == QDialog.Accepted: exp = QgsExpression(dlg.expressionText()) if not exp.hasParserError(): - result = exp.evaluate(context) - if not exp.hasEvalError(): - try: - self.spnValue.setValue(float(result)) - except: - pass - - def expressionContext(self): - context = QgsExpressionContext() - context.appendScope(QgsExpressionContextUtils.globalScope()) - context.appendScope(QgsExpressionContextUtils.projectScope()) - processingScope = QgsExpressionContextScope() - layers = dataobjects.getAllLayers() - for layer in layers: - name = layer.name() - processingScope.setVariable('%s_minx' % name, layer.extent().xMinimum()) - processingScope.setVariable('%s_miny' % name, layer.extent().yMinimum()) - processingScope.setVariable('%s_maxx' % name, layer.extent().xMaximum()) - processingScope.setVariable('%s_maxy' % name, layer.extent().yMaximum()) - if isinstance(layer, QgsRasterLayer): - cellsize = (layer.extent().xMaximum() - - layer.extent().xMinimum()) / layer.width() - processingScope.setVariable('%s_cellsize' % name, cellsize) - - layers = dataobjects.getRasterLayers() - for layer in layers: - for i in range(layer.bandCount()): - stats = layer.dataProvider().bandStatistics(i + 1) - processingScope.setVariable('%s_band%i_avg' % (name, i + 1), stats.mean) - processingScope.setVariable('%s_band%i_stddev' % (name, i + 1), stats.stdDev) - processingScope.setVariable('%s_band%i_min' % (name, i + 1), stats.minimumValue) - processingScope.setVariable('%s_band%i_max' % (name, i + 1), stats.maximumValue) - - extent = iface.mapCanvas().extent() - processingScope.setVariable('canvasextent_minx', extent.xMinimum()) - processingScope.setVariable('canvasextent_miny', extent.yMinimum()) - processingScope.setVariable('canvasextent_maxx', extent.xMaximum()) - processingScope.setVariable('canvasextent_maxy', extent.yMaximum()) - - extent = iface.mapCanvas().fullExtent() - processingScope.setVariable('fullextent_minx', extent.xMinimum()) - processingScope.setVariable('fullextent_miny', extent.yMinimum()) - processingScope.setVariable('fullextent_maxx', extent.xMaximum()) - processingScope.setVariable('fullextent_maxy', extent.yMaximum()) - context.appendScope(processingScope) - return context + self.setValue(dlg.expressionText()) + def getValue(self): - return self.spnValue.value() + return self.leText.text() def setValue(self, value): - self.spnValue.setValue(value) - - def calculateStep(self, minimum, maximum): - valueRange = maximum - minimum - if valueRange <= 1.0: - step = valueRange / 10.0 - # round to 1 significant figure - return round(step, -int(floor(log10(step)))) - else: - return 1.0 + self.leText.setText(unicode(value)) diff --git a/python/plugins/processing/gui/StringInputPanel.py b/python/plugins/processing/gui/StringInputPanel.py new file mode 100644 index 00000000000..b5ec19b7af5 --- /dev/null +++ b/python/plugins/processing/gui/StringInputPanel.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + NumberInputPanel.py + --------------------- + Date : August 2016 + Copyright : (C) 2016 by Victor Olaya + Email : volayaf at gmail dot com +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Victor Olaya' +__date__ = 'August 2016' +__copyright__ = '(C) 2016, Victor Olaya' + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os + +from qgis.PyQt import uic +from qgis.PyQt.QtCore import pyqtSignal +from qgis.PyQt.QtWidgets import QDialog + +from qgis.core import (QgsDataSourceUri, + QgsCredentials, + QgsExpression, + QgsRasterLayer) +from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog +from qgis.utils import iface + +pluginPath = os.path.split(os.path.dirname(__file__))[0] +WIDGET, BASE = uic.loadUiType( + os.path.join(pluginPath, 'ui', 'widgetBaseSelector.ui')) + + +class StringInputPanel(BASE, WIDGET): + + hasChanged = pyqtSignal() + + def __init__(self, param): + super(StringInputPanel, self).__init__(None) + self.setupUi(self) + + self.param = param + self.text = param.default + + self.btnSelect.clicked.connect(self.showExpressionsBuilder) + self.leText.textChanged.connect(lambda: self.hasChanged.emit()) + + def showExpressionsBuilder(self): + context = self.param.expressionContext() + dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, '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()) + + + def getValue(self): + return self.leText.text() + + def setValue(self, value): + self.leText.setText(unicode(value)) diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index bd58e86c1d8..f9b804ccb3e 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -50,6 +50,7 @@ from processing.gui.MultipleInputPanel import MultipleInputPanel from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel from processing.gui.FixedTablePanel import FixedTablePanel from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel +from processing.gui.StringInputPanel import StringInputPanel DIALOG_STANDARD = 'standard' @@ -442,8 +443,7 @@ class NumberWidgetWrapper(WidgetWrapper): def createWidget(self): if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH): - return NumberInputPanel(self.param.default, self.param.min, self.param.max, - self.param.isInteger) + return NumberInputPanel(self.param) else: widget = QComboBox() widget.setEditable(True) @@ -605,9 +605,9 @@ class StringWidgetWrapper(WidgetWrapper): if self.param.default: widget.setPlainText(self.param.default) else: - widget = QLineEdit() + widget = StringInputPanel(self.param) if self.param.default: - widget.setText(self.param.default) + widget.setValue(self.param.default) elif self.dialogType == DIALOG_BATCH: widget = QLineEdit() if self.param.default: @@ -642,22 +642,10 @@ class StringWidgetWrapper(WidgetWrapper): if self.param.multiline: text = self.widget.toPlainText() else: - text = self.widget.text() - - if self.param.evaluateExpressions: - try: - text = self.evaluateExpression(text) - except: - pass + text = self.widget.getValue() return text if self.dialogType == DIALOG_BATCH: text = self.widget.text() - if self.param.evaluateExpressions: - try: - text = self.evaluateExpression(text) - except: - pass - return text else: if self.param.multiline: value = self.widget.getValue() diff --git a/python/plugins/processing/ui/widgetNumberSelector.ui b/python/plugins/processing/ui/widgetNumberSelector.ui deleted file mode 100644 index e5d88ff54b1..00000000000 --- a/python/plugins/processing/ui/widgetNumberSelector.ui +++ /dev/null @@ -1,58 +0,0 @@ - - - Form - - - - 0 - 0 - 251 - 23 - - - - Form - - - - 2 - - - 0 - - - - - 6 - - - -99999999.999999001622200 - - - 99999999.999999001622200 - - - - - - - Open number input dialog - - - ... - - - - - - - - QgsDoubleSpinBox - QDoubleSpinBox -
qgis.gui
- 1 -
-
- - -