Skip to content
Permalink
Browse files

Added first version of threading interface (by Camilo Polymeris, as p…

…art of GSoC 2012)

Fixed #5720. Still have to add refreshing to the model after the change in the element is done.

git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@227 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
  • Loading branch information
volayaf
volayaf committed Jun 5, 2012
1 parent cd73169 commit bbefe6decbfa5e0693f1d20f698cc69736cefb83
@@ -3,7 +3,7 @@
from sextante.saga.SagaAlgorithmProvider import SagaAlgorithmProvider
from sextante.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider
from sextante.core.QGisLayers import QGisLayers
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor, SilentProgress
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor
from sextante.core.SextanteConfig import SextanteConfig
from sextante.core.SextanteLog import SextanteLog
from sextante.modeler.ModelerAlgorithmProvider import ModelerAlgorithmProvider
@@ -281,7 +281,8 @@ def runalg(name, *args):
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, alg.getAsCommand())

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
AlgorithmExecutor.runalg(alg, SilentProgress())
algEx = AlgorithmExecutor(alg)
algEx.start()
QApplication.restoreOverrideCursor()
return alg.getOutputValuesAsDictionary()

@@ -336,7 +337,9 @@ def runandload(name, *args):
return

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
ret = AlgorithmExecutor.runalg(alg, SilentProgress())
#~ ret = AlgorithmExecutor.runalg(alg, SilentProgress())
algex = AlgorithmExecutor(alg, SilentProgress())
algex.start()
QApplication.restoreOverrideCursor()
if ret:
SextantePostprocessing.handleAlgorithmResults(alg)
@@ -7,71 +7,76 @@
from sextante.gui.SextantePostprocessing import SextantePostprocessing
import traceback

class AlgorithmExecutor:
class AlgorithmExecutor(QThread):
percentageChanged = pyqtSignal(int)
textChanged = pyqtSignal(QString)
cancelled = pyqtSignal()
error = pyqtSignal()
iterated = pyqtSignal(int)
#started & finished inherited from QThread

@staticmethod
def runalg(alg, progress):
'''executes a given algorithm, showing its progress in the progress object passed along.
Return true if everything went OK, false if the algorithm was canceled or there was
any problem and could not be completed'''
def __init__(self, alg, iterParam = None, parent = None):
QThread.__init__(self, parent)
self.algorithm = alg
self.parameterToIterate = iterParam

class Progress:
def __init__(self, algex):
self.algorithmExecutor = algex
def setText(self, text):
self.algorithmExecutor.textChanged.emit(text)
def setPercentage(self, p):
self.algorithmExecutor.percentageChanged.emit(p)
self.progress = Progress(self)
if self.parameterToIterate:
self.run = self.runalgIterating

#generate all single-feature layers
settings = QSettings()
systemEncoding = settings.value( "/UI/encoding", "System" ).toString()
layerfile = alg.getParameterValue(self.parameterToIterate)
layer = QGisLayers.getObjectFromUri(layerfile, False)
provider = layer.dataProvider()
allAttrs = provider.attributeIndexes()
provider.select( allAttrs )
feat = QgsFeature()
self.filelist = []
while provider.nextFeature(feat):
output = SextanteUtils.getTempFilename("shp")
self.filelist.append(output)
writer = QgsVectorFileWriter(output, systemEncoding,provider.fields(), provider.geometryType(), provider.crs() )
writer.addFeature(feat)
del writer
else:
self.run = self.runalg

def runalg(self):
try:
alg.execute(progress)
return not alg.canceled
self.algorithm.execute(self.progress)
if self.algorithm.canceled:
self.canceled.emit()
except GeoAlgorithmExecutionException, e :
QMessageBox.critical(None, "Error", e.msg)
return False
except Exception:
QMessageBox.critical(None, "Error", traceback.format_exc())
return False
self.error.emit()
except:
self.error.emit()

