Skip to content

Commit 730c580

Browse files
committedMay 13, 2016
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
2 parents b51d70a + 2535c0a commit 730c580

File tree

5 files changed

+152
-17
lines changed

5 files changed

+152
-17
lines changed
 

‎python/plugins/processing/gui/AlgorithmDialog.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from qgis.PyQt.QtWidgets import QMessageBox, QApplication, QPushButton, QWidget, QVBoxLayout
3030
from qgis.PyQt.QtGui import QCursor, QColor, QPalette
3131

32-
from qgis.core import QgsMapLayerRegistry
32+
from qgis.core import QgsMapLayerRegistry, QgsExpressionContext, QgsExpressionContextUtils, QgsExpression
3333

3434
from processing.core.ProcessingLog import ProcessingLog
3535
from processing.core.ProcessingConfig import ProcessingConfig
@@ -102,8 +102,8 @@ def setParamValues(self):
102102
continue
103103
if not self.setParamValue(
104104
param, self.mainWidget.valueItems[param.name]):
105-
raise AlgorithmDialogBase.InvalidParameterValue(param,
106-
self.mainWidget.valueItems[param.name])
105+
raise AlgorithmDialogBase.InvalidParameterValue(
106+
param, self.mainWidget.valueItems[param.name])
107107

108108
for param in params:
109109
if isinstance(param, ParameterExtent):
@@ -121,6 +121,19 @@ def setParamValues(self):
121121

122122
return True
123123

124+
def evaluateExpression(self, text):
125+
context = QgsExpressionContext()
126+
context.appendScope(QgsExpressionContextUtils.globalScope())
127+
context.appendScope(QgsExpressionContextUtils.projectScope())
128+
exp = QgsExpression(text)
129+
if exp.hasParserError():
130+
raise Exception(exp.parserErrorString())
131+
result = exp.evaluate(context)
132+
if exp.hasEvalError():
133+
raise ValueError(exp.evalErrorString())
134+
return result
135+
136+
124137
def setParamValue(self, param, widget, alg=None):
125138
if isinstance(param, ParameterRaster):
126139
return param.setValue(widget.getValue())
@@ -159,7 +172,12 @@ def setParamValue(self, param, widget, alg=None):
159172
if param.multiline:
160173
return param.setValue(unicode(widget.toPlainText()))
161174
else:
162-
return param.setValue(unicode(widget.text()))
175+
text = widget.text()
176+
try:
177+
text = self.evaluateExpression(text)
178+
except:
179+
return False
180+
return param.setValue(text)
163181
elif isinstance(param, ParameterGeometryPredicate):
164182
return param.setValue(widget.value())
165183
else:

‎python/plugins/processing/gui/NumberInputPanel.py

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@
2929

3030
from qgis.PyQt import uic
3131
from qgis.PyQt.QtCore import pyqtSignal
32+
from PyQt.QtGui import QDialog
3233

3334
from math import log10, floor
34-
from processing.gui.NumberInputDialog import NumberInputDialog
35+
from qgis.core import (QgsDataSourceURI, QgsCredentials, QgsExpressionContext,
36+
QgsExpressionContextUtils, QgsExpression, QgsRasterLayer,
37+
QgsExpressionContextScope)
38+
from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog
39+
from qgis.utils import iface
40+
from processing.tools import dataobjects
3541

