def _executeAlgorithm(alg): message = alg.checkBeforeOpeningParametersDialog() if message: dlg = MessageDialog() dlg.setTitle(Processing.tr('Missing dependency')) dlg.setMessage( Processing.tr('<h3>Missing dependency. This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return alg = alg.getCopy() if (alg.getVisibleParametersCount() + alg.getVisibleOutputsCount()) > 0: dlg = alg.getCustomParametersDialog() if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress() execute(alg, feedback) handleAlgorithmResults(alg, feedback) feedback.close()
def test_check_validity(self): """Test that the output invalid contains the error reason""" polygon_layer = self._make_layer('Polygon') self.assertTrue(polygon_layer.startEditing()) f = QgsFeature(polygon_layer.fields()) f.setAttributes([1]) # Flake! f.setGeometry(QgsGeometry.fromWkt( 'POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))')) self.assertTrue(f.isValid()) f2 = QgsFeature(polygon_layer.fields()) f2.setAttributes([1]) f2.setGeometry(QgsGeometry.fromWkt( 'POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))')) self.assertTrue(f2.isValid()) self.assertTrue(polygon_layer.addFeatures([f, f2])) polygon_layer.commitChanges() polygon_layer.rollBack() self.assertEqual(polygon_layer.featureCount(), 2) QgsProject.instance().addMapLayers([polygon_layer]) alg = self.registry.createAlgorithmById('qgis:checkvalidity') context = QgsProcessingContext() context.setProject(QgsProject.instance()) feedback = ConsoleFeedBack() self.assertIsNotNone(alg) parameters = {} parameters['INPUT_LAYER'] = polygon_layer.id() parameters['VALID_OUTPUT'] = 'memory:' parameters['INVALID_OUTPUT'] = 'memory:' parameters['ERROR_OUTPUT'] = 'memory:' # QGIS method parameters['METHOD'] = 1 ok, results = execute( alg, parameters, context=context, feedback=feedback) self.assertTrue(ok) invalid_layer = QgsProcessingUtils.mapLayerFromString( results['INVALID_OUTPUT'], context) self.assertEqual(invalid_layer.fields().names()[-1], '_errors') self.assertEqual(invalid_layer.featureCount(), 1) f = next(invalid_layer.getFeatures()) self.assertEqual(f.attributes(), [ 1, 'segments 0 and 2 of line 0 intersect at 1, 1']) # GEOS method parameters['METHOD'] = 2 ok, results = execute( alg, parameters, context=context, feedback=feedback) self.assertTrue(ok) invalid_layer = QgsProcessingUtils.mapLayerFromString( results['INVALID_OUTPUT'], context) self.assertEqual(invalid_layer.fields().names()[-1], '_errors') self.assertEqual(invalid_layer.featureCount(), 1) f = next(invalid_layer.getFeatures()) self.assertEqual(f.attributes(), [1, 'Self-intersection'])
def executeAlgorithm(self): alg = self.algorithmTree.selectedAlgorithm() if alg is not None: ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def _executeAlgorithm(alg): ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(Processing.tr('Missing dependency')) dlg.setMessage( Processing.tr('<h3>Missing dependency. This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if (alg.countVisibleParameters()) > 0: dlg = alg.createCustomParametersWidget(None) if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def executeAlgorithm(self): item = self.algorithmTree.currentItem() if isinstance(item, TreeAlgorithmItem): alg = QgsApplication.processingRegistry().createAlgorithmById(item.alg.id()) if not alg: return ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) if dlg.executed: showRecent = ProcessingConfig.getSetting( ProcessingConfig.SHOW_RECENT_ALGORITHMS) if showRecent: self.addRecentAlgorithms(True) # have to manually delete the dialog - otherwise it's owned by the # iface mainWindow and never deleted dlg.deleteLater() else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close() if isinstance(item, TreeActionItem): action = item.action action.setData(self) action.execute()
def accept(self): keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN) parameters = self.getParamValues() if parameters: with OverrideCursor(Qt.WaitCursor): context = dataobjects.createContext() ProcessingLog.addToLog(self.alg.asPythonCommand(parameters, context)) self.executed, results = execute(self.alg, parameters, context, self.feedback) if self.executed: handleAlgorithmResults(self.alg, context, self.feedback, not keepOpen) if not keepOpen: QDialog.reject(self)
def accept(self): keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN) try: if self.setParamValues(): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) ProcessingLog.addToLog(ProcessingLog.LOG_ALGORITHM, self.alg.getAsCommand()) self.executed = execute(self.alg, self.feedback) if self.executed: handleAlgorithmResults(self.alg, self.feedback, not keepOpen) if not keepOpen: QDialog.reject(self) finally: QApplication.restoreOverrideCursor()
def executeAlgorithm(self): alg = self.algorithmTree.selectedAlgorithm().create() if self.algorithmTree.selectedAlgorithm() is not None else None if alg is not None: ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if self.in_place_mode and not [d for d in alg.parameterDefinitions() if d.name() not in ('INPUT', 'OUTPUT')]: parameters = {} feedback = MessageBarProgress(algname=alg.displayName()) ok, results = execute_in_place(alg, parameters, feedback=feedback) if ok: iface.messageBar().pushSuccess('', self.tr('{} complete').format(alg.displayName())) feedback.close() # MessageBarProgress handles errors return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg, self.in_place_mode, iface.mainWindow()) dlg.setAttribute(Qt.WA_DeleteOnClose) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress(algname=alg.displayName()) context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def test_import(self): """Test algorithm with CamelCaseSchema""" alg = self.registry.createAlgorithmById("qgis:importintopostgis") self.assertIsNotNone(alg) table_name = 'out_TestPyQgsExportToPostgis' parameters = { 'CREATEINDEX': True, 'DATABASE': 'qgis_test', 'DROP_STRING_LENGTH': False, 'ENCODING': 'UTF-8', 'FORCE_SINGLEPART': False, 'GEOMETRY_COLUMN': 'geom', 'INPUT': unitTestDataPath() + '/points.shp', 'LOWERCASE_NAMES': True, 'OVERWRITE': True, 'PRIMARY_KEY': None, 'SCHEMA': 'CamelCaseSchema', 'TABLENAME': table_name } feedback = ConsoleFeedBack() context = QgsProcessingContext() # Note: the following returns true also in case of errors ... self.assertTrue(execute(alg, parameters, context, feedback)) # ... so we check the log self.assertEqual(feedback._errors, []) # Check that data have been imported correctly exported = QgsVectorLayer(unitTestDataPath() + '/points.shp', 'exported') self.assertTrue(exported.isValid()) imported = QgsVectorLayer("service='qgis_test' dbname=\'qgis_test\' table=\"CamelCaseSchema\".\"%s\" (geom)" % table_name, 'imported', 'postgres') self.assertTrue(imported.isValid()) imported_fields = [f.name() for f in imported.fields()] for f in exported.fields(): self.assertTrue(f.name().lower() in imported_fields) # Check data imported_f = next(imported.getFeatures("class = 'Jet' AND heading = 85")) self.assertTrue(imported_f.isValid()) exported_f = next(exported.getFeatures("class = 'Jet' AND heading = 85")) self.assertTrue(exported_f.isValid()) self.assertEqual(exported_f.geometry().asWkt(), imported_f.geometry().asWkt())
def _executeAlgorithm(alg_id): alg = QgsApplication.processingRegistry().createAlgorithmById(alg_id) if alg is None: dlg = MessageDialog() dlg.setTitle(Processing.tr('Missing Algorithm')) dlg.setMessage( Processing.tr('The algorithm "{}" is no longer available. (Perhaps a plugin was uninstalled?)').format(alg_id)) dlg.exec_() return ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(Processing.tr('Missing Dependency')) dlg.setMessage( Processing.tr('<h3>Missing dependency. This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if (alg.countVisibleParameters()) > 0: dlg = alg.createCustomParametersWidget(parent=iface.mainWindow()) if not dlg: dlg = AlgorithmDialog(alg, parent=iface.mainWindow()) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def accept(self): keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN) parameters = self.getParamValues() if parameters: with OverrideCursor(Qt.WaitCursor): self.feedback = FieldCalculatorFeedback(self) self.feedback.progressChanged.connect(self.setPercentage) context = dataobjects.createContext() ProcessingLog.addToLog(self.alg.asPythonCommand(parameters, context)) self.executed, results = execute(self.alg, parameters, context, self.feedback) self.setPercentage(0) if self.executed: handleAlgorithmResults(self.alg, context, self.feedback, not keepOpen) self._wasExecuted = self.executed or self._wasExecuted if not keepOpen: QDialog.reject(self)
def runAlgorithm(algOrName, onFinish, *args, **kwargs): if isinstance(algOrName, GeoAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') QgsMessageLog.logMessage(Processing.tr('Error: Algorithm {0} not found\n').format(algOrName), Processing.tr("Processing")) return parameters = {} if len(args) == 1 and isinstance(args[0], dict): # Set params by name and try to run the alg even if not all parameter values are provided, # by using the default values instead. for (name, value) in list(args[0].items()): param = alg.parameterDefinition(name) if param: parameters[param.name()] = value continue # fix_print_with_import print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) QgsMessageLog.logMessage( Processing.tr('Error: Wrong parameter value {0} for parameter {1}.').format(value, name), Processing.tr("Processing")) QgsMessageLog.logMessage(Processing.tr('Error in {0}. Wrong parameter value {1} for parameter {2}.').format( alg.name(), value, name ), Processing.tr("Processing"), QgsMessageLog.CRITICAL ) return # check for any manadatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags() & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import print('Error: Missing parameter value for parameter %s.' % param.name()) QgsMessageLog.logMessage( Processing.tr('Error: Missing parameter value for parameter {0}.').format(param.name()), Processing.tr("Processing")) return else: if len(args) != alg.countVisibleParameters(): # fix_print_with_import print('Error: Wrong number of parameters') QgsMessageLog.logMessage(Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing")) processing.algorithmHelp(algOrName) return i = 0 for param in alg.parameterDefinitions(): if not param.flags() & QgsProcessingParameterDefinition.FlagHidden: if not True: # TODO param.setValue(args[i]): # fix_print_with_import print('Error: Wrong parameter value: ' + str(args[i])) QgsMessageLog.logMessage(Processing.tr('Error: Wrong parameter value: ') + str(args[i]), Processing.tr("Processing")) return else: parameters[param.name()] = args[i] i = i + 1 for output in alg.outputs: if not output.flags() & QgsProcessingParameterDefinition.FlagHidden: if not output.setValue(args[i]): # fix_print_with_import print('Error: Wrong output value: ' + str(args[i])) QgsMessageLog.logMessage(Processing.tr('Error: Wrong output value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 context = None if kwargs is not None and 'context' in list(kwargs.keys()): context = kwargs["context"] else: context = dataobjects.createContext() ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) QgsMessageLog.logMessage(Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing")) return if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') QgsMessageLog.logMessage( Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.'), Processing.tr("Processing")) # Don't set the wait cursor twice, because then when you # restore it, it will still be a wait cursor. overrideCursor = False if iface is not None: cursor = QApplication.overrideCursor() if cursor is None or cursor == 0: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True elif cursor.shape() != Qt.WaitCursor: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True feedback = None if kwargs is not None and "feedback" in list(kwargs.keys()): feedback = kwargs["feedback"] elif iface is not None: feedback = MessageBarProgress(alg.displayName()) ret, results = execute(alg, parameters, context, feedback) if ret: if onFinish is not None: onFinish(alg, context, feedback) else: QgsMessageLog.logMessage(Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing")) if overrideCursor: QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return results
def accept(self): self.algs = [] self.load = [] self.canceled = False for row in range(self.mainWidget.tblParameters.rowCount()): alg = self.alg.getCopy() col = 0 for param in alg.parameters: if param.hidden: continue wrapper = self.mainWidget.wrappers[row][col] if not self.mainWidget.setParamValue(param, wrapper, alg): 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.outputs: if out.hidden: continue widget = self.mainWidget.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': out.value = 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.algs.append(alg) if self.alg.getVisibleOutputsCount(): widget = self.mainWidget.tblParameters.cellWidget(row, col) self.load.append(widget.currentIndex() == 0) else: self.load.append(False) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mainWidget.setEnabled(False) 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, alg in enumerate(self.algs): self.setText(self.tr('\nProcessing algorithm {0}/{1}...').format(count + 1, len(self.algs))) self.setInfo(self.tr('<b>Algorithm {0} starting...</b>').format(alg.displayName())) if execute(alg, self.feedback) and not self.canceled: if self.load[count]: handleAlgorithmResults(alg, self.feedback, False) self.setInfo(self.tr('Algorithm {0} correctly executed...').format(alg.displayName())) else: QApplication.restoreOverrideCursor() return self.finish()
def runAlgorithm(self): self.feedback = self.createFeedback() self.context = dataobjects.createContext(self.feedback) self.context.setLogLevel(self.logLevel()) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.createProcessingParameters() if checkCRS and not self.algorithm().validateInputCrs( parameters, self.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, self.context) if not ok: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.blockControlsWhileRunning() self.setExecutedAnyResult(True) self.cancelButton().setEnabled(False) self.iterateParam = None for param in self.algorithm().parameterDefinitions(): if isinstance( parameters.get(param.name(), None), QgsProcessingFeatureSourceDefinition ) and parameters[param.name( )].flags & QgsProcessingFeatureSourceDefinition.FlagCreateIndividualOutputPerInputFeature: self.iterateParam = param.name() break self.clearProgress() self.feedback.pushVersionInfo(self.algorithm().provider()) if self.algorithm().provider().warningMessage(): self.feedback.reportError( self.algorithm().provider().warningMessage()) self.setProgressText( QCoreApplication.translate('AlgorithmDialog', 'Processing algorithm…')) self.setInfo(QCoreApplication.translate( 'AlgorithmDialog', '<b>Algorithm \'{0}\' starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) self.feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.algorithm( ).parameterDefinition(k).valueAsPythonString(v, self.context)) self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') self.feedback.pushInfo('') start_time = time.time() def elapsed_time(start_time, result): delta_t = time.time() - start_time hours = int(delta_t / 3600) minutes = int((delta_t % 3600) / 60) seconds = delta_t - hours * 3600 - minutes * 60 str_hours = [self.tr("hour"), self.tr("hours")][hours > 1] str_minutes = [self.tr("minute"), self.tr("minutes")][minutes > 1] str_seconds = [self.tr("second"), self.tr("seconds")][seconds != 1] if hours > 0: elapsed = '{0} {1:0.2f} {2} ({3} {4} {5} {6} {7:0.0f} {2})'.format( result, delta_t, str_seconds, hours, str_hours, minutes, str_minutes, seconds) elif minutes > 0: elapsed = '{0} {1:0.2f} {2} ({3} {4} {5:0.0f} {2})'.format( result, delta_t, str_seconds, minutes, str_minutes, seconds) else: elapsed = '{0} {1:0.2f} {2}'.format( result, delta_t, str_seconds) return (elapsed) 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, self.context, self.feedback): self.feedback.pushInfo( self.tr( elapsed_time(start_time, 'Execution completed in'))) self.cancelButton().setEnabled(False) self.finish(True, parameters, self.context, self.feedback) else: self.cancelButton().setEnabled(False) self.resetGui() else: command = self.algorithm().asPythonCommand( parameters, self.context) if command: ProcessingLog.addToLog(command) QgsGui.instance().processingRecentAlgorithmLog().push( self.algorithm().id()) self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: self.feedback.pushInfo( self.tr( elapsed_time(start_time, 'Execution completed in'))) self.feedback.pushInfo(self.tr('Results:')) r = { k: v for k, v in results.items() if k not in ('CHILD_RESULTS', 'CHILD_INPUTS') } self.feedback.pushCommandInfo(pformat(r)) else: self.feedback.reportError( self.tr( elapsed_time(start_time, 'Execution failed after'))) self.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, self.context, self.feedback, in_place=self.in_place) self.feedback = None self.context = None if not self.in_place and not ( self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading): # Make sure the Log tab is visible before executing the algorithm self.showLog() task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, self.context, self.feedback) if task.isCanceled(): on_complete(False, {}) else: task.executed.connect(on_complete) self.setCurrentTask(task) else: self.proxy_progress = QgsProxyProgressTask( QCoreApplication.translate( "AlgorithmDialog", "Executing “{}”").format( self.algorithm().displayName())) QgsApplication.taskManager().addTask(self.proxy_progress) self.feedback.progressChanged.connect( self.proxy_progress.setProxyProgress) self.feedback_dialog = self.createProgressDialog() self.feedback_dialog.show() if self.in_place: ok, results = execute_in_place(self.algorithm(), parameters, self.context, self.feedback) else: ok, results = execute(self.algorithm(), parameters, self.context, self.feedback) self.feedback.progressChanged.disconnect() self.proxy_progress.finalize(ok) 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) except AlgorithmDialogBase.InvalidOutputExtension 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("", e.message, level=Qgis.Warning, duration=5)
def runAlgorithm(self): alg_parameters = [] feedback = self.createFeedback() load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked() project = QgsProject.instance() if load_layers else None for row in range(self.mainWidget().batchRowCount()): parameters = self.mainWidget().parametersForRow( row, destinationProject=project, warnOnInvalid=True) alg_parameters.append(parameters) task = QgsScopedProxyProgressTask( self.tr('Batch Processing - {0}').format( self.algorithm().displayName())) multi_feedback = QgsProcessingMultiStepFeedback( len(alg_parameters), feedback) feedback.progressChanged.connect(task.setProgress) with OverrideCursor(Qt.WaitCursor): self.mainWidget().setEnabled(False) self.cancelButton().setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass start_time = time.time() algorithm_results = [] for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setProgressText( QCoreApplication.translate( 'BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format( count + 1, len(alg_parameters))) self.setInfo( self.tr('<b>Algorithm {0} starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) multi_feedback.setCurrentStep(count) parameters = self.algorithm().preprocessParameters(parameters) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') # important - we create a new context for each iteration # this avoids holding onto resources and layers from earlier iterations, # and allows batch processing of many more items then is possible # if we hold on to these layers context = dataobjects.createContext(feedback) alg_start_time = time.time() ret, results = execute(self.algorithm(), parameters, context, multi_feedback) if ret: self.setInfo(QCoreApplication.translate( 'BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format( self.algorithm().displayName()), escapeHtml=False) 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: break handleAlgorithmResults(self.algorithm(), context, multi_feedback, False, parameters) feedback.pushInfo( self.tr('Batch execution completed in {0:0.2f} seconds'.format( time.time() - start_time))) task = None self.finish(algorithm_results) self.cancelButton().setEnabled(False)
def accept(self): self.algs = [] self.load = [] self.canceled = False for row in range(self.mainWidget.tblParameters.rowCount()): alg = self.alg.getCopy() # hack - remove when getCopy is removed alg.setProvider(self.alg.provider()) col = 0 for param in alg.parameters: if param.hidden: continue wrapper = self.mainWidget.wrappers[row][col] if not self.mainWidget.setParamValue(param, wrapper, alg): 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.outputs: if out.hidden: continue widget = self.mainWidget.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': out.value = 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.algs.append(alg) if self.alg.getVisibleOutputsCount(): widget = self.mainWidget.tblParameters.cellWidget(row, col) self.load.append(widget.currentIndex() == 0) else: self.load.append(False) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mainWidget.setEnabled(False) 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 context = dataobjects.createContext() for count, alg in enumerate(self.algs): self.setText( self.tr('\nProcessing algorithm {0}/{1}...').format( count + 1, len(self.algs))) self.setInfo( self.tr('<b>Algorithm {0} starting...</b>').format( alg.displayName())) if execute(alg, context, self.feedback) and not self.canceled: if self.load[count]: handleAlgorithmResults(alg, context, self.feedback, False) self.setInfo( self.tr('Algorithm {0} correctly executed...').format( alg.displayName())) else: QApplication.restoreOverrideCursor() return self.finish()
def runAlgorithm(self): self.feedback = self.createFeedback() self.context = dataobjects.createContext(self.feedback) checkCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.getParameterValues() if checkCRS and not self.algorithm().validateInputCrs(parameters, self.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, self.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) self.feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.algorithm().parameterDefinition(k).valueAsPythonString(v, self.context)) self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') self.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, self.context, self.feedback): self.feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds').format(time.time() - start_time)) self.cancelButton().setEnabled(False) self.finish(True, parameters, self.context, self.feedback) else: self.cancelButton().setEnabled(False) self.resetGui() else: command = self.algorithm().asPythonCommand(parameters, self.context) if command: ProcessingLog.addToLog(command) QgsGui.instance().processingRecentAlgorithmLog().push(self.algorithm().id()) self.cancelButton().setEnabled(self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: self.feedback.pushInfo(self.tr('Execution completed in {0:0.2f} seconds').format(time.time() - start_time)) self.feedback.pushInfo(self.tr('Results:')) self.feedback.pushCommandInfo(pformat(results)) else: self.feedback.reportError( self.tr('Execution failed after {0:0.2f} seconds').format(time.time() - start_time)) self.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) if not self.in_place: self.finish(ok, results, self.context, self.feedback) elif ok: self.close() self.feedback = None self.context = None if not self.in_place and not (self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading): # Make sure the Log tab is visible before executing the algorithm self.showLog() task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, self.context, self.feedback) if task.isCanceled(): on_complete(False, {}) else: task.executed.connect(on_complete) self.setCurrentTask(task) else: self.proxy_progress = QgsProxyProgressTask(QCoreApplication.translate("AlgorithmDialog", "Executing “{}”").format(self.algorithm().displayName())) QgsApplication.taskManager().addTask(self.proxy_progress) self.feedback.progressChanged.connect(self.proxy_progress.setProxyProgress) self.feedback_dialog = self.createProgressDialog() self.feedback_dialog.show() if self.in_place: ok, results = execute_in_place(self.algorithm(), parameters, self.context, self.feedback) else: ok, results = execute(self.algorithm(), parameters, self.context, self.feedback) self.feedback.progressChanged.disconnect() self.proxy_progress.finalize(ok) 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) except AlgorithmDialogBase.InvalidOutputExtension 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("", e.message, level=Qgis.Warning, duration=5)
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 checkExtentCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS) if checkExtentCRS and self.checkExtentCRS(): reply = QMessageBox.question( self, self.tr("Extent CRS"), self. tr('Extent parameters must use the same CRS as the input layers.\n' 'Your input layers do not have the same extent as the project, ' 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n' 'Do 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(list(buttons.values()))): button = list(buttons.values())[i] if button.isChecked(): self.iterateParam = list(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 {0} starting...</b>').format( self.alg.name)) if self.iterateParam: if executeIterating(self.alg, self.iterateParam, self.feedback): self.finish() else: QApplication.restoreOverrideCursor() self.resetGUI() else: command = self.alg.getAsCommand() if command: ProcessingLog.addToLog(ProcessingLog.LOG_ALGORITHM, command) if execute(self.alg, self.feedback): self.finish() else: QApplication.restoreOverrideCursor() self.resetGUI() 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.bar.clearWidgets() self.bar.pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description), level=QgsMessageBar.WARNING, duration=5)
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().createAlgorithmById(algOrName) if feedback is None: feedback = MessageBarProgress(alg.displayName() if alg else Processing.tr('Processing')) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') msg = Processing.tr('Error: Algorithm {0} not found\n').format(algOrName) feedback.reportError(msg) raise QgsProcessingException(msg) # check for any mandatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags() & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import msg = Processing.tr('Error: Missing parameter value for parameter {0}.').format(param.name()) print('Error: Missing parameter value for parameter %s.' % param.name()) feedback.reportError(msg) raise QgsProcessingException(msg) if context is None: context = dataobjects.createContext(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) feedback.reportError(msg) raise QgsProcessingException(msg) if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') feedback.pushInfo( Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.')) ret, results = execute(alg, parameters, context, feedback) if ret: feedback.pushInfo( Processing.tr('Results: {}').format(results)) if onFinish is not None: onFinish(alg, context, feedback) else: # auto convert layer references in results to map layers for out in alg.outputDefinitions(): if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)): result = results[out.name()] if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer(result) # transfer layer ownership out of context if layer: results[out.name()] = layer # replace layer string ref with actual layer (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg) raise QgsProcessingException(msg) if isinstance(feedback, MessageBarProgress): feedback.close() return results
def accept(self): alg_parameters = [] load = [] feedback = self.createFeedback() context = dataobjects.createContext(feedback) for row in range(self.mainWidget.tblParameters.rowCount()): col = 0 parameters = {} for param in self.alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination(): continue wrapper = self.mainWidget.wrappers[row][col] parameters[param.name()] = wrapper.value() if not param.checkValueIsAcceptable(wrapper.value(), context): self.bar.pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format( param.description(), row + 1), level=QgsMessageBar.WARNING, duration=5) return col += 1 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 param.checkValueIsAcceptable(text, context): if isinstance(out, (QgsProcessingParameterRasterDestination, 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) return alg_parameters.append(parameters) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mainWidget.setEnabled(False) self.buttonCancel.setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass 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) 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: break feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time))) handleAlgorithmResults(self.alg, context, feedback, False) self.finish(algorithm_results) self.buttonCancel.setEnabled(False)
def accept(self): alg_parameters = [] feedback = self.createFeedback() load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked() project = QgsProject.instance() if load_layers else None for row in range(self.mainWidget().tblParameters.rowCount()): col = 0 parameters = {} for param in self.algorithm().parameterDefinitions(): if param.flags( ) & QgsProcessingParameterDefinition.FlagHidden or param.isDestination( ): continue wrapper = self.mainWidget().wrappers[row][col] parameters[param.name()] = wrapper.value() if not param.checkValueIsAcceptable(wrapper.value()): self.messageBar().pushMessage( "", self.tr( 'Wrong or missing parameter value: {0} (row {1})'). format(param.description(), row + 1), level=Qgis.Warning, duration=5) return col += 1 count_visible_outputs = 0 for out in self.algorithm().destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue count_visible_outputs += 1 widget = self.mainWidget().tblParameters.cellWidget(row, col) text = widget.getValue() if out.checkValueIsAcceptable(text): if isinstance(out, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink)): # load rasters and sinks on completion parameters[ out.name()] = QgsProcessingOutputLayerDefinition( text, project) else: parameters[out.name()] = text col += 1 else: self.messageBar().pushMessage( "", self.tr('Wrong or missing output value: {0} (row {1})' ).format(out.description(), row + 1), level=Qgis.Warning, duration=5) return alg_parameters.append(parameters) with OverrideCursor(Qt.WaitCursor): self.mainWidget().setEnabled(False) self.cancelButton().setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass start_time = time.time() algorithm_results = [] for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setProgressText( QCoreApplication.translate( 'BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format( count + 1, len(alg_parameters))) self.setInfo( self.tr('<b>Algorithm {0} starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) parameters = self.algorithm().preprocessParameters(parameters) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') # important - we create a new context for each iteration # this avoids holding onto resources and layers from earlier iterations, # and allows batch processing of many more items then is possible # if we hold on to these layers context = dataobjects.createContext(feedback) alg_start_time = time.time() ret, results = execute(self.algorithm(), parameters, context, feedback) if ret: self.setInfo(QCoreApplication.translate( 'BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format( self.algorithm().displayName()), escapeHtml=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: break handleAlgorithmResults(self.algorithm(), context, feedback, False) feedback.pushInfo( self.tr('Batch execution completed in {0:0.2f} seconds'.format( time.time() - start_time))) self.finish(algorithm_results) self.cancelButton().setEnabled(False)
def runAlgorithm(algOrName, onFinish, *args, **kwargs): if isinstance(algOrName, GeoAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') QgsMessageLog.logMessage( Processing.tr('Error: Algorithm {0} not found\n').format( algOrName), Processing.tr("Processing")) return parameters = {} if len(args) == 1 and isinstance(args[0], dict): # Set params by name and try to run the alg even if not all parameter values are provided, # by using the default values instead. for (name, value) in list(args[0].items()): param = alg.parameterDefinition(name) if param: parameters[param.name()] = value continue # fix_print_with_import print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) QgsMessageLog.logMessage( Processing.tr( 'Error: Wrong parameter value {0} for parameter {1}.'). format(value, name), Processing.tr("Processing")) QgsMessageLog.logMessage( Processing. tr('Error in {0}. Wrong parameter value {1} for parameter {2}.' ).format(alg.name(), value, name), Processing.tr("Processing"), QgsMessageLog.CRITICAL) return # check for any manadatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags( ) & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import print( 'Error: Missing parameter value for parameter %s.' % param.name()) QgsMessageLog.logMessage( Processing. tr('Error: Missing parameter value for parameter {0}.' ).format(param.name()), Processing.tr("Processing")) return else: if len(args) != alg.countVisibleParameters(): # fix_print_with_import print('Error: Wrong number of parameters') QgsMessageLog.logMessage( Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing")) processing.algorithmHelp(algOrName) return i = 0 for param in alg.parameterDefinitions(): if not param.flags( ) & QgsProcessingParameterDefinition.FlagHidden: if not True: # TODO param.setValue(args[i]): # fix_print_with_import print('Error: Wrong parameter value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong parameter value: ') + str(args[i]), Processing.tr("Processing")) return else: parameters[param.name()] = args[i] i = i + 1 for output in alg.outputs: if not output.flags( ) & QgsProcessingParameterDefinition.FlagHidden: if not output.setValue(args[i]): # fix_print_with_import print('Error: Wrong output value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong output value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 context = None if kwargs is not None and 'context' in list(kwargs.keys()): context = kwargs["context"] else: context = dataobjects.createContext() ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) QgsMessageLog.logMessage( Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing")) return if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') QgsMessageLog.logMessage( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' ), Processing.tr("Processing")) # Don't set the wait cursor twice, because then when you # restore it, it will still be a wait cursor. overrideCursor = False if iface is not None: cursor = QApplication.overrideCursor() if cursor is None or cursor == 0: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True elif cursor.shape() != Qt.WaitCursor: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True feedback = None if kwargs is not None and "feedback" in list(kwargs.keys()): feedback = kwargs["feedback"] elif iface is not None: feedback = MessageBarProgress(alg.displayName()) ret, results = execute(alg, parameters, context, feedback) if ret: if onFinish is not None: onFinish(alg, context, feedback) else: QgsMessageLog.logMessage( Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing")) if overrideCursor: QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return results
def executeAlgorithm(self): config = {} if self.in_place_mode: config['IN_PLACE'] = True alg = self.algorithmTree.selectedAlgorithm().create( config) if self.algorithmTree.selectedAlgorithm( ) is not None else None if alg is not None: ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if self.in_place_mode and not [ d for d in alg.parameterDefinitions() if d.name() not in ('INPUT', 'OUTPUT') ]: parameters = {} feedback = MessageBarProgress(algname=alg.displayName()) ok, results = execute_in_place(alg, parameters, feedback=feedback) if ok: iface.messageBar().pushSuccess( '', self.tr( '{algname} completed. %n feature(s) processed.', n=results['__count']).format( algname=alg.displayName())) feedback.close() # MessageBarProgress handles errors return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg, self.in_place_mode, iface.mainWindow()) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress(algname=alg.displayName()) context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def runAlgorithm(algOrName, onFinish, *args, **kwargs): if isinstance(algOrName, GeoAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') QgsMessageLog.logMessage( Processing.tr('Error: Algorithm {0} not found\n').format( algOrName), Processing.tr("Processing")) return # hack - remove when getCopy is removed provider = alg.provider() alg = alg.getCopy() #hack pt2 alg.setProvider(provider) if len(args) == 1 and isinstance(args[0], dict): # Set params by name and try to run the alg even if not all parameter values are provided, # by using the default values instead. setParams = [] for (name, value) in list(args[0].items()): param = alg.getParameterFromName(name) if param and param.setValue(value): setParams.append(name) continue output = alg.getOutputFromName(name) if output and output.setValue(value): continue # fix_print_with_import print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) QgsMessageLog.logMessage( Processing.tr( 'Error: Wrong parameter value {0} for parameter {1}.'). format(value, name), Processing.tr("Processing")) QgsMessageLog.logMessage( Processing. tr('Error in {0}. Wrong parameter value {1} for parameter {2}.' ).format(alg.name(), value, name), Processing.tr("Processing"), QgsMessageLog.CRITICAL) return # fill any missing parameters with default values if allowed for param in alg.parameters: if param.name not in setParams: if not param.setDefaultValue(): # fix_print_with_import print( 'Error: Missing parameter value for parameter %s.' % param.name) QgsMessageLog.logMessage( Processing. tr('Error: Missing parameter value for parameter {0}.' ).format(param.name), Processing.tr("Processing")) return else: if len(args) != alg.getVisibleParametersCount( ) + alg.getVisibleOutputsCount(): # fix_print_with_import print('Error: Wrong number of parameters') QgsMessageLog.logMessage( Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing")) processing.algorithmHelp(algOrName) return i = 0 for param in alg.parameters: if not param.hidden: if not param.setValue(args[i]): # fix_print_with_import print('Error: Wrong parameter value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong parameter value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 for output in alg.outputs: if not output.hidden: if not output.setValue(args[i]): # fix_print_with_import print('Error: Wrong output value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong output value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 context = None if kwargs is not None and 'context' in list(kwargs.keys()): context = kwargs["context"] else: context = dataobjects.createContext() msg = alg._checkParameterValuesBeforeExecuting(context) if msg: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) QgsMessageLog.logMessage( Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing")) return if not alg.checkInputCRS(context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') QgsMessageLog.logMessage( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' ), Processing.tr("Processing")) # Don't set the wait cursor twice, because then when you # restore it, it will still be a wait cursor. overrideCursor = False if iface is not None: cursor = QApplication.overrideCursor() if cursor is None or cursor == 0: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True elif cursor.shape() != Qt.WaitCursor: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True feedback = None if kwargs is not None and "feedback" in list(kwargs.keys()): feedback = kwargs["feedback"] elif iface is not None: feedback = MessageBarProgress(alg.displayName()) ret = execute(alg, context, feedback) if ret: if onFinish is not None: onFinish(alg, context, feedback) else: QgsMessageLog.logMessage( Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing")) if overrideCursor: QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return alg
def runAlgorithm(self): self.feedback = self.createFeedback() self.context = dataobjects.createContext(self.feedback) self.context.setLogLevel(self.logLevel()) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: # messy as all heck, but we don't want to call the dialog's implementation of # createProcessingParameters as we want to catch the exceptions raised by the # parameter panel instead... parameters = {} if self.mainWidget() is None else self.mainWidget( ).createProcessingParameters() if checkCRS and not self.algorithm().validateInputCrs( parameters, self.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, self.context) if not ok: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.blockControlsWhileRunning() self.setExecutedAnyResult(True) self.cancelButton().setEnabled(False) self.iterateParam = None for param in self.algorithm().parameterDefinitions(): if isinstance( parameters.get(param.name(), None), QgsProcessingFeatureSourceDefinition ) and parameters[param.name( )].flags & QgsProcessingFeatureSourceDefinition.FlagCreateIndividualOutputPerInputFeature: self.iterateParam = param.name() break self.clearProgress() self.feedback.pushVersionInfo(self.algorithm().provider()) if self.algorithm().provider().warningMessage(): self.feedback.reportError( self.algorithm().provider().warningMessage()) self.feedback.pushInfo( QCoreApplication.translate('AlgorithmDialog', 'Algorithm started at: {}').format( datetime.datetime.now().replace( microsecond=0).isoformat())) self.setInfo(QCoreApplication.translate( 'AlgorithmDialog', '<b>Algorithm \'{0}\' starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) self.feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.algorithm( ).parameterDefinition(k).valueAsPythonString(v, self.context)) self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') self.feedback.pushInfo('') start_time = time.time() def elapsed_time(start_time, result): delta_t = time.time() - start_time hours = int(delta_t / 3600) minutes = int((delta_t % 3600) / 60) seconds = delta_t - hours * 3600 - minutes * 60 str_hours = [self.tr("hour"), self.tr("hours")][hours > 1] str_minutes = [self.tr("minute"), self.tr("minutes")][minutes > 1] str_seconds = [self.tr("second"), self.tr("seconds")][seconds != 1] if hours > 0: elapsed = '{0} {1:0.2f} {2} ({3} {4} {5} {6} {7:0.0f} {2})'.format( result, delta_t, str_seconds, hours, str_hours, minutes, str_minutes, seconds) elif minutes > 0: elapsed = '{0} {1:0.2f} {2} ({3} {4} {5:0.0f} {2})'.format( result, delta_t, str_seconds, minutes, str_minutes, seconds) else: elapsed = '{0} {1:0.2f} {2}'.format( result, delta_t, str_seconds) return elapsed 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, self.context, self.feedback): self.feedback.pushInfo( self.tr( elapsed_time(start_time, 'Execution completed in'))) self.cancelButton().setEnabled(False) self.finish(True, parameters, self.context, self.feedback) else: self.cancelButton().setEnabled(False) self.resetGui() else: self.history_details = { 'python_command': self.algorithm().asPythonCommand(parameters, self.context), 'algorithm_id': self.algorithm().id(), 'parameters': self.algorithm().asMap(parameters, self.context) } process_command, command_ok = self.algorithm( ).asQgisProcessCommand(parameters, self.context) if command_ok: self.history_details['process_command'] = process_command self.history_log_id, _ = QgsGui.historyProviderRegistry( ).addEntry('processing', self.history_details) QgsGui.instance().processingRecentAlgorithmLog().push( self.algorithm().id()) self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: self.feedback.pushInfo( self.tr( elapsed_time(start_time, 'Execution completed in'))) self.feedback.pushInfo(self.tr('Results:')) r = { k: v for k, v in results.items() if k not in ('CHILD_RESULTS', 'CHILD_INPUTS') } self.feedback.pushCommandInfo(pformat(r)) else: self.feedback.reportError( self.tr( elapsed_time(start_time, 'Execution failed after'))) self.feedback.pushInfo('') if self.history_log_id is not None: # can't deepcopy this! self.history_details['results'] = { k: v for k, v in results.items() if k != 'CHILD_INPUTS' } QgsGui.historyProviderRegistry().updateEntry( self.history_log_id, self.history_details) 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, self.context, self.feedback, in_place=self.in_place) self.feedback = None self.context = None if not self.in_place and not ( self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading): # Make sure the Log tab is visible before executing the algorithm self.showLog() task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, self.context, self.feedback) if task.isCanceled(): on_complete(False, {}) else: task.executed.connect(on_complete) self.setCurrentTask(task) else: self.proxy_progress = QgsProxyProgressTask( QCoreApplication.translate( "AlgorithmDialog", "Executing “{}”").format( self.algorithm().displayName())) QgsApplication.taskManager().addTask(self.proxy_progress) self.feedback.progressChanged.connect( self.proxy_progress.setProxyProgress) self.feedback_dialog = self.createProgressDialog() self.feedback_dialog.show() if self.in_place: ok, results = execute_in_place(self.algorithm(), parameters, self.context, self.feedback) else: ok, results = execute(self.algorithm(), parameters, self.context, self.feedback) self.feedback.progressChanged.disconnect() self.proxy_progress.finalize(ok) on_complete(ok, results) except AlgorithmDialogBase.InvalidParameterValue as e: self.flag_invalid_parameter_value(e.parameter.description(), e.widget) except AlgorithmDialogBase.InvalidOutputExtension as e: self.flag_invalid_output_extension(e.message, e.widget)
def runAlgorithm(algOrName, onFinish, *args, **kwargs): if isinstance(algOrName, GeoAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') QgsMessageLog.logMessage(Processing.tr('Error: Algorithm {0} not found\n').format(algOrName), Processing.tr("Processing")) return alg = alg.getCopy() if len(args) == 1 and isinstance(args[0], dict): # Set params by name and try to run the alg even if not all parameter values are provided, # by using the default values instead. setParams = [] for (name, value) in list(args[0].items()): param = alg.getParameterFromName(name) if param and param.setValue(value): setParams.append(name) continue output = alg.getOutputFromName(name) if output and output.setValue(value): continue # fix_print_with_import print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) QgsMessageLog.logMessage( Processing.tr('Error: Wrong parameter value {0} for parameter {1}.').format(value, name), Processing.tr("Processing")) ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, Processing.tr('Error in {0}. Wrong parameter value {1} for parameter {2}.').format( alg.name(), value, name ) ) return # fill any missing parameters with default values if allowed for param in alg.parameters: if param.name not in setParams: if not param.setDefaultValue(): # fix_print_with_import print('Error: Missing parameter value for parameter %s.' % param.name) QgsMessageLog.logMessage( Processing.tr('Error: Missing parameter value for parameter {0}.').format(param.name), Processing.tr("Processing")) ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, Processing.tr('Error in {0}. Missing parameter value for parameter {1}.').format( alg.name(), param.name) ) return else: if len(args) != alg.getVisibleParametersCount() + alg.getVisibleOutputsCount(): # fix_print_with_import print('Error: Wrong number of parameters') QgsMessageLog.logMessage(Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing")) processing.algorithmHelp(algOrName) return i = 0 for param in alg.parameters: if not param.hidden: if not param.setValue(args[i]): # fix_print_with_import print('Error: Wrong parameter value: ' + str(args[i])) QgsMessageLog.logMessage(Processing.tr('Error: Wrong parameter value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 for output in alg.outputs: if not output.hidden: if not output.setValue(args[i]): # fix_print_with_import print('Error: Wrong output value: ' + str(args[i])) QgsMessageLog.logMessage(Processing.tr('Error: Wrong output value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 msg = alg._checkParameterValuesBeforeExecuting() if msg: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) QgsMessageLog.logMessage(Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing")) return if not alg.checkInputCRS(): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') QgsMessageLog.logMessage( Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.'), Processing.tr("Processing")) # Don't set the wait cursor twice, because then when you # restore it, it will still be a wait cursor. overrideCursor = False if iface is not None: cursor = QApplication.overrideCursor() if cursor is None or cursor == 0: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True elif cursor.shape() != Qt.WaitCursor: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True feedback = None if kwargs is not None and "feedback" in list(kwargs.keys()): feedback = kwargs["feedback"] elif iface is not None: feedback = MessageBarProgress(alg.displayName()) ret = execute(alg, feedback) if ret: if onFinish is not None: onFinish(alg, feedback) else: QgsMessageLog.logMessage(Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing")) if overrideCursor: QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return alg
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().createAlgorithmById(algOrName) if feedback is None: feedback = QgsProcessingFeedback() if alg is None: msg = Processing.tr('Error: Algorithm {0} not found\n').format(algOrName) feedback.reportError(msg) raise QgsProcessingException(msg) if context is None: context = dataobjects.createContext(feedback) if context.feedback() is None: context.setFeedback(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) feedback.reportError(msg) raise QgsProcessingException(msg) if not alg.validateInputCrs(parameters, context): feedback.pushInfo( Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.')) ret, results = execute(alg, parameters, context, feedback) if ret: feedback.pushInfo( Processing.tr('Results: {}').format(results)) if onFinish is not None: onFinish(alg, context, feedback) else: # auto convert layer references in results to map layers for out in alg.outputDefinitions(): if out.name() not in results: continue if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)): result = results[out.name()] if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer(result) # transfer layer ownership out of context if layer: results[out.name()] = layer # replace layer string ref with actual layer (+ownership) elif isinstance(out, QgsProcessingOutputMultipleLayers): result = results[out.name()] if result: layers_result = [] for l in result: if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer(l) # transfer layer ownership out of context if layer: layers_result.append(layer) else: layers_result.append(l) else: layers_result.append(l) results[out.name()] = layers_result # replace layers strings ref with actual layers (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg) raise QgsProcessingException(msg) if isinstance(feedback, MessageBarProgress): feedback.close() return results
def executeAlgorithm(self, alg_id, parent, in_place=False, as_batch=False): """Executes a project model with GUI interaction if needed. :param alg_id: algorithm id :type alg_id: string :param parent: parent widget :type parent: QWidget :param in_place: in place flag, defaults to False :type in_place: bool, optional :param as_batch: execute as batch flag, defaults to False :type as_batch: bool, optional """ config = {} if in_place: config['IN_PLACE'] = True alg = QgsApplication.instance().processingRegistry( ).createAlgorithmById(alg_id, config) if alg is not None: ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if as_batch: dlg = BatchAlgorithmDialog(alg, iface.mainWindow()) dlg.setAttribute(Qt.WA_DeleteOnClose) dlg.show() dlg.exec_() else: in_place_input_parameter_name = 'INPUT' if hasattr(alg, 'inputParameterName'): in_place_input_parameter_name = alg.inputParameterName() if in_place and not [ d for d in alg.parameterDefinitions() if d.name() not in (in_place_input_parameter_name, 'OUTPUT') ]: parameters = {} feedback = MessageBarProgress(algname=alg.displayName()) ok, results = execute_in_place(alg, parameters, feedback=feedback) if ok: iface.messageBar().pushSuccess( '', self. tr('{algname} completed. %n feature(s) processed.', n=results['__count']).format( algname=alg.displayName())) feedback.close() # MessageBarProgress handles errors return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(parent) if not dlg: dlg = AlgorithmDialog(alg, in_place, iface.mainWindow()) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except Exception: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress(algname=alg.displayName()) context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def test_check_validity(self): """Test that the output invalid contains the error reason""" polygon_layer = self._make_layer('Polygon') self.assertTrue(polygon_layer.startEditing()) f = QgsFeature(polygon_layer.fields()) f.setAttributes([1]) # Flake! f.setGeometry( QgsGeometry.fromWkt('POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))')) self.assertTrue(f.isValid()) f2 = QgsFeature(polygon_layer.fields()) f2.setAttributes([1]) f2.setGeometry( QgsGeometry.fromWkt( 'POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))')) self.assertTrue(f2.isValid()) self.assertTrue(polygon_layer.addFeatures([f, f2])) polygon_layer.commitChanges() polygon_layer.rollBack() self.assertEqual(polygon_layer.featureCount(), 2) QgsProject.instance().addMapLayers([polygon_layer]) alg = self.registry.createAlgorithmById('qgis:checkvalidity') context = QgsProcessingContext() context.setProject(QgsProject.instance()) feedback = ConsoleFeedBack() self.assertIsNotNone(alg) parameters = {} parameters['INPUT_LAYER'] = polygon_layer.id() parameters['VALID_OUTPUT'] = 'memory:' parameters['INVALID_OUTPUT'] = 'memory:' parameters['ERROR_OUTPUT'] = 'memory:' # QGIS method parameters['METHOD'] = 1 ok, results = execute(alg, parameters, context=context, feedback=feedback) self.assertTrue(ok) invalid_layer = QgsProcessingUtils.mapLayerFromString( results['INVALID_OUTPUT'], context) self.assertEqual(invalid_layer.fields().names()[-1], '_errors') self.assertEqual(invalid_layer.featureCount(), 1) f = next(invalid_layer.getFeatures()) self.assertEqual(f.attributes(), [ 1, 'segments 0 and 2 of line 0 intersect at 1, 1\nGeometry has 1 errors.' ]) # GEOS method parameters['METHOD'] = 2 ok, results = execute(alg, parameters, context=context, feedback=feedback) self.assertTrue(ok) invalid_layer = QgsProcessingUtils.mapLayerFromString( results['INVALID_OUTPUT'], context) self.assertEqual(invalid_layer.fields().names()[-1], '_errors') self.assertEqual(invalid_layer.featureCount(), 1) f = next(invalid_layer.getFeatures()) self.assertEqual(f.attributes(), [1, 'Self-intersection'])
def runAlgorithm(self): alg_parameters = [] feedback = self.createFeedback() load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked() project = QgsProject.instance() if load_layers else None for row in range(self.mainWidget().tblParameters.rowCount()): col = 0 parameters = {} for param in self.algorithm().parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination(): continue wrapper = self.mainWidget().wrappers[row][col] parameters[param.name()] = wrapper.parameterValue() if not param.checkValueIsAcceptable(wrapper.parameterValue()): self.messageBar().pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format( param.description(), row + 1), level=Qgis.Warning, duration=5) return col += 1 count_visible_outputs = 0 for out in self.algorithm().destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue count_visible_outputs += 1 widget = self.mainWidget().tblParameters.cellWidget(row, col) text = widget.getValue() if out.checkValueIsAcceptable(text): if isinstance(out, (QgsProcessingParameterRasterDestination, QgsProcessingParameterVectorDestination, QgsProcessingParameterFeatureSink)): # load rasters and sinks on completion parameters[out.name()] = QgsProcessingOutputLayerDefinition(text, project) else: parameters[out.name()] = text col += 1 else: self.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format( out.description(), row + 1), level=Qgis.Warning, duration=5) return alg_parameters.append(parameters) task = QgsScopedProxyProgressTask(self.tr('Batch Processing - {0}').format(self.algorithm().displayName())) multi_feedback = QgsProcessingMultiStepFeedback(len(alg_parameters), feedback) feedback.progressChanged.connect(task.setProgress) with OverrideCursor(Qt.WaitCursor): self.mainWidget().setEnabled(False) self.cancelButton().setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass start_time = time.time() algorithm_results = [] for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setProgressText(QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format(count + 1, len(alg_parameters))) self.setInfo(self.tr('<b>Algorithm {0} starting…</b>').format(self.algorithm().displayName()), escapeHtml=False) multi_feedback.setCurrentStep(count) parameters = self.algorithm().preprocessParameters(parameters) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') # important - we create a new context for each iteration # this avoids holding onto resources and layers from earlier iterations, # and allows batch processing of many more items then is possible # if we hold on to these layers context = dataobjects.createContext(feedback) alg_start_time = time.time() ret, results = execute(self.algorithm(), parameters, context, multi_feedback) if ret: self.setInfo(QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format(self.algorithm().displayName()), escapeHtml=False) 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: break handleAlgorithmResults(self.algorithm(), context, multi_feedback, False) feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time))) task = None self.finish(algorithm_results) self.cancelButton().setEnabled(False)
def runAlgorithm(self): alg_parameters = [] feedback = self.createFeedback() load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked() project = QgsProject.instance() if load_layers else None for row in range(self.mainWidget().batchRowCount()): parameters = self.mainWidget().parametersForRow(row, destinationProject=project, warnOnInvalid=True) alg_parameters.append(parameters) task = QgsScopedProxyProgressTask(self.tr('Batch Processing - {0}').format(self.algorithm().displayName())) multi_feedback = QgsProcessingMultiStepFeedback(len(alg_parameters), feedback) feedback.progressChanged.connect(task.setProgress) with OverrideCursor(Qt.WaitCursor): self.mainWidget().setEnabled(False) self.cancelButton().setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass start_time = time.time() algorithm_results = [] for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setProgressText( QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format( count + 1, len(alg_parameters))) self.setInfo(self.tr('<b>Algorithm {0} starting…</b>').format(self.algorithm().displayName()), escapeHtml=False) multi_feedback.setCurrentStep(count) parameters = self.algorithm().preprocessParameters(parameters) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') # important - we create a new context for each iteration # this avoids holding onto resources and layers from earlier iterations, # and allows batch processing of many more items then is possible # if we hold on to these layers context = dataobjects.createContext(feedback) alg_start_time = time.time() ret, results = execute(self.algorithm(), parameters, context, multi_feedback) if ret: self.setInfo( QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format( self.algorithm().displayName()), escapeHtml=False) 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: break handleAlgorithmResults(self.algorithm(), context, multi_feedback, False, parameters) feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time))) task = None self.finish(algorithm_results) self.cancelButton().setEnabled(False)
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().createAlgorithmById( algOrName) if feedback is None: feedback = MessageBarProgress( alg.displayName() if alg else Processing.tr('Processing')) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') msg = Processing.tr('Error: Algorithm {0} not found\n').format( algOrName) feedback.reportError(msg) raise QgsProcessingException(msg) # check for any mandatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags( ) & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import msg = Processing.tr( 'Error: Missing parameter value for parameter {0}.' ).format(param.name()) print('Error: Missing parameter value for parameter %s.' % param.name()) feedback.reportError(msg) raise QgsProcessingException(msg) if context is None: context = dataobjects.createContext(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) feedback.reportError(msg) raise QgsProcessingException(msg) if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') feedback.pushInfo( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' )) ret, results = execute(alg, parameters, context, feedback) if ret: feedback.pushInfo(Processing.tr('Results: {}').format(results)) if onFinish is not None: onFinish(alg, context, feedback) else: # auto convert layer references in results to map layers for out in alg.outputDefinitions(): if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)): result = results[out.name()] if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer( result ) # transfer layer ownership out of context if layer: results[out.name( )] = layer # replace layer string ref with actual layer (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg) raise QgsProcessingException(msg) if isinstance(feedback, MessageBarProgress): feedback.close() return results
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('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 checkExtentCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS) # TODO if False and checkExtentCRS and self.checkExtentCRS(): reply = QMessageBox.question( self, self.tr("Extent CRS"), self. tr('Extent parameters must use the same CRS as the input layers.\n' 'Your input layers do not have the same extent as the project, ' 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n' 'Do you want to continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.algorithm().checkParameterValues( parameters, context) if msg: 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(self.tr('Processing algorithm...')) self.setInfo( self.tr('<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)