@staticmethod
def runalgIterating(alg,paramToIter,progress):
#generate all single-feature layers
settings = QSettings()
systemEncoding = settings.value( "/UI/encoding", "System" ).toString()
layerfile = alg.getParameterValue(paramToIter)
layer = QGisLayers.getObjectFromUri(layerfile, False)
provider = layer.dataProvider()
allAttrs = provider.attributeIndexes()
provider.select( allAttrs )
feat = QgsFeature()
filelist = []
def runalgIterating(self):
outputs = {}
while provider.nextFeature(feat):
output = SextanteUtils.getTempFilename("shp")
filelist.append(output)
writer = QgsVectorFileWriter(output, systemEncoding,provider.fields(), provider.geometryType(), provider.crs() )
writer.addFeature(feat)
del writer

#store output values to use them later as basenames for all outputs
for out in alg.outputs:
for out in self.algorithm.outputs:
outputs[out.name] = out.value

#now run all the algorithms
i = 1
for f in filelist:
alg.setParameterValue(paramToIter, f)
for out in alg.outputs:
for f in self.filelist:
self.algorithm.setParameterValue(self.parameterToIterate, f)
for out in self.algorithm.outputs:
filename = outputs[out.name]
if filename:
filename = filename[:filename.rfind(".")] + "_" + str(i) + filename[filename.rfind("."):]
out.value = filename
progress.setText("Executing iteration " + str(i) + "/" + str(len(filelist)) + "...")
progress.setPercentage((i * 100) / len(filelist))
if AlgorithmExecutor.runalg(alg, SilentProgress()):
SextantePostprocessing.handleAlgorithmResults(alg, False)
i+=1
else:
return False;

return True


class SilentProgress():

def setText(self, text):
pass

def setPercentage(self, i):
pass
self.progress.setText("Executing iteration " + str(i) + "/" + str(len(self.filelist)) + "...")
self.progress.setPercentage((i * 100) / len(self.filelist))
self.runalg()
if self.algorithm.canceled:
return
self.iterated.emit(i)
i += 1
@@ -12,7 +12,7 @@
from sextante.parameters.ParameterMultipleInput import ParameterMultipleInput
import copy
from sextante.gui.BatchOutputSelectionPanel import BatchOutputSelectionPanel
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor, SilentProgress
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor
from sextante.outputs.OutputHTML import OutputHTML
from sextante.core.SextanteResults import SextanteResults
from sextante.gui.ResultsDialog import ResultsDialog
@@ -99,16 +99,11 @@ def okPressed(self):
self.algs.append(alg)

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
i=1
self.progress.setMaximum(len(self.algs))
for alg in self.algs:
if AlgorithmExecutor.runalg(alg, SilentProgress()):
self.progress.setValue(i)
self.loadHTMLResults(alg, i)
i+=1
else:
QApplication.restoreOverrideCursor()
return
algEx = AlgorithmExecutor(alg);
algEx.start()

QApplication.restoreOverrideCursor()
QMessageBox.information(self, "Batch processing", "Batch processing successfully completed!")
self.close()
@@ -11,11 +11,9 @@
from sextante.parameters.ParameterTableField import ParameterTableField
from sextante.parameters.ParameterTable import ParameterTable
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from sextante.core.SextanteLog import SextanteLog
from sextante.gui.SextantePostprocessing import SextantePostprocessing
from sextante.parameters.ParameterRange import ParameterRange
from sextante.gui.HTMLViewerDialog import HTMLViewerDialog
from sextante.parameters.ParameterNumber import ParameterNumber

from sextante.gui.ParametersPanel import ParametersPanel
@@ -52,7 +50,10 @@ def setupUi(self, dialog, alg):
dialog.resize(650, 450)
self.buttonBox = QtGui.QDialogButtonBox()
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setStandardButtons(
QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Ok)
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)

self.paramTable = ParametersPanel(self.alg, self.dialog)
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidget(self.paramTable)
@@ -93,8 +94,9 @@ def setupUi(self, dialog, alg):
self.verticalLayout.addWidget(self.progress)
self.verticalLayout.addWidget(self.buttonBox)
dialog.setLayout(self.verticalLayout)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), self.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), self.reject)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.dialog.close)
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).clicked.connect(self.cancel)
QtCore.QMetaObject.connectSlotsByName(dialog)


@@ -148,67 +150,76 @@ def setParamValue(self, param, widget):
else:
return param.setValue(str(widget.text()))


