mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-10-31 00:06:02 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			265 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			265 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 pprint import pformat
 | |
| import time
 | |
| 
 | |
| from qgis.PyQt.QtCore import QCoreApplication, Qt
 | |
| from qgis.PyQt.QtWidgets import QMessageBox, QPushButton, QSizePolicy, QDialogButtonBox
 | |
| from qgis.PyQt.QtGui import QColor, QPalette
 | |
| 
 | |
| from qgis.core import (Qgis,
 | |
|                        QgsProject,
 | |
|                        QgsApplication,
 | |
|                        QgsProcessingUtils,
 | |
|                        QgsProcessingParameterDefinition,
 | |
|                        QgsProcessingAlgRunnerTask,
 | |
|                        QgsProcessingOutputHtml,
 | |
|                        QgsProcessingParameterVectorDestination,
 | |
|                        QgsProcessingOutputLayerDefinition,
 | |
|                        QgsProcessingParameterFeatureSink,
 | |
|                        QgsProcessingParameterRasterDestination,
 | |
|                        QgsProcessingAlgorithm)
 | |
| from qgis.gui import (QgsMessageBar,
 | |
|                       QgsProcessingAlgorithmDialogBase)
 | |
| from qgis.utils import iface
 | |
| 
 | |
| from processing.core.ProcessingLog import ProcessingLog
 | |
| from processing.core.ProcessingConfig import ProcessingConfig
 | |
| from processing.core.ProcessingResults import resultsList
 | |
| from processing.gui.ParametersPanel import ParametersPanel
 | |
| from processing.gui.BatchAlgorithmDialog import BatchAlgorithmDialog
 | |
| from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
 | |
| from processing.gui.AlgorithmExecutor import executeIterating, execute
 | |
| from processing.gui.Postprocessing import handleAlgorithmResults
 | |
| 
 | |
| from processing.tools import dataobjects
 | |
| 
 | |
| 
 | |
| class AlgorithmDialog(QgsProcessingAlgorithmDialogBase):
 | |
| 
 | |
|     def __init__(self, alg):
 | |
|         super().__init__()
 | |
|         self.feedback_dialog = None
 | |
| 
 | |
|         self.setAlgorithm(alg)
 | |
|         self.setMainWidget(self.getParametersPanel(alg, self))
 | |
| 
 | |
|         self.runAsBatchButton = QPushButton(QCoreApplication.translate("AlgorithmDialog", "Run as Batch Process…"))
 | |
|         self.runAsBatchButton.clicked.connect(self.runAsBatch)
 | |
|         self.buttonBox().addButton(self.runAsBatchButton, QDialogButtonBox.ResetRole) # reset role to ensure left alignment
 | |
| 
 | |
|     def getParametersPanel(self, alg, parent):
 | |
|         return ParametersPanel(parent, alg)
 | |
| 
 | |
|     def runAsBatch(self):
 | |
|         self.close()
 | |
|         dlg = BatchAlgorithmDialog(self.algorithm())
 | |
|         dlg.show()
 | |
|         dlg.exec_()
 | |
| 
 | |
|     def setParameters(self, parameters):
 | |
|         self.mainWidget().setParameters(parameters)
 | |
| 
 | |
|     def getParameterValues(self):
 | |
|         parameters = {}
 | |
| 
 | |
|         if self.mainWidget() is None:
 | |
|             return parameters
 | |
| 
 | |
|         for param in self.algorithm().parameterDefinitions():
 | |
|             if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
 | |
|                 continue
 | |
|             if not param.isDestination():
 | |
|                 wrapper = self.mainWidget().wrappers[param.name()]
 | |
|                 value = None
 | |
|                 if wrapper.widget:
 | |
|                     value = wrapper.value()
 | |
|                     parameters[param.name()] = value
 | |
| 
 | |
|                     if not param.checkValueIsAcceptable(value):
 | |
|                         raise AlgorithmDialogBase.InvalidParameterValue(param, wrapper.widget)
 | |
