Skip to content

Commit

Permalink
reimplemented unthreaded executino (threads are not still fully stabl…
Browse files Browse the repository at this point in the history
…e). Running algs in a thread is now optional

git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@273 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
  • Loading branch information
volayaf committed Jun 29, 2012
1 parent 201d347 commit f4b0df4
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 43 deletions.
57 changes: 33 additions & 24 deletions src/sextante/core/Sextante.py
Expand Up @@ -21,6 +21,8 @@
from sextante.pymorph.PymorphAlgorithmProvider import PymorphAlgorithmProvider
from sextante.mmqgisx.MMQGISXAlgorithmProvider import MMQGISXAlgorithmProvider
from sextante.lidar.LidarToolsAlgorithmProvider import LidarToolsAlgorithmProvider
from sextante.gui.UnthreadedAlgorithmExecutor import UnthreadedAlgorithmExecutor,\
SilentProgress

class Sextante:

Expand Down Expand Up @@ -287,18 +289,21 @@ def runalg(name, *args):
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, alg.getAsCommand())

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
algEx = AlgorithmExecutor(alg)
def finish():
#SextantePostprocessing.handleAlgorithmResults(alg)
QApplication.restoreOverrideCursor()
def error(msg):
QApplication.restoreOverrideCursor()
print msg
SextanteLog.addToLog(SextanteLog.LOG_ERROR, msg)
algEx.error.connect(error)
algEx.finished.connect(finish)
algEx.start()
algEx.wait()
if SextanteConfig.getSetting(SextanteConfig.USE_THREADS):
algEx = AlgorithmExecutor(alg)
def finish():
QApplication.restoreOverrideCursor()
def error(msg):
QApplication.restoreOverrideCursor()
print msg
SextanteLog.addToLog(SextanteLog.LOG_ERROR, msg)
algEx.error.connect(error)
algEx.finished.connect(finish)
algEx.start()
algEx.wait()
else:
UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress())

return alg.getOutputValuesAsDictionary()


Expand Down Expand Up @@ -350,19 +355,23 @@ def runandload(name, *args):
if msg:
QMessageBox.critical(None, "Unable to execute algorithm", msg)
return

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
algEx = AlgorithmExecutor(alg)
def finish():
SextantePostprocessing.handleAlgorithmResults(alg)
QApplication.restoreOverrideCursor()
def error(msg):
QApplication.restoreOverrideCursor()
QMessageBox.critical(None, "Error", msg)
SextanteLog.addToLog(SextanteLog.LOG_ERROR, msg)
algEx.error.connect(error)
algEx.finished.connect(finish)
algEx.start()
if SextanteConfig.getSetting(SextanteConfig.USE_THREADS):
algEx = AlgorithmExecutor(alg)
def finish():
SextantePostprocessing.handleAlgorithmResults(alg)
QApplication.restoreOverrideCursor()
def error(msg):
QApplication.restoreOverrideCursor()
QMessageBox.critical(None, "Error", msg)
SextanteLog.addToLog(SextanteLog.LOG_ERROR, msg)
algEx.error.connect(error)
algEx.finished.connect(finish)
algEx.start()
else:
if UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress()):
SextantePostprocessing.handleAlgorithmResults(alg)




Expand Down
2 changes: 2 additions & 0 deletions src/sextante/core/SextanteConfig.py
Expand Up @@ -14,6 +14,7 @@ class SextanteConfig():
USE_SELECTED = "USE_SELECTED"
USE_FILENAME_AS_LAYER_NAME = "USE_FILENAME_AS_LAYER_NAME"
KEEP_DIALOG_OPEN = "KEEP_DIALOG_OPEN"
USE_THREADS = "USE_THREADS"

settings = {}
settingIcons= {}
Expand All @@ -22,6 +23,7 @@ class SextanteConfig():
def initialize():
icon = QtGui.QIcon(os.path.dirname(__file__) + "/../images/alg.png")
SextanteConfig.settingIcons["General"] = icon
SextanteConfig.addSetting(Setting("General", SextanteConfig.USE_THREADS, "Run algorithms in a new thread (still unstable)", False))
SextanteConfig.addSetting(Setting("General", SextanteConfig.KEEP_DIALOG_OPEN, "Keep dialog open after running an algorithm", False))
SextanteConfig.addSetting(Setting("General", SextanteConfig.USE_SELECTED, "Use only selected features in external applications", True))
SextanteConfig.addSetting(Setting("General", SextanteConfig.TABLE_LIKE_PARAM_PANEL, "Show table-like parameter panels", False))
Expand Down
23 changes: 19 additions & 4 deletions src/sextante/gui/BatchProcessingDialog.py
Expand Up @@ -15,8 +15,10 @@
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor
from sextante.outputs.OutputHTML import OutputHTML
from sextante.core.SextanteResults import SextanteResults
from sextante.gui.ResultsDialog import ResultsDialog
from sextante.core.SextanteLog import SextanteLog
from sextante.core.SextanteConfig import SextanteConfig
from sextante.gui.UnthreadedAlgorithmExecutor import SilentProgress,\
UnthreadedAlgorithmExecutor

