Skip to content
Permalink
Browse files

Restore batch algorithm mode following new processing API

  • Loading branch information
nyalldawson committed Jun 13, 2017
1 parent 020537a commit 54124bd0aa7c4f7c46e7b07d486d2772b5370f29
@@ -44,10 +44,13 @@ class AutofillDialog(BASE, WIDGET):
def __init__(self, alg):
super(AutofillDialog, self).__init__(None)
self.setupUi(self)
self.mode = None
self.param_index = None
self.alg = alg

self.cmbFillType.currentIndexChanged.connect(self.toggleParameters)

for param in alg.parameterDefinitions():
for param in self.alg.parameterDefinitions():
self.cmbParameters.addItem(param.description())

def toggleParameters(self, index):
@@ -60,10 +63,10 @@ def toggleParameters(self, index):

def accept(self):
self.mode = self.cmbFillType.currentIndex()
self.param = self.cmbParameters.currentIndex()
self.param_index = self.cmbParameters.currentIndex()
QDialog.accept(self)

def reject(self):
self.mode = None
self.param = None
self.param_index = None
QDialog.reject(self)
@@ -26,23 +26,29 @@

__revision__ = '$Format:%H$'

from pprint import pformat
import time

from qgis.PyQt.QtWidgets import QApplication, QMessageBox, QSizePolicy
from qgis.PyQt.QtGui import QCursor
from qgis.PyQt.QtCore import Qt

from qgis.core import QgsProcessingParameterDefinition
from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingParameterRasterOutput,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputLayerDefinition,
QgsProcessingOutputHtml,
QgsProcessingOutputNumber,
QgsProject)

from qgis.gui import QgsMessageBar

from processing.gui.BatchPanel import BatchPanel
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
from processing.gui.AlgorithmExecutor import execute
from processing.gui.Postprocessing import handleAlgorithmResults

from processing.core.ProcessingResults import ProcessingResults

from processing.core.outputs import OutputNumber
from processing.core.outputs import OutputString
from processing.core.outputs import OutputHTML
from processing.core.ProcessingResults import resultsList

from processing.tools.system import getTempFilename
from processing.tools import dataobjects
@@ -56,7 +62,6 @@ def __init__(self, alg):
AlgorithmDialogBase.__init__(self, alg)

self.alg = alg
self.alg_parameters = []

self.setWindowTitle(self.tr('Batch Processing - {0}').format(self.alg.displayName()))

@@ -69,11 +74,11 @@ def __init__(self, alg):
self.layout().insertWidget(0, self.bar)

def accept(self):
self.alg_parameters = []
self.load = []
self.canceled = False
alg_parameters = []
load = []

context = dataobjects.createContext()
feedback = self.createFeedback()

for row in range(self.mainWidget.tblParameters.rowCount()):
col = 0
@@ -87,82 +92,99 @@ def accept(self):
self.bar.pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
param.description(), row + 1),
level=QgsMessageBar.WARNING, duration=5)
self.algs = None
return
col += 1
for out in alg.destinationParameterDefinitions():
count_visible_outputs = 0
for out in self.alg.destinationParameterDefinitions():
if out.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue

count_visible_outputs += 1
widget = self.mainWidget.tblParameters.cellWidget(row, col)
text = widget.getValue()
if text.strip() != '':
out.value = text
if param.checkValueIsAcceptable(text, context):
if isinstance(out, (QgsProcessingParameterRasterOutput,
QgsProcessingParameterFeatureSink)):
# load rasters and sinks on completion
parameters[out.name()] = QgsProcessingOutputLayerDefinition(text, context.project())
else:
parameters[out.name()] = text
col += 1
else:
self.bar.pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format(
out.description(), row + 1),
level=QgsMessageBar.WARNING, duration=5)
self.algs = None
return

self.alg_parameters.append(parameters)
if self.alg.countVisibleOutputs():
widget = self.mainWidget.tblParameters.cellWidget(row, col)
self.load.append(widget.currentIndex() == 0)
else:
self.load.append(False)
alg_parameters.append(parameters)

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
self.mainWidget.setEnabled(False)
self.buttonCancel.setEnabled(True)

