Merge branch 'processing_exps' of https://github.com/volaya/QGIS into processing_exps

Conflicts:
	python/plugins/processing/gui/NumberInputPanel.py
	python/plugins/processing/gui/OutputSelectionPanel.py
This commit is contained in:
Alexander Bruy 2016-05-13 09:26:55 +03:00
commit 730c5806aa
5 changed files with 152 additions and 17 deletions

View File

@ -29,7 +29,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
from qgis.core import QgsMapLayerRegistry, QgsExpressionContext, QgsExpressionContextUtils, QgsExpression
from processing.core.ProcessingLog import ProcessingLog
from processing.core.ProcessingConfig import ProcessingConfig
@ -102,8 +102,8 @@ class AlgorithmDialog(AlgorithmDialogBase):
continue
if not self.setParamValue(
param, self.mainWidget.valueItems[param.name]):
raise AlgorithmDialogBase.InvalidParameterValue(param,
self.mainWidget.valueItems[param.name])
raise AlgorithmDialogBase.InvalidParameterValue(
param, self.mainWidget.valueItems[param.name])
for param in params:
if isinstance(param, ParameterExtent):
@ -121,6 +121,19 @@ 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, widget, alg=None):
if isinstance(param, ParameterRaster):
return param.setValue(widget.getValue())
@ -159,7 +172,12 @@ class AlgorithmDialog(AlgorithmDialogBase):
if param.multiline:
return param.setValue(unicode(widget.toPlainText()))
else:
return param.setValue(unicode(widget.text()))
text = widget.text()
try:
text = self.evaluateExpression(text)
except:
return False
return param.setValue(text)
elif isinstance(param, ParameterGeometryPredicate):
return param.setValue(widget.value())
else:

View File

@ -29,9 +29,15 @@ import os
from qgis.PyQt import uic
from qgis.PyQt.QtCore import pyqtSignal
from PyQt.QtGui import QDialog
from math import log10, floor
from processing.gui.NumberInputDialog import NumberInputDialog
from qgis.core import (QgsDataSourceURI, QgsCredentials, QgsExpressionContext,
QgsExpressionContextUtils, QgsExpression, QgsRasterLayer,
QgsExpressionContextScope)
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(
@ -46,6 +52,7 @@ class NumberInputPanel(BASE, WIDGET):
super(NumberInputPanel, self).__init__(None)
self.setupUi(self)
self.spnValue.setExpressionsEnabled(True)
self.isInteger = isInteger
if self.isInteger:
self.spnValue.setDecimals(0)
@ -74,15 +81,65 @@ class NumberInputPanel(BASE, WIDGET):
self.spnValue.setValue(0)
self.spnValue.setClearValue(0)
self.btnCalc.clicked.connect(self.showNumberInputDialog)
self.btnCalc.setFixedHeight(self.spnValue.height())
self.btnCalc.clicked.connect(self.showExpressionsBuilder)
self.spnValue.valueChanged.connect(lambda: self.hasChanged.emit())
def showNumberInputDialog(self):
dlg = NumberInputDialog(self.isInteger)
dlg.exec_()
if dlg.value is not None:
self.spnValue.setValue(dlg.value)
def showExpressionsBuilder(self):
context = self.expressionContext()
dlg = QgsExpressionBuilderDialog(None, self.spnValue.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
def getValue(self):
return self.spnValue.value()

View File

@ -32,8 +32,9 @@ from qgis.PyQt import uic
from qgis.PyQt.QtCore import QCoreApplication, QSettings
from qgis.PyQt.QtWidgets import QDialog, QMenu, QAction, QFileDialog
from qgis.PyQt.QtGui import QCursor
from qgis.gui import QgsEncodingFileDialog
from qgis.core import QgsDataSourceURI, QgsCredentials
from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog
from qgis.core import QgsDataSourceURI, QgsCredentials, QgsExpressionContext,\
QgsExpressionContextUtils, QgsExpression, QgsExpressionContextScope
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.outputs import OutputVector
@ -78,6 +79,11 @@ class OutputSelectionPanel(BASE, WIDGET):
actionSaveToFile.triggered.connect(self.selectFile)
popupMenu.addAction(actionSaveToFile)
actionShowExpressionsBuilder = QAction(
self.tr('Use expression...'), self.btnSelect)
actionShowExpressionsBuilder.triggered.connect(self.showExpressionsBuilder)
popupMenu.addAction(actionShowExpressionsBuilder)
if isinstance(self.output, OutputVector) \
and self.alg.provider.supportsNonFileBasedOutput():
actionSaveToMemory = QAction(
@ -100,6 +106,22 @@ class OutputSelectionPanel(BASE, WIDGET):
popupMenu.exec_(QCursor.pos())
def showExpressionsBuilder(self):
dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, "generic", self.expressionContext())
dlg.setWindowTitle(self.tr("Expression based output"));
if dlg.exec_() == QDialog.Accepted:
self.leText.setText(dlg.expressionText())
def expressionContext(self):
context = QgsExpressionContext()
context.appendScope(QgsExpressionContextUtils.globalScope())
context.appendScope(QgsExpressionContextUtils.projectScope())
processingScope = QgsExpressionContextScope()
for param in self.ag.parameters:
processingScope.setVariable("%s_value" % param.name, "")
context.appendScope(processingScope)
return context
def saveToTemporaryFile(self):
self.leText.setText('')
@ -202,6 +224,12 @@ class OutputSelectionPanel(BASE, WIDGET):
def getValue(self):
fileName = unicode(self.leText.text())
context = self.expressionContext()
exp = QgsExpression(fileName)
if not exp.hasParserError():
result = exp.evaluate(context)
if not exp.hasEvalError():
fileName = result
if fileName.strip() in ['', self.SAVE_TO_TEMP_FILE]:
value = None
elif fileName.startswith('memory:'):

View File

@ -21,10 +21,23 @@
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="leText"/>
<widget class="QLineEdit" name="leText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnSelect">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>250</width>
<height>23</height>
<width>608</width>
<height>20</height>
</rect>
</property>
<property name="windowTitle">
@ -21,10 +21,23 @@
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="cmbText"/>
<widget class="QComboBox" name="cmbText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnSelect">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
@ -32,6 +45,12 @@
</item>
<item>
<widget class="QToolButton" name="btnIterate">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Iterate over this layer</string>
</property>