mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-16 00:05:45 -04:00
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:
commit
730c5806aa
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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:'):
|
||||
|
@ -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,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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user