self.progressBar.setMaximum(len(self.algs))
# Make sure the Log tab is visible before executing the algorithm
try:
self.tabWidget.setCurrentIndex(1)
self.repaint()
except:
pass

for count, parameters in enumerate(self.alg_parameters):
self.setText(self.tr('\nProcessing algorithm {0}/{1}...').format(count + 1, len(self.alg_parameters)))
start_time = time.time()

algorithm_results = []
for count, parameters in enumerate(alg_parameters):
if feedback.isCanceled():
break
self.setText(self.tr('\nProcessing algorithm {0}/{1}...').format(count + 1, len(alg_parameters)))
self.setInfo(self.tr('<b>Algorithm {0} starting...</b>').format(self.alg.displayName()), escape_html=False)
ret, results = execute(self.alg, parameters, context, self.feedback)
if ret and not self.canceled:
if self.load[count]:
handleAlgorithmResults(self.alg, context, self.feedback, False)

feedback.pushInfo(self.tr('Input parameters:'))
feedback.pushCommandInfo(pformat(parameters))
feedback.pushInfo('')

alg_start_time = time.time()
ret, results = execute(self.alg, parameters, context, feedback)
if ret:
self.setInfo(self.tr('Algorithm {0} correctly executed...').format(self.alg.displayName()), escape_html=False)
feedback.setProgress(100)
feedback.pushInfo(
self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time)))
feedback.pushInfo(self.tr('Results:'))
feedback.pushCommandInfo(pformat(results))
feedback.pushInfo('')
algorithm_results.append(results)
else:
QApplication.restoreOverrideCursor()
return
break

self.finish()
feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))

def finish(self):
for count, parameters in enumerate(self.alg_parameters):
self.loadHTMLResults(self.alg, count)
handleAlgorithmResults(self.alg, context, feedback, False)

self.createSummaryTable()
self.finish(algorithm_results)
self.buttonCancel.setEnabled(False)

def finish(self, algorithm_results):
for count, results in enumerate(algorithm_results):
self.loadHTMLResults(results, count)

self.createSummaryTable(algorithm_results)
QApplication.restoreOverrideCursor()

self.mainWidget.setEnabled(True)
QMessageBox.information(self, self.tr('Batch processing'),
self.tr('Batch processing completed'))

def loadHTMLResults(self, alg, num):
for out in alg.outputs:
if out.flags() & QgsProcessingParameterDefinition.FlagHidden or not out.open:
continue

if isinstance(out, OutputHTML):
ProcessingResults.addResult(
'{} [{}]'.format(out.description(), num), out.value)
def loadHTMLResults(self, results, num):
for out in self.alg.outputDefinitions():
if isinstance(out, QgsProcessingOutputHtml) and out.name() in results and results[out.name()]:
resultsList.addResult(icon=self.alg.icon(), name='{} [{}]'.format(out.description(), num),
result=results[out.name()])

def createSummaryTable(self):
def createSummaryTable(self, algorithm_results):
createTable = False

for out in self.algs[0].outputs:
if isinstance(out, (OutputNumber, OutputString)):
for out in self.alg.outputDefinitions():
if isinstance(out, (QgsProcessingOutputNumber, QgsProcessingOutputString)):
createTable = True
break

@@ -171,12 +193,12 @@ def createSummaryTable(self):

outputFile = getTempFilename('html')
with codecs.open(outputFile, 'w', encoding='utf-8') as f:
for alg in self.algs:
for res in algorithm_results:
f.write('<hr>\n')
for out in alg.outputs:
if isinstance(out, (OutputNumber, OutputString)):
f.write('<p>{}: {}</p>\n'.format(out.description(), out.value))
for out in self.alg.outputDefinitions():
if isinstance(out, (QgsProcessingOutputNumber, QgsProcessingOutputString)) and out.name() in res:
f.write('<p>{}: {}</p>\n'.format(out.description(), res[out.name()]))
f.write('<hr>\n')

