mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
286 lines
12 KiB
Python
286 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
***************************************************************************
|
|
AlgorithmDialog.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. *
|
|
* *
|
|
***************************************************************************
|
|
"""
|
|
|
|
__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$'
|
|
|
|
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 processing.core.ProcessingLog import ProcessingLog
|
|
from processing.core.ProcessingConfig import ProcessingConfig
|
|
|
|
from processing.gui.BatchAlgorithmDialog import BatchAlgorithmDialog
|
|
from processing.gui.ParametersPanel import ParametersPanel
|
|
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
|
|
from processing.gui.AlgorithmExecutor import runalg, runalgIterating
|
|
from processing.gui.Postprocessing import handleAlgorithmResults
|
|
|
|
from processing.core.parameters import ParameterExtent
|
|
from processing.core.parameters import ParameterRaster
|
|
from processing.core.parameters import ParameterVector
|
|
from processing.core.parameters import ParameterTable
|
|
from processing.core.parameters import ParameterBoolean
|
|
from processing.core.parameters import ParameterSelection
|
|
from processing.core.parameters import ParameterFixedTable
|
|
from processing.core.parameters import ParameterRange
|
|
from processing.core.parameters import ParameterTableField
|
|
from processing.core.parameters import ParameterTableMultipleField
|
|
from processing.core.parameters import ParameterMultipleInput
|
|
from processing.core.parameters import ParameterString
|
|
from processing.core.parameters import ParameterNumber
|
|
from processing.core.parameters import ParameterFile
|
|
from processing.core.parameters import ParameterCrs
|
|
from processing.core.parameters import ParameterPoint
|
|
from processing.core.parameters import ParameterGeometryPredicate
|
|
|
|
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):
|
|
|
|
def __init__(self, alg):
|
|
AlgorithmDialogBase.__init__(self, alg)
|
|
|
|
self.alg = alg
|
|
|
|
self.mainWidget = ParametersPanel(self, alg)
|
|
self.setMainWidget()
|
|
|
|
self.cornerWidget = QWidget()
|
|
layout = QVBoxLayout()
|
|
layout.setContentsMargins(0, 0, 0, 5)
|
|
self.tabWidget.setStyleSheet("QTabBar::tab { height: 30px; }")
|
|
self.runAsBatchButton = QPushButton(self.tr("Run as batch process..."))
|
|
self.runAsBatchButton.clicked.connect(self.runAsBatch)
|
|
layout.addWidget(self.runAsBatchButton)
|
|
self.cornerWidget.setLayout(layout)
|
|
self.tabWidget.setCornerWidget(self.cornerWidget)
|
|
|
|
QgsMapLayerRegistry.instance().layerWasAdded.connect(self.mainWidget.layerAdded)
|
|
QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(self.mainWidget.layersWillBeRemoved)
|
|
|
|
def runAsBatch(self):
|
|
self.close()
|
|
dlg = BatchAlgorithmDialog(self.alg)
|
|
dlg.show()
|
|
dlg.exec_()
|
|
|
|
def setParamValues(self):
|
|
params = self.alg.parameters
|
|
outputs = self.alg.outputs
|
|
|
|
for param in params:
|
|
if param.hidden:
|
|
continue
|
|
if not self.setParamValue(
|
|
param, self.mainWidget.valueItems[param.name]):
|
|
raise AlgorithmDialogBase.InvalidParameterValue(
|
|
param, self.mainWidget.valueItems[param.name])
|
|
|
|
for output in outputs:
|
|
if output.hidden:
|
|
continue
|
|
output.value = self.mainWidget.valueItems[output.name].getValue()
|
|
if isinstance(output, (OutputRaster, OutputVector, OutputTable)):
|
|
output.open = self.mainWidget.checkBoxes[output.name].isChecked()
|
|
|
|
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())
|
|
elif isinstance(param, (ParameterVector, ParameterTable)):
|
|
try:
|
|
return param.setValue(widget.itemData(widget.currentIndex()))
|
|
except:
|
|
return param.setValue(widget.getValue())
|
|
elif isinstance(param, ParameterBoolean):
|
|
return param.setValue(widget.isChecked())
|
|
elif isinstance(param, ParameterSelection):
|
|
return param.setValue(widget.currentIndex())
|
|
elif isinstance(param, ParameterFixedTable):
|
|
return param.setValue(widget.table)
|
|
elif isinstance(param, ParameterRange):
|
|
return param.setValue(widget.getValue())
|
|
elif isinstance(param, ParameterTableField):
|
|
if param.optional and widget.currentIndex() == 0:
|
|
return param.setValue(None)
|
|
return param.setValue(widget.currentText())
|
|
elif isinstance(param, ParameterTableMultipleField):
|
|
if param.optional and len(list(widget.get_selected_items())) == 0:
|
|
return param.setValue(None)
|
|
return param.setValue(list(widget.get_selected_items()))
|
|
elif isinstance(param, ParameterMultipleInput):
|
|
if param.datatype == dataobjects.TYPE_FILE:
|
|
return param.setValue(widget.selectedoptions)
|
|
else:
|
|
if param.datatype == dataobjects.TYPE_RASTER:
|
|
options = dataobjects.getRasterLayers(sorting=False)
|
|
elif param.datatype == dataobjects.TYPE_VECTOR_ANY:
|
|
options = dataobjects.getVectorLayers(sorting=False)
|
|
else:
|
|
options = dataobjects.getVectorLayers([param.datatype], sorting=False)
|
|
return param.setValue([options[i] for i in widget.selectedoptions])
|
|
elif isinstance(param, (ParameterNumber, ParameterFile, ParameterCrs,
|
|
ParameterExtent, ParameterPoint)):
|
|
return param.setValue(widget.getValue())
|
|
elif isinstance(param, ParameterString):
|
|
if param.multiline:
|
|
text = unicode(widget.toPlainText())
|
|
else:
|
|
text = widget.text()
|
|
|
|
if param.evaluateExpressions:
|
|
try:
|
|
text = self.evaluateExpression(text)
|
|
except:
|
|
pass
|
|
return param.setValue(text)
|
|
elif isinstance(param, ParameterGeometryPredicate):
|
|
return param.setValue(widget.value())
|
|
else:
|
|
return param.setValue(unicode(widget.text()))
|
|
|
|
def accept(self):
|
|
self.settings.setValue("/Processing/dialogBase", self.saveGeometry())
|
|
|
|
checkCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_CRS)
|
|
try:
|
|
self.setParamValues()
|
|
if checkCRS and not self.alg.checkInputCRS():
|
|
reply = QMessageBox.question(self, self.tr("Unmatching CRS's"),
|
|
self.tr('Layers do not all use the same CRS. This can '
|
|
'cause unexpected results.\nDo you want to '
|
|
'continue?'),
|
|
QMessageBox.Yes | QMessageBox.No,
|
|
QMessageBox.No)
|
|
if reply == QMessageBox.No:
|
|
return
|
|
msg = self.alg._checkParameterValuesBeforeExecuting()
|
|
if msg:
|
|
QMessageBox.warning(
|
|
self, self.tr('Unable to execute algorithm'), msg)
|
|
return
|
|
self.btnRun.setEnabled(False)
|
|
self.btnClose.setEnabled(False)
|
|
buttons = self.mainWidget.iterateButtons
|
|
self.iterateParam = None
|
|
|
|
for i in range(len(buttons.values())):
|
|
button = buttons.values()[i]
|
|
if button.isChecked():
|
|
self.iterateParam = buttons.keys()[i]
|
|
break
|
|
|
|
self.progressBar.setMaximum(0)
|
|
self.lblProgress.setText(self.tr('Processing algorithm...'))
|
|
# Make sure the Log tab is visible before executing the algorithm
|
|
try:
|
|
self.tabWidget.setCurrentIndex(1)
|
|
self.repaint()
|
|
except:
|
|
pass
|
|
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
|
|
self.setInfo(
|
|
self.tr('<b>Algorithm %s starting...</b>') % self.alg.name)
|
|
|
|
if self.iterateParam:
|
|
if runalgIterating(self.alg, self.iterateParam, self):
|
|
self.finish()
|
|
else:
|
|
QApplication.restoreOverrideCursor()
|
|
self.resetGUI()
|
|
else:
|
|
command = self.alg.getAsCommand()
|
|
if command:
|
|
ProcessingLog.addToLog(
|
|
ProcessingLog.LOG_ALGORITHM, command)
|
|
if runalg(self.alg, self):
|
|
self.finish()
|
|
else:
|
|
QApplication.restoreOverrideCursor()
|
|
self.resetGUI()
|
|
except AlgorithmDialogBase.InvalidParameterValue as e:
|
|
try:
|
|
self.buttonBox.accepted.connect(lambda:
|
|
e.widget.setPalette(QPalette()))
|
|
palette = e.widget.palette()
|
|
palette.setColor(QPalette.Base, QColor(255, 255, 0))
|
|
e.widget.setPalette(palette)
|
|
self.lblProgress.setText(
|
|
self.tr('<b>Missing parameter value: %s</b>') % e.parameter.description)
|
|
return
|
|
except:
|
|
QMessageBox.critical(self,
|
|
self.tr('Unable to execute algorithm'),
|
|
self.tr('Wrong or missing parameter values'))
|
|
|
|
def finish(self):
|
|
keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
|
|
|
|
if self.iterateParam is None:
|
|
if not handleAlgorithmResults(self.alg, self, not keepOpen):
|
|
self.resetGUI()
|
|
return
|
|
|
|
self.executed = True
|
|
self.setInfo('Algorithm %s finished' % self.alg.name)
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
if not keepOpen:
|
|
self.close()
|
|
else:
|
|
self.resetGUI()
|
|
if self.alg.getHTMLOutputsCount() > 0:
|
|
self.setInfo(
|
|
self.tr('HTML output has been generated by this algorithm.'
|
|
'\nOpen the results dialog to check it.'))
|
|
|
|
def closeEvent(self, evt):
|
|
QgsMapLayerRegistry.instance().layerWasAdded.disconnect(self.mainWidget.layerAdded)
|
|
QgsMapLayerRegistry.instance().layersWillBeRemoved.disconnect(self.mainWidget.layersWillBeRemoved)
|
|
super(AlgorithmDialog, self).closeEvent(evt)
|