[processing][needs-docs] Resurrect ability to convert models to scripts

Brings back QGIS 2.18's ability to directly convert a Processing model
to an equivalent Processing Python script algorithm, correctly
updated and working in the 3.x API.

Available from the model dialog, and from the right-click context
menu on an existing model.

Sponsored by Solspec
This commit is contained in:
Nyall Dawson 2019-02-01 12:22:59 +10:00
parent bc76678e74
commit 56e465cc8a
4 changed files with 77 additions and 7 deletions

View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
EditModelAction.py
---------------------
Date : February 2019
Copyright : (C) 2019 by Nyall Dawson
Email : nyall dot dawson 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__ = 'Nyall Dawson'
__date__ = 'February 2019'
__copyright__ = '(C) 2019, Nyall Dawson'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import QgsProcessingModelAlgorithm, QgsProcessing, QgsApplication
from processing.gui.ContextAction import ContextAction
from processing.script.ScriptEditorDialog import ScriptEditorDialog
class ExportModelAsPythonScriptAction(ContextAction):
def __init__(self):
super().__init__()
self.name = QCoreApplication.translate('ExportModelAsPythonScriptAction', 'Export Model as Python Algorithm…')
def isEnabled(self):
return isinstance(self.itemData, QgsProcessingModelAlgorithm)
def icon(self):
return QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')
def execute(self):
alg = self.itemData
dlg = ScriptEditorDialog(None)
dlg.editor.setText('\n'.join(alg.asPythonCode(QgsProcessing.PythonQgsProcessingAlgorithmSubclass, 4)))
dlg.show()

View File

@ -47,6 +47,7 @@ from processing.modeler.AddModelFromFileAction import AddModelFromFileAction
from processing.modeler.CreateNewModelAction import CreateNewModelAction
from processing.modeler.DeleteModelAction import DeleteModelAction
from processing.modeler.EditModelAction import EditModelAction
from processing.modeler.ExportModelAsPythonScriptAction import ExportModelAsPythonScriptAction
from processing.modeler.OpenModelFromFileAction import OpenModelFromFileAction
from processing.modeler.exceptions import WrongModelException
from processing.modeler.ModelerUtils import ModelerUtils
@ -59,7 +60,9 @@ class ModelerAlgorithmProvider(QgsProcessingProvider):
def __init__(self):
super().__init__()
self.actions = [CreateNewModelAction(), OpenModelFromFileAction(), AddModelFromFileAction()]
self.contextMenuActions = [EditModelAction(), DeleteModelAction()]
sep_action = ContextAction()
sep_action.is_separator = True
self.contextMenuActions = [EditModelAction(), DeleteModelAction(), sep_action, ExportModelAsPythonScriptAction()]
self.algs = []
self.isLoading = False

View File

@ -61,7 +61,9 @@ from qgis.PyQt.QtWidgets import (QGraphicsView,
QVBoxLayout,
QGridLayout,
QFrame,
QLineEdit)
QLineEdit,
QToolButton,
QAction)
from qgis.PyQt.QtGui import (QIcon,
QImage,
QPainter,
@ -70,7 +72,7 @@ from qgis.PyQt.QtSvg import QSvgGenerator
from qgis.PyQt.QtPrintSupport import QPrinter
from qgis.core import (Qgis,
QgsApplication,
QgsProcessingAlgorithm,
QgsProcessing,
QgsProject,
QgsSettings,
QgsMessageLog,
@ -92,6 +94,7 @@ from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.modeler.ModelerUtils import ModelerUtils
from processing.modeler.ModelerScene import ModelerScene
from processing.modeler.ProjectProvider import PROJECT_PROVIDER_ID
from processing.script.ScriptEditorDialog import ScriptEditorDialog
from qgis.utils import iface
@ -253,6 +256,13 @@ class ModelerDialog(BASE, WIDGET):
self.mToolbar.setIconSize(iface.iconSize())
self.setStyleSheet(iface.mainWindow().styleSheet())
self.toolbutton_export_to_script = QToolButton()
self.toolbutton_export_to_script.setPopupMode(QToolButton.InstantPopup)
self.export_to_script_algorithm_action = QAction(self.tr('Export as Script Algorithm…'))
self.toolbutton_export_to_script.addActions([self.export_to_script_algorithm_action])
self.mToolbar.insertWidget(self.mActionExportImage, self.toolbutton_export_to_script)
self.export_to_script_algorithm_action.triggered.connect(self.export_as_script_algorithm)
self.mActionOpen.setIcon(
QgsApplication.getThemeIcon('/mActionFileOpen.svg'))
self.mActionSave.setIcon(
@ -275,8 +285,8 @@ class ModelerDialog(BASE, WIDGET):
QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg'))
self.mActionExportSvg.setIcon(
QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg'))
#self.mActionExportPython.setIcon(
# QgsApplication.getThemeIcon('/mActionSaveAsPython.svg'))
self.toolbutton_export_to_script.setIcon(
QgsApplication.getThemeIcon('/mActionSaveAsPython.svg'))
self.mActionEditHelp.setIcon(
QgsApplication.getThemeIcon('/mActionEditHelpContent.svg'))
self.mActionRun.setIcon(
@ -814,3 +824,9 @@ class ModelerDialog(BASE, WIDGET):
newX = MARGIN + BOX_WIDTH / 2
newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2
return QPointF(newX, newY)
def export_as_script_algorithm(self):
dlg = ScriptEditorDialog(None)
dlg.editor.setText('\n'.join(self.model.asPythonCode(QgsProcessing.PythonQgsProcessingAlgorithmSubclass, 4)))
dlg.show()

View File

@ -166,10 +166,10 @@
</action>
<action name="mActionExportPython">
<property name="text">
<string>Export as Python script…</string>
<string>Export as Python Script…</string>
</property>
<property name="toolTip">
<string>Export as Python script</string>
<string>Export as Python Script</string>
</property>
</action>
<action name="mActionEditHelp">