3642
pluginPath = os.path.split(os.path.dirname(__file__))[0]
3743
WIDGET, BASE = uic.loadUiType(
@@ -46,6 +52,7 @@ def __init__(self, number, minimum, maximum, isInteger):
4652
super(NumberInputPanel, self).__init__(None)
4753
self.setupUi(self)
4854

55+
self.spnValue.setExpressionsEnabled(True)
4956
self.isInteger = isInteger
5057
if self.isInteger:
5158
self.spnValue.setDecimals(0)
@@ -74,15 +81,65 @@ def __init__(self, number, minimum, maximum, isInteger):
7481
self.spnValue.setValue(0)
7582
self.spnValue.setClearValue(0)
7683

77-
self.btnCalc.clicked.connect(self.showNumberInputDialog)
84+
self.btnCalc.setFixedHeight(self.spnValue.height())
85+
86+
self.btnCalc.clicked.connect(self.showExpressionsBuilder)
7887

7988
self.spnValue.valueChanged.connect(lambda: self.hasChanged.emit())
8089

81-
def showNumberInputDialog(self):
82-
dlg = NumberInputDialog(self.isInteger)
83-
dlg.exec_()
84-
if dlg.value is not None:
85-
self.spnValue.setValue(dlg.value)
90+
def showExpressionsBuilder(self):
91+
context = self.expressionContext()
92+
dlg = QgsExpressionBuilderDialog(None, self.spnValue.text(), self, "generic", context)
93+
dlg.setWindowTitle(self.tr("Expression based input"));
94+
if dlg.exec_() == QDialog.Accepted:
95+
exp = QgsExpression(dlg.expressionText())
96+
if not exp.hasParserError():
97+
result = exp.evaluate(context)
98+
if not exp.hasEvalError():
99+
try:
100+
self.spnValue.setValue(float(result))
101+
except:
102+
pass
103+
104+
def expressionContext(self):
105+
context = QgsExpressionContext()
106+
context.appendScope(QgsExpressionContextUtils.globalScope())
107+
context.appendScope(QgsExpressionContextUtils.projectScope())
108+
processingScope = QgsExpressionContextScope()
109+
layers = dataobjects.getAllLayers()
110+
for layer in layers:
111+
name = layer.name()
112+
processingScope.setVariable("%s_minx" % name, layer.extent().xMinimum())
113+
processingScope.setVariable("%s_miny" % name, layer.extent().yMinimum())
114+
processingScope.setVariable("%s_maxx" % name, layer.extent().xMaximum())
115+
processingScope.setVariable("%s_maxy" % name, layer.extent().yMaximum())
116+
if isinstance(layer, QgsRasterLayer):
117+
cellsize = (layer.extent().xMaximum()
118+
- layer.extent().xMinimum()) / layer.width()
119+
processingScope.setVariable("%s_cellsize" % name, cellsize)
120+
121+
layers = dataobjects.getRasterLayers()
122+
for layer in layers:
123+
for i in range(layer.bandCount()):
124+
stats = layer.dataProvider().bandStatistics(i + 1)
125+
processingScope.setVariable("%s_band%i_avg" % (name, i + 1), stats.mean)
126+
processingScope.setVariable("%s_band%i_stddev" % (name, i + 1), stats.stdDev)
127+
processingScope.setVariable("%s_band%i_min" % (name, i + 1), stats.minimumValue)
128+
processingScope.setVariable("%s_band%i_max" % (name, i + 1), stats.maximumValue)
129+
130+
extent = iface.mapCanvas().extent()
131+
processingScope.setVariable("canvasextent_minx", extent.xMinimum())
132+
processingScope.setVariable("canvasextent_miny", extent.yMinimum())
133+
processingScope.setVariable("canvasextent_maxx", extent.xMaximum())
134+
processingScope.setVariable("canvasextent_maxy", extent.yMaximum())
135+
136+
extent = iface.mapCanvas().fullExtent()
137+
processingScope.setVariable("fullextent_minx", extent.xMinimum())
138+
processingScope.setVariable("fullextent_miny", extent.yMinimum())
139+
processingScope.setVariable("fullextent_maxx", extent.xMaximum())
140+
processingScope.setVariable("fullextent_maxy", extent.yMaximum())
141+
context.appendScope(processingScope)
142+
return context
86143

87144
def getValue(self):
88145
return self.spnValue.value()

‎python/plugins/processing/gui/OutputSelectionPanel.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
from qgis.PyQt.QtCore import QCoreApplication, QSettings
3333
from qgis.PyQt.QtWidgets import QDialog, QMenu, QAction, QFileDialog
3434
from qgis.PyQt.QtGui import QCursor
35-
from qgis.gui import QgsEncodingFileDialog
36-
from qgis.core import QgsDataSourceURI, QgsCredentials
35+
from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog
36+
from qgis.core import QgsDataSourceURI, QgsCredentials, QgsExpressionContext,\
37+
QgsExpressionContextUtils, QgsExpression, QgsExpressionContextScope
3738

3839
from processing.core.ProcessingConfig import ProcessingConfig
3940
from processing.core.outputs import OutputVector
@@ -78,6 +79,11 @@ def selectOutput(self):
7879
actionSaveToFile.triggered.connect(self.selectFile)
7980
popupMenu.addAction(actionSaveToFile)
8081

82+
actionShowExpressionsBuilder = QAction(
83+
self.tr('Use expression...'), self.btnSelect)
84+
actionShowExpressionsBuilder.triggered.connect(self.showExpressionsBuilder)
85+
popupMenu.addAction(actionShowExpressionsBuilder)
86+
8187
if isinstance(self.output, OutputVector) \
8288
and self.alg.provider.supportsNonFileBasedOutput():
8389
actionSaveToMemory = QAction(
@@ -100,6 +106,22 @@ def selectOutput(self):
100106

101107
popupMenu.exec_(QCursor.pos())
102108

109+
def showExpressionsBuilder(self):
110+
dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, "generic", self.expressionContext())
111+
dlg.setWindowTitle(self.tr("Expression based output"));
112+
if dlg.exec_() == QDialog.Accepted:
113+
self.leText.setText(dlg.expressionText())
114+
115+
def expressionContext(self):
116+
context = QgsExpressionContext()
117+
context.appendScope(QgsExpressionContextUtils.globalScope())
118+
context.appendScope(QgsExpressionContextUtils.projectScope())
119+
processingScope = QgsExpressionContextScope()
120+
for param in self.ag.parameters:
121+
processingScope.setVariable("%s_value" % param.name, "")
122+
context.appendScope(processingScope)
123+
return context
124+
103125
def saveToTemporaryFile(self):
104126
self.leText.setText('')
105127

@@ -202,6 +224,12 @@ def selectDirectory(self):
202224

203225
def getValue(self):
204226
fileName = unicode(self.leText.text())
227+
context = self.expressionContext()
228+
exp = QgsExpression(fileName)
229+
if not exp.hasParserError():
230+
result = exp.evaluate(context)
231+
if not exp.hasEvalError():
232+
fileName = result
205233
if fileName.strip() in ['', self.SAVE_TO_TEMP_FILE]:
206234
value = None
207235
elif fileName.startswith('memory:'):

‎python/plugins/processing/ui/widgetBaseSelector.ui

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,23 @@
2121
<number>0</number>
2222
</property>
2323
<item>
24-
<widget class="QLineEdit" name="leText"/>
24+
<widget class="QLineEdit" name="leText">
25+
<property name="sizePolicy">
26+
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
27+
<horstretch>0</horstretch>
28+
<verstretch>0</verstretch>
29+
</sizepolicy>
30+
</property>
31+
</widget>
2532
</item>
2633
<item>
2734
<widget class="QToolButton" name="btnSelect">
35+
<property name="sizePolicy">
36+
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
37+
<horstretch>0</horstretch>
38+
<verstretch>0</verstretch>
39+
</sizepolicy>
40+
</property>
2841
<property name="text">
2942
<string>...</string>
3043
</property>

‎python/plugins/processing/ui/widgetLayerSelector.ui

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>250</width>
10-
<height>23</height>
9+
<width>608</width>
10+
<height>20</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -21,17 +21,36 @@
2121
<number>0</number>
2222
</property>
2323
<item>
24-
<widget class="QComboBox" name="cmbText"/>
24+
<widget class="QComboBox" name="cmbText">
25+
<property name="sizePolicy">
26+
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
27+
<horstretch>0</horstretch>
28+
<verstretch>0</verstretch>
29+
</sizepolicy>
30+
</property>
31+
</widget>
2532
</item>
2633
<item>
2734
<widget class="QToolButton" name="btnSelect">
35+
<property name="sizePolicy">
36+
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
37+
<horstretch>0</horstretch>
38+
<verstretch>0</verstretch>
39+
</sizepolicy>
40+
</property>
2841
<property name="text">
2942
<string>...</string>
3043
</property>
3144
</widget>
3245
</item>
3346
<item>
3447
<widget class="QToolButton" name="btnIterate">
48+
<property name="sizePolicy">
49+
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
50+
<horstretch>0</horstretch>
51+
<verstretch>0</verstretch>
52+
</sizepolicy>
53+
</property>
3554
<property name="toolTip">
3655
<string>Iterate over this layer</string>
3756
</property>

0 commit comments

Comments
 (0)
Please sign in to comment.