Skip to content

Commit

Permalink
[sextante] modeler improvements: added 'save as' button and fixed iss…
Browse files Browse the repository at this point in the history
…ue with line endings.

Added more tests
  • Loading branch information
volaya committed Mar 30, 2013
1 parent d48efd8 commit 50c3303
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 31 deletions.
13 changes: 7 additions & 6 deletions python/plugins/sextante/modeler/ModelerAlgorithm.py
Expand Up @@ -59,6 +59,7 @@ def getCopy(self):
newone = ModelerAlgorithm() newone = ModelerAlgorithm()
newone.openModel(self.descriptionFile) newone.openModel(self.descriptionFile)
newone.provider = self.provider newone.provider = self.provider
newone.deactivated = self.deactivate
return newone return newone


def __init__(self): def __init__(self):
Expand Down Expand Up @@ -113,7 +114,7 @@ def openModel(self, filename):


self.descriptionFile = filename self.descriptionFile = filename
lines = codecs.open(filename, "r", encoding='utf-8') lines = codecs.open(filename, "r", encoding='utf-8')
line = lines.readline().strip("\n") line = lines.readline().strip("\n").strip("\r")
iAlg = 0 iAlg = 0
try: try:
while line != "": while line != "":
Expand Down Expand Up @@ -141,11 +142,11 @@ def openModel(self, filename):
algLine = line[len("ALGORITHM:"):] algLine = line[len("ALGORITHM:"):]
alg = ModelerUtils.getAlgorithm(algLine) alg = ModelerUtils.getAlgorithm(algLine)
if alg is not None: if alg is not None:
posline = lines.readline().strip("\n") posline = lines.readline().strip("\n").strip("\r")
tokens = posline.split(",") tokens = posline.split(",")
self.algPos.append(QtCore.QPointF(float(tokens[0]), float(tokens[1]))) self.algPos.append(QtCore.QPointF(float(tokens[0]), float(tokens[1])))
self.algs.append(alg) self.algs.append(alg)
dependenceline = lines.readline().strip("\n") dependenceline = lines.readline().strip("\n").strip("\r")
dependencies = []; dependencies = [];
if dependenceline != str(None): if dependenceline != str(None):
for index in dependenceline.split(","): for index in dependenceline.split(","):
Expand All @@ -154,14 +155,14 @@ def openModel(self, filename):
except: except:
pass #a quick fix fwhile I figure out how to solve problems when parsing this pass #a quick fix fwhile I figure out how to solve problems when parsing this
for param in alg.parameters: for param in alg.parameters:
line = lines.readline().strip("\n") line = lines.readline().strip("\n").strip("\r")
if line==str(None): if line==str(None):
algParams[param.name] = None algParams[param.name] = None
else: else:
tokens = line.split("|") tokens = line.split("|")
algParams[param.name] = AlgorithmAndParameter(int(tokens[0]), tokens[1]) algParams[param.name] = AlgorithmAndParameter(int(tokens[0]), tokens[1])
for out in alg.outputs: for out in alg.outputs:
line = lines.readline().strip("\n") line = lines.readline().strip("\n").strip("\r")
if str(None)!=line: if str(None)!=line:
algOutputs[out.name] = line algOutputs[out.name] = line
#we add the output to the algorithm, with a name indicating where it comes from #we add the output to the algorithm, with a name indicating where it comes from
Expand All @@ -178,7 +179,7 @@ def openModel(self, filename):
iAlg += 1 iAlg += 1
else: else:
raise WrongModelException("Error in algorithm name: " + algLine) raise WrongModelException("Error in algorithm name: " + algLine)
line = lines.readline().strip("\n") line = lines.readline().strip("\n").strip("\r")
except Exception, e: except Exception, e:
if isinstance (e, WrongModelException): if isinstance (e, WrongModelException):
raise e raise e
Expand Down
37 changes: 16 additions & 21 deletions python/plugins/sextante/modeler/ModelerDialog.py
Expand Up @@ -73,8 +73,11 @@ def __init__(self, alg=None):
self.openButton.setToolTip(self.tr("Open existing model")) self.openButton.setToolTip(self.tr("Open existing model"))
self.buttonBox.addButton(self.openButton, QDialogButtonBox.ActionRole) self.buttonBox.addButton(self.openButton, QDialogButtonBox.ActionRole)
self.saveButton = QPushButton(self.tr("Save")) self.saveButton = QPushButton(self.tr("Save"))
self.saveButton.setToolTip(self.tr("Save current model")) self.saveButton.setToolTip(self.tr("Save current model"))
self.buttonBox.addButton(self.saveButton, QDialogButtonBox.ActionRole) self.buttonBox.addButton(self.saveButton, QDialogButtonBox.ActionRole)
self.saveAsButton = QPushButton(self.tr("Save as ..."))
self.saveAsButton.setToolTip(self.tr("Save current model as"))
self.buttonBox.addButton(self.saveAsButton, QDialogButtonBox.ActionRole)


