Skip to content

Commit 995ede3

Browse files
committed
added support for all gdal/ogr formats in all providers
added support for pre and post execution hooks
1 parent c58c9da commit 995ede3

13 files changed

+188
-40
lines changed

python/plugins/sextante/core/GeoAlgorithm.py

+72-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
from sextante.outputs.OutputTable import OutputTable
1818
from sextante.outputs.OutputHTML import OutputHTML
1919
import copy
20+
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
21+
from sextante.core.SextanteConfig import SextanteConfig
22+
from sextante.gdal.GdalUtils import GdalUtils
2023

2124
class GeoAlgorithm:
2225

@@ -103,18 +106,23 @@ def checkParameterValuesBeforeExecuting(self):
103106
This check is called from the parameters dialog, and also when calling from the console'''
104107
return None
105108
#=========================================================
106-
109+
110+
107111
def execute(self, progress):
108112
'''The method to use to call a SEXTANTE algorithm.
109113
Although the body of the algorithm is in processAlgorithm(),
110114
it should be called using this method, since it performs
111115
some additional operations.
112116
Raises a GeoAlgorithmExecutionException in case anything goes wrong.'''
113-
self.setOutputCRSFromInputLayers()
114-
self.resolveTemporaryOutputs()
115-
self.checkOutputFileExtensions()
117+
116118
try:
117-
self.processAlgorithm(progress)
119+
self.setOutputCRSFromInputLayers()
120+
self.resolveTemporaryOutputs()
121+
self.checkOutputFileExtensions()
122+
self.runPreExecutionScript(progress)
123+
self.processAlgorithm(progress)
124+
self.convertUnsupportedFormats(progress)
125+
self.runPostExecutionScript(progress)
118126
except GeoAlgorithmExecutionException, gaee:
119127
SextanteLog.addToLog(SextanteLog.LOG_ERROR, gaee.msg)
120128
raise gaee
@@ -132,6 +140,62 @@ def execute(self, progress):
132140
SextanteLog.addToLog(SextanteLog.LOG_ERROR, lines)
133141
raise GeoAlgorithmExecutionException(errstring)
134142

143+
144+
def runPostExecutionScript(self, progress):
145+
scriptFile = SextanteConfig.getSetting(SextanteConfig.POST_EXECUTION_SCRIPT)
146+
self.runHookScript(scriptFile, progress);
147+
148+
def runPreExecutionScript(self, progress):
149+
scriptFile = SextanteConfig.getSetting(SextanteConfig.PRE_EXECUTION_SCRIPT)
150+
self.runHookScript(scriptFile, progress);
151+
152+
def runHookScript(self, filename, progress):
153+
if not os.path.exists(filename):
154+
return
155+
try:
156+
script = "import sextante\n"
157+
ns = {}
158+
ns['progress'] = progress
159+
ns['alg'] = self
160+
f = open(filename)
161+
lines = f.readlines()
162+
for line in lines:
163+
script+=line
164+
exec(script) in ns
165+
except: # a wrong script should not cause problems, so we swallow all exceptions
166+
pass
167+
168+
def convertUnsupportedFormats(self, progress):
169+
i = 0
170+
progress.setText("Converting outputs")
171+
for out in self.outputs:
172+
if isinstance(out, OutputVector):
173+
if out.compatible is not None:
174+
layer = QGisLayers.getObjectFromUri(out.compatible)
175+
provider = layer.dataProvider()
176+
writer = out.getVectorWriter( provider.fields(), provider.geometryType(), provider.crs())
177+
features = QGisLayers.features(layer)
178+
for feature in features:
179+
writer.addFeature(feature)
180+
elif isinstance(out, OutputRaster):
181+
if out.compatible is not None:
182+
layer = QGisLayers.getObjectFromUri(out.compatible)
183+
provider = layer.dataProvider()
184+
writer = QgsRasterFileWriter(out.value)
185+
format = self.getFormatShortNameFromFilename(out.value)
186+
writer.setOutputFormat(format);
187+
writer.writeRaster(layer.pipe(), layer.width(), layer.height(), layer.extent(), layer.crs())
188+
progress.setPercentage(100 * i / float(len(self.outputs)))
189+
190+
def getFormatShortNameFromFilename(self, filename):
191+
ext = filename[filename.rfind(".")+1:]
192+
supported = GdalUtils.getSupportedRasters()
193+
for name in supported.keys():
194+
exts = supported[name]
195+
if ext in exts:
196+
return name
197+
return "GTiff"
198+
135199
def checkOutputFileExtensions(self):
136200
'''Checks if the values of outputs are correct and have one of the supported output extensions.
137201
If not, it adds the first one of the supported extensions, which is assumed to be the default one'''
@@ -140,11 +204,11 @@ def checkOutputFileExtensions(self):
140204
if not os.path.isabs(out.value):
141205
continue
142206
if isinstance(out, OutputRaster):
143-
exts = self.provider.getSupportedOutputRasterLayerExtensions()
207+
exts = QGisLayers.getSupportedOutputRasterLayerExtensions()
144208
elif isinstance(out, OutputVector):
145-
exts = self.provider.getSupportedOutputVectorLayerExtensions()
209+
exts = QGisLayers.getSupportedOutputVectorLayerExtensions()
146210
elif isinstance(out, OutputTable):
147-
exts = self.provider.getSupportedOutputTableExtensions()
211+
exts = QGisLayers.getSupportedOutputTableExtensions()
148212
elif isinstance(out, OutputHTML):
149213
exts =["html", "htm"]
150214
else:

python/plugins/sextante/core/QGisLayers.py

+27
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* *
1717
***************************************************************************
1818
"""
19+
from sextante.gdal.GdalUtils import GdalUtils
1920

2021
__author__ = 'Victor Olaya'
2122
__date__ = 'August 2012'
@@ -37,6 +38,32 @@ class QGisLayers:
3738
ALL_TYPES = -1
3839
iface = None;
3940

41+
@staticmethod
42+
def getSupportedOutputVectorLayerExtensions():
43+
formats = QgsVectorFileWriter.supportedFiltersAndFormats()
44+
exts = ["shp"]#shp is the default, should be the first
45+
for extension in formats.keys():
46+
extension = unicode(extension)
47+
extension = extension[extension.find('*.') + 2:]
48+
extension = extension[:extension.find(" ")]
49+
if extension.lower() != "shp":
50+
exts.append(extension)
51+
return exts
52+
53+
@staticmethod
54+
def getSupportedOutputRasterLayerExtensions():
55+
allexts = ["tif"]
56+
for exts in GdalUtils.getSupportedRasters().values():
57+
for ext in exts:
58+
if ext not in allexts:
59+
allexts.append(ext)
60+
return allexts
61+
62+
@staticmethod
63+
def getSupportedOutputTableExtensions():
64+
exts = ["dbf, csv"]
65+
return exts
66+
4067
@staticmethod
4168
def getRasterLayers():
4269
layers = QGisLayers.iface.legendInterface().layers()

python/plugins/sextante/core/Sextante.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def runAlgorithm(algOrName, onFinish, *args):
257257
alghelp(algOrName)
258258
return
259259

260-
alg = alg.getCopy()#copy.deepcopy(alg)
260+
alg = alg.getCopy()
261261
if isinstance(args, dict):
262262
# set params by name
263263
for name, value in args.items():
@@ -306,7 +306,7 @@ def runAlgorithm(algOrName, onFinish, *args):
306306
def finish():
307307
QApplication.restoreOverrideCursor()
308308
if onFinish is not None:
309-
onFinish(alg)
309+
onFinish(alg, SilentProgress())
310310
progress.close()
311311
def error(msg):
312312
QApplication.restoreOverrideCursor()
@@ -325,9 +325,10 @@ def cancel():
325325
algEx.start()
326326
algEx.wait()
327327
else:
328-
ret = UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress())
328+
progress = SilentProgress()
329+
ret = UnthreadedAlgorithmExecutor.runalg(alg, progress)
329330
if onFinish is not None and ret:
330-
onFinish(alg)
331+
onFinish(alg, progress)
331332
QApplication.restoreOverrideCursor()
332333
return alg
333334

python/plugins/sextante/core/SextanteConfig.py

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class SextanteConfig():
4343
USE_THREADS = "USE_THREADS"
4444
SHOW_DEBUG_IN_DIALOG = "SHOW_DEBUG_IN_DIALOG"
4545
RECENT_ALGORITHMS = "RECENT_ALGORITHMS"
46+
PRE_EXECUTION_SCRIPT = "PRE_EXECUTION_SCRIPT"
47+
POST_EXECUTION_SCRIPT = "POST_EXECUTION_SCRIPT"
4648

4749
settings = {}
4850
settingIcons= {}
@@ -65,7 +67,11 @@ def initialize():
6567
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_POINT_STYLE,"Style for point layers",""))
6668
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_LINE_STYLE,"Style for line layers",""))
6769
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_POLYGON_STYLE,"Style for polygon layers",""))
70+
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_POLYGON_STYLE,"Style for polygon layers",""))
71+
SextanteConfig.addSetting(Setting("General", SextanteConfig.PRE_EXECUTION_SCRIPT,"Pre-execution script",""))
72+
SextanteConfig.addSetting(Setting("General", SextanteConfig.POST_EXECUTION_SCRIPT,"Post-execution script",""))
6873
SextanteConfig.addSetting(Setting("General", SextanteConfig.RECENT_ALGORITHMS,"Recent algs","", hidden=True))
74+
6975

7076
@staticmethod
7177
def setGroupIcon(group, icon):

python/plugins/sextante/gdal/GdalOgrAlgorithmProvider.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,7 @@ def createAlgsList(self):
100100
def getSupportedOutputRasterLayerExtensions(self):
101101
return GdalUtils.getSupportedRasterExtensions()
102102

103-
def getSupportedOutputVectorLayerExtensions(self):
104-
return ["shp", "sqlite"]
103+
#===========================================================================
104+
# def getSupportedOutputVectorLayerExtensions(self):
105+
# return ["shp", "sqlite"]
106+
#===========================================================================

python/plugins/sextante/gdal/GdalUtils.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@ def getSupportedRasters():
7373

7474
shortName = str(QString(driver.ShortName).remove( QRegExp( '\(.*$' ) ).trimmed())
7575
metadata = driver.GetMetadata()
76+
if not metadata.has_key(gdal.DCAP_CREATE) or metadata[gdal.DCAP_CREATE] != 'YES':
77+
continue
7678
if metadata.has_key(gdal.DMD_EXTENSION):
77-
extensions = metadata[gdal.DMD_EXTENSION].split("/")
79+
extensions = metadata[gdal.DMD_EXTENSION].split("/")
7880
if extensions:
7981
GdalUtils.supportedRasters[shortName] = extensions
8082

@@ -85,7 +87,7 @@ def getSupportedRasterExtensions():
8587
allexts = ["tif"]
8688
for exts in GdalUtils.getSupportedRasters().values():
8789
for ext in exts:
88-
if ext not in allexts:
90+
if ext not in allexts and ext != "":
8991
allexts.append(ext)
9092
return allexts
9193

python/plugins/sextante/gui/AlgorithmExecutionDialog.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@ def accept(self):
286286

287287
@pyqtSlot()
288288
def finish(self):
289-
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
290-
SextantePostprocessing.handleAlgorithmResults(self.alg, not keepOpen)
289+
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
290+
SextantePostprocessing.handleAlgorithmResults(self.alg, self, not keepOpen)
291291
self.executed = True
292292
self.setInfo("Algorithm %s finished" % self.alg.name)
293293
QApplication.restoreOverrideCursor()

python/plugins/sextante/gui/SextantePostprocessing.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@
3838
class SextantePostprocessing:
3939

4040
@staticmethod
41-
def handleAlgorithmResults(alg, showResults = True):
41+
def handleAlgorithmResults(alg, progress, showResults = True):
4242
htmlResults = False;
43+
progress.setText("Loading resulting layers")
44+
i = 0
4345
for out in alg.outputs:
46+
progress.setPercentage(100 * i / float(len(alg.outputs)))
4447
if out.hidden or not out.open:
4548
continue
4649
if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
@@ -59,6 +62,7 @@ def handleAlgorithmResults(alg, showResults = True):
5962
elif isinstance(out, OutputHTML):
6063
SextanteResults.addResult(out.description, out.value)
6164
htmlResults = True
65+
i += 1
6266
if showResults and htmlResults:
6367
QApplication.restoreOverrideCursor()
6468
dlg = ResultsDialog()

python/plugins/sextante/gui/UnthreadedAlgorithmExecutor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def runalgIterating(alg,paramToIter,progress):
8484
progress.setText("Executing iteration " + str(i) + "/" + str(len(filelist)) + "...")
8585
progress.setPercentage((i * 100) / len(filelist))
8686
if UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress()):
87-
SextantePostprocessing.handleAlgorithmResults(alg, False)
87+
SextantePostprocessing.handleAlgorithmResults(alg, progress, False)
8888
i+=1
8989
else:
9090
return False;

python/plugins/sextante/outputs/OutputRaster.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* *
1717
***************************************************************************
1818
"""
19+
from sextante.core.QGisLayers import QGisLayers
1920

2021
__author__ = 'Victor Olaya'
2122
__date__ = 'August 2012'
@@ -24,14 +25,28 @@
2425
__revision__ = '$Format:%H$'
2526

2627
from sextante.outputs.Output import Output
28+
from sextante.core.SextanteUtils import SextanteUtils
2729

2830
class OutputRaster(Output):
29-
31+
32+
compatible = None
33+
3034
def getFileFilter(self, alg):
31-
exts = alg.provider.getSupportedOutputRasterLayerExtensions()
35+
exts = QGisLayers.getSupportedOutputRasterLayerExtensions()
3236
for i in range(len(exts)):
3337
exts[i] = exts[i].upper() + " files(*." + exts[i].lower() + ")"
3438
return ";;".join(exts)
3539

3640
def getDefaultFileExtension(self, alg):
3741
return alg.provider.getSupportedOutputRasterLayerExtensions()[0]
42+
43+
def getCompatibleFileName(self, alg):
44+
'''Returns a filename that is compatible with the algorithm that is going to generate this output.
45+
If the algorithm supports the file format of the current output value, it returns that value. If not,
46+
it returns a temporary file with a supported file format, to be used to generate the output result.'''
47+
if self.value.endswith(self.getDefaultFileExtension(alg)):
48+
return self.value
49+
else:
50+
if self.compatible is None:
51+
self.compatible = SextanteUtils.getTempFilename(self.getDefaultFileExtension(alg))
52+
return self.compatible;

python/plugins/sextante/outputs/OutputTable.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@
3131
class OutputTable(Output):
3232

3333
def getFileFilter(self,alg):
34-
exts = alg.provider.getSupportedOutputTableExtensions()
34+
exts = ['csv']
3535
for i in range(len(exts)):
3636
exts[i] = exts[i].upper() + " files(*." + exts[i].lower() + ")"
3737
return ";;".join(exts)
3838

3939
def getDefaultFileExtension(self, alg):
4040
return alg.provider.getSupportedOutputTableExtensions()[0]
4141

42+
def getCompatibleFileName(self, alg):
43+
#TODO!!!
44+
return self.value
45+
4246
def getTableWriter(self, fields):
4347
'''Returns a suitable writer to which records can be added as a
4448
result of the algorithm. Use this to transparently handle output