|             else:
 | |
|                 dest_project = None
 | |
|                 if not param.flags() & QgsProcessingParameterDefinition.FlagHidden and \
 | |
|                         isinstance(param, (QgsProcessingParameterRasterDestination,
 | |
|                                            QgsProcessingParameterFeatureSink,
 | |
|                                            QgsProcessingParameterVectorDestination)):
 | |
|                     if self.mainWidget().checkBoxes[param.name()].isChecked():
 | |
|                         dest_project = QgsProject.instance()
 | |
| 
 | |
|                 value = self.mainWidget().outputWidgets[param.name()].getValue()
 | |
|                 if value and isinstance(value, QgsProcessingOutputLayerDefinition):
 | |
|                     value.destinationProject = dest_project
 | |
|                 if value:
 | |
|                     parameters[param.name()] = value
 | |
| 
 | |
|         return self.algorithm().preprocessParameters(parameters)
 | |
| 
 | |
|     def accept(self):
 | |
|         feedback = self.createFeedback()
 | |
|         context = dataobjects.createContext(feedback)
 | |
| 
 | |
|         checkCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_CRS)
 | |
|         try:
 | |
|             parameters = self.getParameterValues()
 | |
| 
 | |
|             if checkCRS and not self.algorithm().validateInputCrs(parameters, context):
 | |
|                 reply = QMessageBox.question(self, self.tr("Unmatching CRS's"),
 | |
|                                              self.tr('Parameters 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
 | |
|             ok, msg = self.algorithm().checkParameterValues(parameters, context)
 | |
|             if not ok:
 | |
|                 QMessageBox.warning(
 | |
|                     self, self.tr('Unable to execute algorithm'), msg)
 | |
|                 return
 | |
|             self.runButton().setEnabled(False)
 | |
|             self.cancelButton().setEnabled(False)
 | |
|             buttons = self.mainWidget().iterateButtons
 | |
|             self.iterateParam = None
 | |
| 
 | |
|             for i in range(len(list(buttons.values()))):
 | |
|                 button = list(buttons.values())[i]
 | |
|                 if button.isChecked():
 | |
|                     self.iterateParam = list(buttons.keys())[i]
 | |
|                     break
 | |
| 
 | |
|             self.clearProgress()
 | |
|             self.setProgressText(QCoreApplication.translate('AlgorithmDialog', 'Processing algorithm…'))
 | |
| 
 | |
|             self.setInfo(
 | |
|                 QCoreApplication.translate('AlgorithmDialog', '<b>Algorithm \'{0}\' starting…</b>').format(self.algorithm().displayName()), escapeHtml=False)
 | |
| 
 | |
|             feedback.pushInfo(self.tr('Input parameters:'))
 | |
|             display_params = []
 | |
|             for k, v in parameters.items():
 | |
|                 display_params.append("'" + k + "' : " + self.algorithm().parameterDefinition(k).valueAsPythonString(v, context))
 | |
|             feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }')
 | |
|             feedback.pushInfo('')
 | |
|             start_time = time.time()
 | |
| 
 | |
|             if self.iterateParam:
 | |
|                 # Make sure the Log tab is visible before executing the algorithm
 | |
|                 try:
 | |
|                     self.showLog()
 | |
|                     self.repaint()
 | |
|                 except:
 | |
|                     pass
 | |
| 
 | |
|                 self.cancelButton().setEnabled(self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel)
 | |
|                 if executeIterating(self.algorithm(), parameters, self.iterateParam, context, feedback):
 | |
|                     feedback.pushInfo(
 | |
|                         self.tr('Execution completed in {0:0.2f} seconds').format(time.time() - start_time))
 | |
|                     self.cancelButton().setEnabled(False)
 | |
|                     self.finish(True, parameters, context, feedback)
 | |
|                 else:
 | |
|                     self.cancelButton().setEnabled(False)
 | |
|                     self.resetGui()
 | |
|             else:
 | |
|                 command = self.algorithm().asPythonCommand(parameters, context)
 | |
|                 if command:
 | |
|                     ProcessingLog.addToLog(command)
 | |
|                 self.cancelButton().setEnabled(self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel)
 | |
| 
 | |
|                 def on_complete(ok, results):
 | |
|                     if ok:
 | |
|                         feedback.pushInfo(self.tr('Execution completed in {0:0.2f} seconds').format(time.time() - start_time))
 | |
|                         feedback.pushInfo(self.tr('Results:'))
 | |
|                         feedback.pushCommandInfo(pformat(results))
 | |
|                     else:
 | |
|                         feedback.reportError(
 | |
|                             self.tr('Execution failed after {0:0.2f} seconds').format(time.time() - start_time))
 | |
|                     feedback.pushInfo('')
 | |
| 
 | |
|                     if self.feedback_dialog is not None:
 | |
|                         self.feedback_dialog.close()
 | |
|                         self.feedback_dialog.deleteLater()
 | |
|                         self.feedback_dialog = None
 | |
| 
 | |
|                     self.cancelButton().setEnabled(False)
 | |
| 
 | |
|                     self.finish(ok, results, context, feedback)
 | |
| 
 | |
|                 if not (self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading):
 | |
|                     # Make sure the Log tab is visible before executing the algorithm
 | |
|                     self.showLog()
 | |
| 
 | |
|                     task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, context, feedback)
 | |