ProcessingResults.addResult(
'{} [summary]'.format(self.algs[0].name), outputFile)
resultsList.addResult(self.alg.icon(),
'{} [summary]'.format(self.alg.name()), outputFile)
@@ -36,14 +36,15 @@
from qgis.core import (QgsMapLayer,
QgsSettings,
QgsProject,
QgsProcessingUtils)
QgsProcessingUtils,
QgsProcessingParameterMultipleLayers,
QgsProcessingParameterRasterLayer,
QgsProcessingParameterDefinition,
QgsProcessingParameterTable,
QgsProcessingParameterFeatureSource)

from processing.gui.MultipleInputDialog import MultipleInputDialog

from processing.core.parameters import ParameterMultipleInput
from processing.core.parameters import ParameterRaster
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterTable
from processing.gui.ParameterGuiUtils import getFileFilter
from processing.tools import dataobjects

@@ -84,7 +85,7 @@ def _table(self):
def showPopupMenu(self):
popupmenu = QMenu()

if not (isinstance(self.param, ParameterMultipleInput) and
if not (isinstance(self.param, QgsProcessingParameterMultipleLayers) and
self.param.datatype == dataobjects.TYPE_FILE):
selectLayerAction = QAction(
self.tr('Select from open layers'), self.pushButton)
@@ -99,19 +100,22 @@ def showPopupMenu(self):
popupmenu.exec_(QCursor.pos())

def showLayerSelectionDialog(self):
if (isinstance(self.param, ParameterRaster) or
(isinstance(self.param, ParameterMultipleInput) and
self.param.datatype == dataobjects.TYPE_RASTER)):
layers = []
if (isinstance(self.param, QgsProcessingParameterRasterLayer) or
(isinstance(self.param, QgsProcessingParameterMultipleLayers) and
self.param.layerType() == QgsProcessingParameterDefinition.TypeRaster)):
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
elif isinstance(self.param, ParameterTable):
elif isinstance(self.param, QgsProcessingParameterTable):
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
else:
if isinstance(self.param, ParameterVector):
datatype = self.param.datatype
else:
datatype = [self.param.datatype]
if datatype != dataobjects.TYPE_VECTOR_ANY:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [datatype])
datatypes = [QgsProcessingParameterDefinition.TypeVectorAny]
if isinstance(self.param, QgsProcessingParameterFeatureSource):
datatypes = self.param.dataTypes()
elif isinstance(self.param, QgsProcessingParameterMultipleLayers):
datatypes = [self.param.layerType()]

if QgsProcessingParameterDefinition.TypeVectorAny not in datatypes:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), datatypes)
else:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())

@@ -120,17 +124,17 @@ def showLayerSelectionDialog(self):
if dlg.selectedoptions is not None:
selected = dlg.selectedoptions
if len(selected) == 1:
self.setValue(layers[selected[0]])
self.setValue(layers[selected[0]].id())
else:
if isinstance(self.param, ParameterMultipleInput):
self.text.setText(';'.join(layers[idx].name() for idx in selected))
if isinstance(self.param, QgsProcessingParameterMultipleLayers):
self.text.setText(';'.join(layers[idx].id() for idx in selected))
else:
rowdif = len(selected) - (self._table().rowCount() - self.row)
for i in range(rowdif):
self._panel().addRow()
for i, layeridx in enumerate(selected):
self._table().cellWidget(i + self.row,
self.col).setValue(layers[layeridx])
self.col).setValue(layers[layeridx].id())

def showFileSelectionDialog(self):
settings = QgsSettings()
@@ -156,7 +160,7 @@ def showFileSelectionDialog(self):
self.text.setText(files[0])
self.textEditingFinished()
else:
if isinstance(self.param, ParameterMultipleInput):
if isinstance(self.param, QgsProcessingParameterMultipleLayers):
self.text.setText(';'.join(str(f) for f in files))
else:
rowdif = len(files) - (self._table().rowCount() - self.row)

0 comments on commit 54124bd

Please sign in to comment.
You can’t perform that action at this time.