python/plugins/sextante/outputs/OutputVector.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* *
1717
***************************************************************************
1818
"""
19+
from sextante.core.QGisLayers import QGisLayers
1920

2021
__author__ = 'Victor Olaya'
2122
__date__ = 'August 2012'
@@ -24,23 +25,39 @@
2425
__revision__ = '$Format:%H$'
2526

2627
from PyQt4.QtCore import *
27-
28+
from qgis.core import *
2829
from sextante.outputs.Output import Output
2930
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
31+
from sextante.core.SextanteUtils import SextanteUtils
32+
3033

3134
class OutputVector(Output):
3235

3336
encoding = None
37+
compatible = None
3438

35-
def getFileFilter(self,alg):
36-
exts = alg.provider.getSupportedOutputVectorLayerExtensions()
39+
def getFileFilter(self,alg):
40+
exts = QGisLayers.getSupportedOutputRasterLayerExtensions()
3741
for i in range(len(exts)):
3842
exts[i] = exts[i].upper() + " files(*." + exts[i].lower() + ")"
3943
return ";;".join(exts)
44+
4045

4146
def getDefaultFileExtension(self, alg):
4247
return alg.provider.getSupportedOutputVectorLayerExtensions()[0]
43-
48+
49+
def getCompatibleFileName(self, alg):
50+
'''Returns a filename that is compatible with the algorithm that is going to generate this output.
51+
If the algorithm supports the file format of the current output value, it returns that value. If not,
52+
it returns a temporary file with a supported file format, to be used to generate the output result.'''
53+
if self.value.endswith(self.getDefaultFileExtension(alg)):
54+
return self.value
55+
else:
56+
if self.compatible is None:
57+
self.compatible = SextanteUtils.getTempFilename(self.getDefaultFileExtension(alg))
58+
return self.compatible;
59+
60+
4461
def getVectorWriter(self, fields, geomType, crs, options=None):
4562
'''Returns a suitable writer to which features can be added as a
4663
result of the algorithm. Use this to transparently handle output

0 commit comments

Comments
 (0)