@pyqtSlot()
def accept(self):
try:
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
if self.setParamValues():
msg = self.alg.checkParameterValuesBeforeExecuting()
if msg:
QMessageBox.critical(self.dialog, "Unable to execute algorithm", msg)
return
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
buttons = self.paramTable.iterateButtons
iterateParam = None
for i in range(len(buttons.values())):
button = buttons.values()[i]
if button.isChecked():
iterateParam = buttons.keys()[i]
break


self.progress.setMaximum(0)
self.progressLabel.setText("Processing algorithm...")
if iterateParam:
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
AlgorithmExecutor.runalgIterating(self.alg, iterateParam, self)
QApplication.restoreOverrideCursor()
else:
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
command = self.alg.getAsCommand()
if command:
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, command)
ret = AlgorithmExecutor.runalg(self.alg, self)
QApplication.restoreOverrideCursor()
if ret:
SextantePostprocessing.handleAlgorithmResults(self.alg, not keepOpen)

self.dialog.executed = True
if not keepOpen:
self.dialog.close()
else:
self.progressLabel.setText("")
self.progress.setValue(0)
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)

else:
QMessageBox.critical(self.dialog, "Unable to execute algorithm", "Wrong or missing parameter values")
#~ try:
if self.setParamValues():
msg = self.alg.checkParameterValuesBeforeExecuting()
if msg:
QMessageBox.critical(self.dialog, "Unable to execute algorithm", msg)
return
except GeoAlgorithmExecutionException, e :
QApplication.restoreOverrideCursor()
QMessageBox.critical(self, "Error",e.msg)
SextanteLog.addToLog(SextanteLog.LOG_ERROR, e.msg)
if not keepOpen:
self.dialog.close()
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
buttons = self.paramTable.iterateButtons
iterateParam = None

for i in range(len(buttons.values())):
button = buttons.values()[i]
if button.isChecked():
iterateParam = buttons.keys()[i]
break

self.progress.setMaximum(0)
self.progressLabel.setText("Processing algorithm...")
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
if iterateParam:
self.algEx = AlgorithmExecutor(self.alg, iterateParam)
else:
self.progressLabel.setText("")
self.progress.setValue(0)
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
command = self.alg.getAsCommand()
if command:
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, command)
self.algEx = AlgorithmExecutor(self.alg)
self.algEx.finished.connect(self.finish)
self.algEx.percentageChanged.connect(self.setPercentage)
self.algEx.textChanged.connect(self.setText)
self.algEx.start()
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(True)
else:
QMessageBox.critical(self.dialog, "Unable to execute algorithm", "Wrong or missing parameter values")

@pyqtSlot()
def finish(self):
self.dialog.executed = True
QApplication.restoreOverrideCursor()

def reject(self):
self.dialog.close()
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)

if not keepOpen:
self.dialog.close()
else:
self.progressLabel.setText("")
self.progress.setValue(0)
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
SextantePostprocessing.handleAlgorithmResults(self.alg, not keepOpen)

#~ except GeoAlgorithmExecutionException, e :
#~ QApplication.restoreOverrideCursor()
#~ QMessageBox.critical(self, "Error",e.msg)
#~ SextanteLog.addToLog(SextanteLog.LOG_ERROR, e.msg)
#~ if not keepOpen:
#~ self.dialog.close()
#~ else:
#~ self.progressLabel.setText("")
#~ self.progress.setValue(0)
#~ self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)

@pyqtSlot()
def cancel(self):
try:
self.algEx.finished.disconnect()
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
except:
pass

def setPercentage(self, i):
if self.progress.maximum() == 0:
@@ -217,5 +228,3 @@ def setPercentage(self, i):

def setText(self, text):
self.progressLabel.setText(text)


This file was deleted.

@@ -133,6 +133,10 @@ def addParameter(self, param):
self.parameters.append(param)
self.paramPos.append(self.getPositionForParameterItem())

def updateParameter(self, paramIndex, param):
self.parameters[paramIndex] = param
#self.updateModelerView()

def addAlgorithm(self, alg, parametersMap, valuesMap, outputsMap):
self.algs.append(alg)
self.algParameters.append(parametersMap)

0 comments on commit bbefe6d

Please sign in to comment.
You can’t perform that action at this time.