class BatchProcessingDialog(QtGui.QDialog):
def __init__(self, alg):
Expand Down Expand Up @@ -101,10 +103,23 @@ def okPressed(self):

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
self.progress.setMaximum(len(self.algs))
self.progress.setValue(0)
self.nextAlg(0)

self.table.setEnabled(False)
if SextanteConfig.getSetting(SextanteConfig.USE_THREADS):
self.progress.setValue(0)
self.nextAlg(0)
else:
i=1
self.progress.setMaximum(len(self.algs))
for alg in self.algs:
if UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress()):
self.progress.setValue(i)
self.loadHTMLResults(alg, i)
i+=1
else:
QApplication.restoreOverrideCursor()
return

self.finishAll()

def loadHTMLResults(self, alg, i):
for out in alg.outputs:
Expand Down
34 changes: 22 additions & 12 deletions src/sextante/gui/ParametersDialog.py
Expand Up @@ -29,6 +29,7 @@
from sextante.outputs.OutputTable import OutputTable
from sextante.core.WrongHelpFileException import WrongHelpFileException
import os
from sextante.gui.UnthreadedAlgorithmExecutor import UnthreadedAlgorithmExecutor

try:
_fromUtf8 = QtCore.QString.fromUtf8
Expand Down Expand Up @@ -177,19 +178,28 @@ def accept(self):
self.progress.setMaximum(0)
self.progressLabel.setText("Processing algorithm...")
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
if iterateParam:
self.algEx = AlgorithmExecutor(self.alg, iterateParam)
useThread = SextanteConfig.getSetting(SextanteConfig.USE_THREADS)
if useThread:
if iterateParam:
self.algEx = AlgorithmExecutor(self.alg, iterateParam)
else:
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.error.connect(self.error)
self.algEx.percentageChanged.connect(self.setPercentage)
self.algEx.textChanged.connect(self.setText)
self.algEx.start()
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(True)
else:
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.error.connect(self.error)
self.algEx.percentageChanged.connect(self.setPercentage)
self.algEx.textChanged.connect(self.setText)
self.algEx.start()
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(True)
if iterateParam:
UnthreadedAlgorithmExecutor.runalgIterating(self.alg, iterateParam, self)
else:
UnthreadedAlgorithmExecutor.runalg(self.alg, self)
self.finish()

else:
QMessageBox.critical(self.dialog, "Unable to execute algorithm", "Wrong or missing parameter values")

Expand Down
76 changes: 76 additions & 0 deletions src/sextante/gui/UnthreadedAlgorithmExecutor.py
@@ -0,0 +1,76 @@
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteUtils import SextanteUtils
from sextante.gui.SextantePostprocessing import SextantePostprocessing
import traceback

class UnthreadedAlgorithmExecutor:

@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 could not be completed'''
try:
alg.execute(progress)
return True
except GeoAlgorithmExecutionException, e :
QMessageBox.critical(None, "Error", e.msg)
return False
except Exception:
QMessageBox.critical(None, "Error", traceback.format_exc())
return False

@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 = []
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:
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:
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 UnthreadedAlgorithmExecutor.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
1 change: 0 additions & 1 deletion src/sextante/modeler/ModelerAlgorithm.py
Expand Up @@ -364,7 +364,6 @@ def processAlgorithm(self, progress):
outputs[out.name] = out.value
self.producedOutputs[iAlg] = outputs
executed.append(iAlg)

except GeoAlgorithmExecutionException, e :
raise GeoAlgorithmExecutionException("Error executing algorithm " + str(iAlg) + "\n" + e.msg)
iAlg += 1
Expand Down
6 changes: 4 additions & 2 deletions src/sextante/modeler/ModelerDialog.py
Expand Up @@ -22,14 +22,16 @@ def __init__(self, alg=None):
self.setupUi()
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowSystemMenuHint |
QtCore.Qt.WindowMinMaxButtonsHint)
if alg:
if alg is not None:
self.alg = alg
self.textGroup.setText(alg.group)
self.textName.setText(alg.name)
self.repaintModel()
last = self.scene.getLastAlgorithmItem()
if last:
if last is not None:
self.view.ensureVisible(last)
else:
self.view.ensureVisible(0,0,10,10)
else:
self.alg = ModelerAlgorithm()
self.alg.setModelerView(self)
Expand Down

0 comments on commit f4b0df4

Please sign in to comment.