mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
[processing] brought back 'export model as python' functionality
This commit is contained in:
parent
b05fb0b5b0
commit
227af8ac8e
@ -127,6 +127,9 @@ class ParameterBoolean(Parameter):
|
||||
self.value = bool(value)
|
||||
return True
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=boolean ' + str(self.default)
|
||||
|
||||
|
||||
class ParameterCrs(Parameter):
|
||||
|
||||
@ -153,6 +156,8 @@ class ParameterCrs(Parameter):
|
||||
def getValueAsCommandLineParameter(self):
|
||||
return '"' + unicode(self.value) + '"'
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=crs ' + str(self.default)
|
||||
|
||||
class ParameterDataObject(Parameter):
|
||||
|
||||
@ -197,6 +202,8 @@ class ParameterExtent(Parameter):
|
||||
def getValueAsCommandLineParameter(self):
|
||||
return '"' + unicode(self.value) + '"'
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=extent'
|
||||
|
||||
class ParameterFile(Parameter):
|
||||
|
||||
@ -225,6 +232,12 @@ class ParameterFile(Parameter):
|
||||
else:
|
||||
return 'file'
|
||||
|
||||
def getAsScriptCode(self):
|
||||
if self.isFolder:
|
||||
return '##' + self.name + '=folder'
|
||||
else:
|
||||
return '##' + self.name + '=file'
|
||||
|
||||
|
||||
class ParameterFixedTable(Parameter):
|
||||
|
||||
@ -406,6 +419,13 @@ class ParameterMultipleInput(ParameterDataObject):
|
||||
else:
|
||||
return 'any vectors'
|
||||
|
||||
def getAsScriptCode(self):
|
||||
if self.datatype == self.TYPE_RASTER:
|
||||
return '##' + self.name + '=multiple raster'
|
||||
if self.datatype == self.TYPE_FILE:
|
||||
return '##' + self.name + '=multiple file'
|
||||
else:
|
||||
return '##' + self.name + '=multiple vector'
|
||||
|
||||
class ParameterNumber(Parameter):
|
||||
|
||||
@ -451,6 +471,9 @@ class ParameterNumber(Parameter):
|
||||
return False
|
||||
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=number ' + str(self.default)
|
||||
|
||||
class ParameterRange(Parameter):
|
||||
|
||||
def __init__(self, name='', description='', default='0,1', optional=False):
|
||||
@ -543,6 +566,9 @@ class ParameterRaster(ParameterDataObject):
|
||||
exts[i] = self.tr('%s files(*.%s)', 'ParameterRaster') % (exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=raster'
|
||||
|
||||
|
||||
class ParameterSelection(Parameter):
|
||||
|
||||
@ -609,6 +635,8 @@ class ParameterString(Parameter):
|
||||
ParameterString.ESCAPED_NEWLINE)) + '"'
|
||||
if self.value is not None else unicode(None))
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=string ' + self.default
|
||||
|
||||
class ParameterTable(ParameterDataObject):
|
||||
|
||||
@ -674,6 +702,9 @@ class ParameterTable(ParameterDataObject):
|
||||
exts[i] = self.tr('%s files(*.%s)', 'ParameterTable') % (exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=table'
|
||||
|
||||
|
||||
class ParameterTableField(Parameter):
|
||||
|
||||
@ -715,6 +746,9 @@ class ParameterTableField(Parameter):
|
||||
else:
|
||||
return 'any'
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=field ' + self.parent
|
||||
|
||||
|
||||
class ParameterVector(ParameterDataObject):
|
||||
|
||||
@ -800,6 +834,9 @@ class ParameterVector(ParameterDataObject):
|
||||
|
||||
return types[:-2]
|
||||
|
||||
def getAsScriptCode(self):
|
||||
return '##' + self.name + '=vector'
|
||||
|
||||
|
||||
class ParameterGeometryPredicate(Parameter):
|
||||
|
||||
|
@ -89,7 +89,7 @@ class Algorithm():
|
||||
#A dict of Input object. keys are param names
|
||||
self.params = {}
|
||||
|
||||
#A dict of Output with final output descriptions. Keys are output names.
|
||||
#A dict of ModelerOutput with final output descriptions. Keys are output names.
|
||||
#Outputs not final are not stored in this dict
|
||||
self.outputs = {}
|
||||
|
||||
@ -119,6 +119,33 @@ class Algorithm():
|
||||
name = self.consoleName + "_" + unicode(i)
|
||||
self.name = name
|
||||
|
||||
def getOutputType(self, outputName):
|
||||
output = self.algorithm.getOutputFromName(outputName)
|
||||
return "output " + output.__class__.__name__.split(".")[-1][6:].lower()
|
||||
|
||||
def toPython(self):
|
||||
s = []
|
||||
params = []
|
||||
for param in self.algorithm.parameters:
|
||||
value = self.params[param.name]
|
||||
def _toString(v):
|
||||
if isinstance(v, (ValueFromInput, ValueFromOutput)):
|
||||
return v.asPythonParameter()
|
||||
elif isinstance(v, basestring):
|
||||
return "'%s'" % v
|
||||
elif isinstance(v, list):
|
||||
return "[%s]" % ",".join([_toString(val) for val in v])
|
||||
else:
|
||||
return unicode(value)
|
||||
params.append(_toString(value))
|
||||
for out in self.algorithm.outputs:
|
||||
if out.name in self.outputs:
|
||||
params.append(safeName(self.outputs[out.name].description).lower())
|
||||
else:
|
||||
params.append(str(None))
|
||||
s.append("outputs_%s=processing.runalg('%s', %s)" % (self.name, self.consoleName, ",".join(params)))
|
||||
return s
|
||||
|
||||
|
||||
class ValueFromInput():
|
||||
|
||||
@ -137,6 +164,8 @@ class ValueFromInput():
|
||||
except:
|
||||
return False
|
||||
|
||||
def asPythonParameter(self):
|
||||
return self.name
|
||||
|
||||
class ValueFromOutput():
|
||||
|
||||
@ -156,6 +185,9 @@ class ValueFromOutput():
|
||||
def __str__(self):
|
||||
return self.alg + "," + self.output
|
||||
|
||||
def asPythonParameter(self):
|
||||
return "outputs_%s['%s']" % (self.alg, self.output)
|
||||
|
||||
|
||||
class ModelerAlgorithm(GeoAlgorithm):
|
||||
|
||||
@ -654,3 +686,33 @@ class ModelerAlgorithm(GeoAlgorithm):
|
||||
raise e
|
||||
else:
|
||||
raise WrongModelException(_tr('Error in model definition line: ') + '%s\n%s' % (line.strip(), traceback.format_exc()))
|
||||
|
||||
|
||||
def toPython(self):
|
||||
s = ['##%s=name' % self.name]
|
||||
for param in self.inputs.values():
|
||||
s.append(param.param.getAsScriptCode())
|
||||
for alg in self.algs.values():
|
||||
for name, out in alg.outputs.iteritems():
|
||||
s.append('##%s=%s' % (safeName(out.description).lower(), alg.getOutputType(name)))
|
||||
|
||||
executed = []
|
||||
toExecute = [alg for alg in self.algs.values() if alg.active]
|
||||
while len(executed) < len(toExecute):
|
||||
for alg in toExecute:
|
||||
if alg.name not in executed:
|
||||
canExecute = True
|
||||
required = self.getDependsOnAlgorithms(alg.name)
|
||||
for requiredAlg in required:
|
||||
if requiredAlg != alg.name and requiredAlg not in executed:
|
||||
canExecute = False
|
||||
break
|
||||
if canExecute:
|
||||
s.extend(alg.toPython())
|
||||
executed.append(alg.name)
|
||||
|
||||
return '\n'.join(s)
|
||||
|
||||
def safeName(name):
|
||||
validChars = 'abcdefghijklmnopqrstuvwxyz'
|
||||
return ''.join(c for c in name.lower() if c in validChars)
|
@ -39,7 +39,6 @@ from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||
from processing.core.ProcessingLog import ProcessingLog
|
||||
from processing.gui.HelpEditionDialog import HelpEditionDialog
|
||||
from processing.gui.AlgorithmDialog import AlgorithmDialog
|
||||
import processing.gui.AlgorithmClassification
|
||||
from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
|
||||
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm, ModelerParameter
|
||||
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
|
||||
@ -161,6 +160,7 @@ class ModelerDialog(BASE, WIDGET):
|
||||
self.btnSave.setIcon(QgsApplication.getThemeIcon('/mActionFileSave.svg'))
|
||||
self.btnSaveAs.setIcon(QgsApplication.getThemeIcon('/mActionFileSaveAs.svg'))
|
||||
self.btnExportImage.setIcon(QgsApplication.getThemeIcon('/mActionSaveMapAsImage.png'))
|
||||
self.btnExportPython.setIcon(QgsApplication.getThemeIcon('/console/iconSaveAsConsole.png'))
|
||||
self.btnEditHelp.setIcon(QIcon(os.path.join(pluginPath, 'images', 'edithelp.png')))
|
||||
self.btnRun.setIcon(QIcon(os.path.join(pluginPath, 'images', 'runalgorithm.png')))
|
||||
|
||||
@ -184,6 +184,7 @@ class ModelerDialog(BASE, WIDGET):
|
||||
self.btnSave.clicked.connect(self.save)
|
||||
self.btnSaveAs.clicked.connect(self.saveAs)
|
||||
self.btnExportImage.clicked.connect(self.exportAsImage)
|
||||
self.btnExportPython.clicked.connect(self.exportAsPython)
|
||||
self.btnEditHelp.clicked.connect(self.editHelp)
|
||||
self.btnRun.clicked.connect(self.runModel)
|
||||
|
||||
@ -281,6 +282,23 @@ class ModelerDialog(BASE, WIDGET):
|
||||
|
||||
img.save(filename)
|
||||
|
||||
def exportAsPython(self):
|
||||
filename = unicode(QFileDialog.getSaveFileName(self,
|
||||
self.tr('Save Model As Python Script'), '',
|
||||
self.tr('Python files (*.py *.PY)')))
|
||||
if not filename:
|
||||
return
|
||||
|
||||
if not filename.lower().endswith('.py'):
|
||||
filename += '.py'
|
||||
|
||||
text = self.alg.toPython()
|
||||
with codecs.open(filename, 'w', encoding='utf-8') as fout:
|
||||
fout.write(text)
|
||||
QMessageBox.information(self, self.tr('Model exported'),
|
||||
self.tr('Model was correctly exported.'))
|
||||
|
||||
|
||||
def saveModel(self, saveAs):
|
||||
if unicode(self.textGroup.text()).strip() == '' \
|
||||
or unicode(self.textName.text()).strip() == '':
|
||||
|
@ -198,7 +198,7 @@ class ModelerParameterDefinitionDialog(QDialog):
|
||||
self.yesNoCombo.setCurrentIndex(
|
||||
1 if self.param.optional else 0)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout2)
|
||||
|
||||
|
||||
self.buttonBox = QDialogButtonBox(self)
|
||||
self.buttonBox.setOrientation(Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
|
||||
@ -221,8 +221,10 @@ class ModelerParameterDefinitionDialog(QDialog):
|
||||
validChars = \
|
||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
safeName = ''.join(c for c in description if c in validChars)
|
||||
name = self.paramType.upper().replace(' ', '') + '_' \
|
||||
+ safeName.upper()
|
||||
name = safeName.lower()
|
||||
i = 2
|
||||
while name in self.alg.inputs:
|
||||
name = safeName.lower() + str(i)
|
||||
else:
|
||||
name = self.param.name
|
||||
if self.paramType \
|
||||
|
@ -96,6 +96,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnExportPython">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
|
Loading…
x
Reference in New Issue
Block a user