Skip to content
Permalink
Browse files
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
  • Loading branch information
alexbruy committed May 13, 2016
2 parents b51d70a + 2535c0a commit 730c580
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 17 deletions.
@@ -29,7 +29,7 @@
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 @@ def setParamValues(self):
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 @@ def setParamValues(self):

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 @@ def setParamValue(self, param, widget, alg=None):
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:
@@ -29,9 +29,15 @@

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 @@ def __init__(self, number, minimum, maximum, isInteger):
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 @@ def __init__(self, number, minimum, maximum, isInteger):
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()
@@ -32,8 +32,9 @@
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 @@ def selectOutput(self):
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 @@ def selectOutput(self):

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 @@ def selectDirectory(self):

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:'):
@@ -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>
@@ -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,17 +21,36 @@
<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>
</widget>
</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>

0 comments on commit 730c580

Please sign in to comment.