# fill trees with inputs and algorithms # fill trees with inputs and algorithms
self.fillInputsTree() self.fillInputsTree()
Expand All @@ -94,7 +97,8 @@ def __init__(self, alg=None):
self.algorithmTree.doubleClicked.connect(self.addAlgorithm) self.algorithmTree.doubleClicked.connect(self.addAlgorithm)


self.openButton.clicked.connect(self.openModel) self.openButton.clicked.connect(self.openModel)
self.saveButton.clicked.connect(self.saveModel) self.saveButton.clicked.connect(self.save)
self.saveAsButton.clicked.connect(self.saveAs)
self.runButton.clicked.connect(self.runModel) self.runButton.clicked.connect(self.runModel)
self.editHelpButton.clicked.connect(self.editHelp) self.editHelpButton.clicked.connect(self.editHelp)


Expand All @@ -120,20 +124,6 @@ def editHelp(self):
if self.alg.descriptionFile is None and dlg.descriptions: if self.alg.descriptionFile is None and dlg.descriptions:
self.help = dlg.descriptions self.help = dlg.descriptions


#===========================================================================
# def createScript(self):
# if str(self.textGroup.text()).strip() == "":
# QMessageBox.warning(self, "Warning", "Please enter group name before saving")
# return
# filename = QtGui.QFileDialog.getSaveFileName(self, "Save Script", ScriptUtils.scriptsFolder(), "Python scripts (*.py)")
# if filename:
# fout = open(filename, "w")
# fout.write(str(self.textGroup.text()) + "=group")
# fout.write(self.alg.getAsPythonCode())
# fout.close()
# self.update = True
#===========================================================================

def runModel(self): def runModel(self):
##TODO: enable alg cloning without saving to file ##TODO: enable alg cloning without saving to file
if self.alg.descriptionFile is None: if self.alg.descriptionFile is None:
Expand All @@ -154,8 +144,14 @@ def runModel(self):
alg = self.alg.getCopy() alg = self.alg.getCopy()
dlg = ParametersDialog(alg) dlg = ParametersDialog(alg)
dlg.exec_() dlg.exec_()


def saveModel(self): def save(self):
self.saveModel(False)

def saveAs(self):
self.saveModel(True)

