mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Restore batch algorithm mode following new processing API
This commit is contained in:
parent
020537ac7e
commit
54124bd0aa
@ -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 @@ class AutofillDialog(BASE, WIDGET):
|
||||
|
||||
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,11 +26,21 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
__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
|
||||
@ -38,11 +48,7 @@ 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 @@ class BatchAlgorithmDialog(AlgorithmDialogBase):
|
||||
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 @@ class BatchAlgorithmDialog(AlgorithmDialogBase):
|
||||
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,36 +92,36 @@ class BatchAlgorithmDialog(AlgorithmDialogBase):
|
||||
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)
|
||||
@ -124,45 +129,62 @@ class BatchAlgorithmDialog(AlgorithmDialogBase):
|
||||
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
|
||||
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()])
|
||||
|
||||
if isinstance(out, OutputHTML):
|
||||
ProcessingResults.addResult(
|
||||
'{} [{}]'.format(out.description(), num), out.value)
|
||||
|
||||
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 @@ class BatchAlgorithmDialog(AlgorithmDialogBase):
|
||||
|
||||
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.PyQt.QtGui import QCursor
|
||||
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 @@ class BatchInputSelectionPanel(QWidget):
|
||||
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 @@ class BatchInputSelectionPanel(QWidget):
|
||||
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 @@ class BatchInputSelectionPanel(QWidget):
|
||||
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 @@ class BatchInputSelectionPanel(QWidget):
|
||||
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)
|
||||
|
@ -31,18 +31,20 @@ __revision__ = '$Format:%H$'
|
||||
import os
|
||||
import re
|
||||
|
||||
from qgis.core import QgsMapLayer, QgsSettings
|
||||
from qgis.core import (QgsMapLayer,
|
||||
QgsSettings,
|
||||
QgsProcessingParameterFolderOutput,
|
||||
QgsProcessingParameterRasterLayer,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterTable,
|
||||
QgsProcessingParameterMultipleLayers,
|
||||
QgsProcessingParameterBoolean,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterMatrix)
|
||||
from qgis.PyQt.QtWidgets import QWidget, QPushButton, QLineEdit, QHBoxLayout, QSizePolicy, QFileDialog
|
||||
|
||||
from processing.gui.AutofillDialog import AutofillDialog
|
||||
from processing.core.parameters import ParameterMultipleInput
|
||||
from processing.core.parameters import ParameterRaster
|
||||
from processing.core.parameters import ParameterTable
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterBoolean
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.parameters import ParameterFixedTable
|
||||
from processing.core.outputs import OutputDirectory
|
||||
from processing.gui.ParameterGuiUtils import getFileFilter
|
||||
|
||||
|
||||
class BatchOutputSelectionPanel(QWidget):
|
||||
@ -71,11 +73,11 @@ class BatchOutputSelectionPanel(QWidget):
|
||||
self.setLayout(self.horizontalLayout)
|
||||
|
||||
def showSelectionDialog(self):
|
||||
if isinstance(self.output, OutputDirectory):
|
||||
if isinstance(self.output, QgsProcessingParameterFolderOutput):
|
||||
self.selectDirectory()
|
||||
return
|
||||
|
||||
filefilter = self.output.getFileFilter(self.alg)
|
||||
filefilter = getFileFilter(self.output)
|
||||
settings = QgsSettings()
|
||||
if settings.contains('/Processing/LastBatchOutputPath'):
|
||||
path = str(settings.value('/Processing/LastBatchOutputPath'))
|
||||
@ -108,22 +110,23 @@ class BatchOutputSelectionPanel(QWidget):
|
||||
n = self.table.rowCount() - self.row
|
||||
for i in range(n):
|
||||
widget = self.table.cellWidget(i + self.row,
|
||||
dlg.param)
|
||||
param = self.alg.parameters[dlg.param]
|
||||
if isinstance(param, (ParameterRaster,
|
||||
ParameterVector, ParameterTable,
|
||||
ParameterMultipleInput)):
|
||||
dlg.param_index)
|
||||
param = self.alg.parameterDefinitions()[dlg.param_index]
|
||||
if isinstance(param, (QgsProcessingParameterRasterLayer,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterTable,
|
||||
QgsProcessingParameterMultipleLayers)):
|
||||
v = widget.value()
|
||||
if isinstance(v, QgsMapLayer):
|
||||
s = v.name()
|
||||
else:
|
||||
s = os.path.basename(v)
|
||||
s = os.path.splitext(s)[0]
|
||||
elif isinstance(param, ParameterBoolean):
|
||||
elif isinstance(param, QgsProcessingParameterBoolean):
|
||||
s = str(widget.currentIndex() == 0)
|
||||
elif isinstance(param, ParameterSelection):
|
||||
elif isinstance(param, QgsProcessingParameterEnum):
|
||||
s = str(widget.currentText())
|
||||
elif isinstance(param, ParameterFixedTable):
|
||||
elif isinstance(param, QgsProcessingParameterMatrix):
|
||||
s = str(widget.table)
|
||||
else:
|
||||
s = str(widget.text())
|
||||
|
@ -94,7 +94,7 @@ class BatchPanel(BASE, WIDGET):
|
||||
|
||||
def initWidgets(self):
|
||||
# If there are advanced parameters — show corresponding button
|
||||
for param in self.alg.parameters:
|
||||
for param in self.alg.parameterDefinitions():
|
||||
if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
|
||||
self.btnAdvanced.show()
|
||||
break
|
||||
@ -129,8 +129,8 @@ class BatchPanel(BASE, WIDGET):
|
||||
self.tblParameters.setHorizontalHeaderItem(
|
||||
column, QTableWidgetItem(self.tr('Load in QGIS')))
|
||||
|
||||
# Add three empty rows by default
|
||||
for i in range(3):
|
||||
# Add two empty rows by default
|
||||
for i in range(2):
|
||||
self.addRow()
|
||||
|
||||
self.tblParameters.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
|
||||
|
Loading…
x
Reference in New Issue
Block a user