|                     task.executed.connect(on_complete)
 | |
|                     self.setCurrentTask(task)
 | |
|                 else:
 | |
|                     self.feedback_dialog = self.createProgressDialog()
 | |
|                     self.feedback_dialog.show()
 | |
|                     ok, results = execute(self.algorithm(), parameters, context, feedback)
 | |
|                     on_complete(ok, results)
 | |
| 
 | |
|         except AlgorithmDialogBase.InvalidParameterValue as e:
 | |
|             try:
 | |
|                 self.buttonBox().accepted.connect(lambda e=e:
 | |
|                                                   e.widget.setPalette(QPalette()))
 | |
|                 palette = e.widget.palette()
 | |
|                 palette.setColor(QPalette.Base, QColor(255, 255, 0))
 | |
|                 e.widget.setPalette(palette)
 | |
|             except:
 | |
|                 pass
 | |
|             self.messageBar().clearWidgets()
 | |
|             self.messageBar().pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description()),
 | |
|                                           level=Qgis.Warning, duration=5)
 | |
| 
 | |
|     def finish(self, successful, result, context, feedback):
 | |
|         keepOpen = not successful or ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
 | |
| 
 | |
|         if self.iterateParam is None:
 | |
| 
 | |
|             # add html results to results dock
 | |
|             for out in self.algorithm().outputDefinitions():
 | |
|                 if isinstance(out, QgsProcessingOutputHtml) and out.name() in result and result[out.name()]:
 | |
|                     resultsList.addResult(icon=self.algorithm().icon(), name=out.description(), timestamp=time.localtime(),
 | |
|                                           result=result[out.name()])
 | |
| 
 | |
|             if not handleAlgorithmResults(self.algorithm(), context, feedback, not keepOpen):
 | |
|                 self.resetGui()
 | |
|                 return
 | |
| 
 | |
|         self.setExecuted(True)
 | |
|         self.setResults(result)
 | |
|         self.setInfo(self.tr('Algorithm \'{0}\' finished').format(self.algorithm().displayName()), escapeHtml=False)
 | |
| 
 | |
|         if not keepOpen:
 | |
|             self.close()
 | |
|         else:
 | |
|             self.resetGui()
 | |
|             if self.algorithm().hasHtmlOutputs():
 | |
|                 self.setInfo(
 | |
|                     self.tr('HTML output has been generated by this algorithm.'
 | |
|                             '\nOpen the results dialog to check it.'), escapeHtml=False)
 |