def saveModel(self, saveAs):
if unicode(self.textGroup.text()).strip() == "" or unicode(self.textName.text()).strip() == "": if unicode(self.textGroup.text()).strip() == "" or unicode(self.textName.text()).strip() == "":
QMessageBox.warning(self, QMessageBox.warning(self,
self.tr("Warning"), self.tr("Warning"),
Expand All @@ -165,7 +161,7 @@ def saveModel(self):
self.alg.setPositions(self.scene.getParameterPositions(), self.scene.getAlgorithmPositions()) self.alg.setPositions(self.scene.getParameterPositions(), self.scene.getAlgorithmPositions())
self.alg.name = unicode(self.textName.text()) self.alg.name = unicode(self.textName.text())
self.alg.group = unicode(self.textGroup.text()) self.alg.group = unicode(self.textGroup.text())
if self.alg.descriptionFile != None: if self.alg.descriptionFile != None and not saveAs:
filename = self.alg.descriptionFile filename = self.alg.descriptionFile
else: else:
filename = unicode(QFileDialog.getSaveFileName(self, self.tr("Save Model"), ModelerUtils.modelsFolder(), self.tr("SEXTANTE models (*.model)"))) filename = unicode(QFileDialog.getSaveFileName(self, self.tr("Save Model"), ModelerUtils.modelsFolder(), self.tr("SEXTANTE models (*.model)")))
Expand Down Expand Up @@ -214,8 +210,7 @@ def repaintModel(self):
self.scene = ModelerScene() self.scene = ModelerScene()
self.scene.setSceneRect(QRectF(0, 0, ModelerAlgorithm.CANVAS_SIZE, ModelerAlgorithm.CANVAS_SIZE)) self.scene.setSceneRect(QRectF(0, 0, ModelerAlgorithm.CANVAS_SIZE, ModelerAlgorithm.CANVAS_SIZE))
self.scene.paintModel(self.alg) self.scene.paintModel(self.alg)
self.view.setScene(self.scene) self.view.setScene(self.scene)
#self.pythonText.setText(self.alg.getAsPythonCode())


def addInput(self): def addInput(self):
item = self.inputsTree.currentItem() item = self.inputsTree.currentItem()
Expand Down
42 changes: 38 additions & 4 deletions python/plugins/sextante/tests/ModelerAlgorithmTest.py
Expand Up @@ -9,29 +9,63 @@
from sextante.modeler import ModelerAlgorithmProvider from sextante.modeler import ModelerAlgorithmProvider
from sextante.modeler.ModelerAlgorithm import ModelerAlgorithm from sextante.modeler.ModelerAlgorithm import ModelerAlgorithm



class ModelerAlgorithmTest(unittest.TestCase): class ModelerAlgorithmTest(unittest.TestCase):


def testCreateModel(self): def testCreateModel(self):
pass pass


def testRemoveAlgorithm(self): def testRemoveAlgorithm(self):
'''NOTE:this is not passing, since the algCopy method reload from file'''
folder = os.path.join(os.path.dirname(ModelerAlgorithmProvider.__file__), "models") folder = os.path.join(os.path.dirname(ModelerAlgorithmProvider.__file__), "models")
modelfile = os.path.join(folder, "noinputs.model") modelfile = os.path.join(folder, "noinputs.model")
model = ModelerAlgorithm() model = ModelerAlgorithm()
model.openModel(modelfile) model.openModel(modelfile)
self.assertTrue(2, len(model.algs)) self.assertTrue(2, len(model.algs))
self.assertFalse(model.removeAlgorithm(0)) self.assertFalse(model.removeAlgorithm(0))
self.assertTrue(model.removeAlgorithm(len(model.algs) - 1)); self.assertTrue(model.removeAlgorithm(len(model.algs) - 1));
outputs = sextante.runalg(model, None) outputs = model.execute(None)
self.assertEquals(2, len(outputs)) self.assertEquals(2, len(outputs))
output=outputs['SAVENAME_ALG0'] output=outputs['SAVENAME_ALG0']
layer=QGisLayers.getObjectFromUri(output, True) layer=QGisLayers.getObjectFromUri(output, True)
self.assertIsNone(layer) self.assertIsNone(layer)


def testRemoveParameter(self): def testRemoveParameter(self):
pass folder = os.path.join(os.path.dirname(ModelerAlgorithmProvider.__file__), "models")
modelfile = os.path.join(folder, "watersheds.model")
model = ModelerAlgorithm()
model.openModel(modelfile)
self.assertTrue(2, len(model.parameters))
self.assertFalse(model.removeParameter(0))
self.assertTrue(2, len(model.parameters))

def testComputingDependecies(self):
folder = os.path.join(os.path.dirname(ModelerAlgorithmProvider.__file__), "models")
modelfile = os.path.join(folder, "watersheds.model")
model = ModelerAlgorithm()
model.openModel(modelfile)
self.assertTrue(2, len(model.parameters))
self.assertTrue(5, len(model.algs))
dependent = model.getDependentAlgorithms(0)
self.assertEquals([0,1,2,3,4], dependent)
dependent = model.getDependentAlgorithms(1)
self.assertEquals([1,2,3,4], dependent)
dependent = model.getDependentAlgorithms(2)
self.assertEquals([2,3,4], dependent)
dependent = model.getDependentAlgorithms(3)
self.assertEquals([3,4], dependent)
dependent = model.getDependentAlgorithms(4)
self.assertEquals([4], dependent)

depends = model.getDependsOnAlgorithms(0)
self.assertEquals([], depends)
depends = model.getDependsOnAlgorithms(1)
self.assertEquals([0], depends)
depends = model.getDependsOnAlgorithms(2)
self.assertEquals([1,0], depends)
depends = model.getDependsOnAlgorithms(3)
self.assertEquals([2,1,0], depends)
depends = model.getDependsOnAlgorithms(4)
self.assertEquals([3,2,1,0], depends)







Expand Down

0 comments on commit 50c3303

Please sign in to comment.