Skip to content

Commit f499c85

Browse files
author
volayaf
committed
improved table usage.Added better transparent layer handling for external apps.Started gdal bindings
git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@65 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
1 parent afdbb21 commit f499c85

File tree

105 files changed

+672
-361
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+672
-361
lines changed

src/sextante/SextantePlugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def openHelp(self):
123123
if os.name == "nt":
124124
os.startfile(filename)
125125
elif sys.platform == "darwin":
126-
subprocess.call(('open', filename))
126+
subprocess.Popen(('open', filename))
127127
else:
128128
subprocess.call(('xdg-open', filename))
129129

src/sextante/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ def name():
55
def description():
66
return "SEXTANTE Geoprocessing platform for QGIS"
77
def version():
8-
return "Version 1.0.1"
8+
return "Version 1.0.2"
99
def icon():
1010
return "icon.png"
1111
def qgisMinimumVersion():

src/sextante/core/AlgorithmProvider.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@ def loadAlgorithms(self):
1919
return
2020
else:
2121
self._loadAlgorithms()
22+
for alg in self.algs:
23+
alg.provider = self
2224

2325
#methods to be overridden.
2426
#==============================
2527

2628

2729
def _loadAlgorithms(self):
2830
'''Algorithm loading should take place here, filling self.algs, which is a list of
29-
elements of class GeoAlgorithm. Use that class to create your own algorithms
30-
Since algorithms should have a reference to the provider they come
31-
from, this is also the place to set the 'provider' variable of each algorithm'''
31+
elements of class GeoAlgorithm. Use that class to create your own algorithms'''
3232
pass
3333

3434
def initializeSettings(self):
35-
'''this is the place where you should add config parameters to sextante using the SextanteConfig class.
36-
this method is called when a provider is added to Sextante.
35+
'''this is the place where you should add config parameters to SEXTANTE using the SextanteConfig class.
36+
this method is called when a provider is added to SEXTANTE.
3737
By default it just adds a setting to activate or deactivate algorithms from the provider'''
3838
name = "ACTIVATE_" + self.getName().upper().replace(" ", "_")
3939
SextanteConfig.addSetting(Setting(self.getName(), name, "Activate", True))
@@ -49,8 +49,6 @@ def getName(self):
4949
return "Generic algorithm provider"
5050

5151

52-
53-
5452
def getIcon(self):
5553
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/alg.png")
5654

src/sextante/core/LayerExporter.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from sextante.core.SextanteConfig import SextanteConfig
2+
from sextante.core.SextanteUtils import SextanteUtils
3+
from qgis.core import *
4+
from PyQt4.QtCore import *
5+
from PyQt4.QtGui import *
6+
7+
class LayerExporter():
8+
9+
'''This class provides method to export layers so they can be used by third party applications.
10+
These method are used by the GeoAlgorithm class and allow the developer to use transparently
11+
any layer that is loaded into QGIS, without having to worry about its origin'''
12+
13+
@staticmethod
14+
def exportVectorLayer(layer):
15+
'''Takes a QgsVectorLayer and returns the filename to refer to it, which allows external
16+
apps which support only file-based layers to use it. It performs the necessary export
17+
in case the input layer is not in a standard format suitable for most appplications, it is
18+
a remote one or db-based (non-file based) one, or if there is a selection and it should be
19+
used, exporting just the selected features.
20+
Currently, the output is restricted to shapefiles, so anything that is not in a shapefile
21+
will get exported'''
22+
settings = QSettings()
23+
systemEncoding = settings.value( "/UI/encoding", "System" ).toString()
24+
output = SextanteUtils.getTempFilename("shp")
25+
provider = layer.dataProvider()
26+
allAttrs = provider.attributeIndexes()
27+
provider.select( allAttrs )
28+
useSelection = SextanteConfig.getSetting(SextanteConfig.USE_SELECTED)
29+
if useSelection and layer.selectedFeatureCount() != 0:
30+
writer = QgsVectorFileWriter( output, systemEncoding,provider.fields(), provider.geometryType(), provider.crs() )
31+
selection = layer.selectedFeatures()
32+
for feat in selection:
33+
writer.addFeature(feat)
34+
del writer
35+
return output
36+
else:
37+
if (not str(layer.source()).endswith("shp")):
38+
writer = QgsVectorFileWriter( output, systemEncoding,provider.fields(), provider.geometryType(), provider.crs() )
39+
feat = QgsFeature()
40+
while provider.nextFeature(feat):
41+
writer.addFeature(feat)
42+
del writer
43+
return output
44+
else:
45+
return str(layer.source())
46+
47+
48+
49+

src/sextante/core/QGisLayers.py

+36-39
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def getRasterLayers():
2020

2121
for layer in layers:
2222
if layer.type() == layer.RasterLayer:
23-
if os.path.exists(layer.source()):#only file-based layers
23+
if layer.usesProvider() and layer.providerKey() == 'gdal':#only gdal file-based layers
2424
raster.append(layer)
2525
return raster
2626

@@ -31,27 +31,25 @@ def getVectorLayers(shapetype=-1):
3131
for layer in layers:
3232
if layer.type() == layer.VectorLayer:
3333
if shapetype == QGisLayers.ALL_TYPES or layer.geometryType() == shapetype:
34-
if os.path.exists(layer.source()):
35-
vector.append(layer)
34+
#if os.path.exists(layer.source()):
35+
vector.append(layer)
3636
return vector
3737

3838
@staticmethod
3939
def getAllLayers():
40-
layers = QGisLayers.iface.legendInterface().layers()
41-
layerslist = list()
42-
for layer in layers:
43-
if os.path.exists(layer.source()):
44-
layerslist.append(layer)
45-
return layerslist
40+
layers = []
41+
layers += QGisLayers.getRasterLayers();
42+
layers += QGisLayers.getVectorLayers();
43+
return layers
4644

4745
@staticmethod
4846
def getTables():
4947
layers = QGisLayers.iface.legendInterface().layers()
5048
tables = list()
5149
for layer in layers:
5250
if layer.type() == layer.VectorLayer :
53-
uri = str(layer.dataProvider().dataSourceUri())
54-
if (uri.endswith("shp")):
51+
uri = str(layer.source())
52+
if uri.endswith("csv") or uri.endswith("dbf"):
5553
tables.append(layer)
5654
return tables
5755

@@ -71,42 +69,41 @@ def load(layer, name = None, crs = None, style = None):
7169
return
7270
prjSetting = None
7371
settings = QSettings()
74-
try:
72+
if crs != None:
73+
prjSetting = settings.value("/Projections/defaultBehaviour")
74+
settings.setValue("/Projections/defaultBehaviour", QVariant(""))
75+
if name == None:
76+
name = path.split(layer)[1]
77+
qgslayer = QgsVectorLayer(layer, name , 'ogr')
78+
if qgslayer.isValid():
7579
if crs != None:
76-
prjSetting = settings.value("/Projections/defaultBehaviour")
77-
settings.setValue("/Projections/defaultBehaviour", QVariant(""))
78-
if name == None:
79-
name = path.split(layer)[1]
80-
qgslayer = QgsVectorLayer(layer, name , 'ogr')
80+
qgslayer.setCrs(crs,False)
81+
if style == None:
82+
if qgslayer.geometryType == 0:
83+
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POINT_STYLE)
84+
elif qgslayer.geometryType == 1:
85+
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_LINE_STYLE)
86+
else:
87+
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POLYGON_STYLE)
88+
qgslayer.loadNamedStyle(style)
89+
QgsMapLayerRegistry.instance().addMapLayer(qgslayer)
90+
else:
91+
qgslayer = QgsRasterLayer(layer, name)
8192
if qgslayer.isValid():
8293
if crs != None:
8394
qgslayer.setCrs(crs,False)
8495
if style == None:
85-
if qgslayer.geometryType == 0:
86-
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POINT_STYLE)
87-
elif qgslayer.geometryType == 1:
88-
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_LINE_STYLE)
89-
else:
90-
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POLYGON_STYLE)
96+
style = SextanteConfig.getSetting(SextanteConfig.RASTER_STYLE)
9197
qgslayer.loadNamedStyle(style)
9298
QgsMapLayerRegistry.instance().addMapLayer(qgslayer)
99+
QGisLayers.iface.legendInterface().refreshLayerSymbology(qgslayer)
93100
else:
94-
qgslayer = QgsRasterLayer(layer, name)
95-
if qgslayer.isValid():
96-
if crs != None:
97-
qgslayer.setCrs(crs,False)
98-
if style == None:
99-
style = SextanteConfig.getSetting(SextanteConfig.RASTER_STYLE)
100-
qgslayer.loadNamedStyle(style)
101-
QgsMapLayerRegistry.instance().addMapLayer(qgslayer)
102-
QGisLayers.iface.legendInterface().refreshLayerSymbology(qgslayer)
103-
else:
104-
QtGui.QMessageBox.critical(None, "Error", "Could not load layer: " + str(layer))
105-
except Exception, e:
106-
QtGui.QMessageBox.critical(None, "Error", "Could not load layer: " + str(layer))
107-
finally:
108-
if prjSetting:
109-
settings.setValue("/Projections/defaultBehaviour", prjSetting)
101+
if prjSetting:
102+
settings.setValue("/Projections/defaultBehaviour", prjSetting)
103+
raise RuntimeError("Could not load layer: " + str(layer)
104+
+"\nCheck the SEXTANTE log to look for errors in algorithm execution")
105+
if prjSetting:
106+
settings.setValue("/Projections/defaultBehaviour", prjSetting)
110107

111108

112109
@staticmethod

src/sextante/core/Sextante.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import copy
66
from sextante.core.QGisLayers import QGisLayers
77
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor, SilentProgress
8-
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
98
from sextante.core.SextanteConfig import SextanteConfig
109
from sextante.core.SextanteLog import SextanteLog
1110
from sextante.modeler.ModelerAlgorithmProvider import ModelerAlgorithmProvider
@@ -18,6 +17,7 @@
1817
from sextante.grass.GrassAlgorithmProvider import GrassAlgorithmProvider
1918
from sextante.gui.RenderingStyles import RenderingStyles
2019
from sextante.modeler.ModelerOnlyAlgorithmProvider import ModelerOnlyAlgorithmProvider
20+
from sextante.gdal.GdalAlgorithmProvider import GdalAlgorithmProvider
2121

2222
class Sextante:
2323

@@ -83,6 +83,7 @@ def initialize():
8383
Sextante.addProvider(RAlgorithmProvider())
8484
Sextante.addProvider(SagaAlgorithmProvider())
8585
Sextante.addProvider(GrassAlgorithmProvider())
86+
Sextante.addProvider(GdalAlgorithmProvider())
8687
Sextante.modeler.initializeSettings();
8788
#and initialize
8889
SextanteLog.startLogging()
@@ -269,12 +270,12 @@ def runalg(name, *args):
269270

270271
@staticmethod
271272
def load(layer):
272-
'''loads a layer into QGIS'''
273+
'''Loads a layer into QGIS'''
273274
QGisLayers.load(layer)
274275

275276
@staticmethod
276277
def loadFromAlg(layersdict):
277-
'''load all layer resulting from a given algorithm.
278+
'''Load all layer resulting from a given algorithm.
278279
Layers are passed as a dictionary, obtained from alg.getOutputValuesAsDictionary()'''
279280
QGisLayers.loadFromDict(layersdict)
280281

src/sextante/core/SextanteConfig.py

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ class SextanteConfig():
99
VECTOR_LINE_STYLE = "VECTOR_LINE_STYLE"
1010
VECTOR_POLYGON_STYLE = "VECTOR_POLYGON_STYLE"
1111
SHOW_RECENT_ALGORITHMS = "SHOW_RECENT_ALGORITHMS"
12+
USE_SELECTED = "USE_SELECTED"
1213

1314
settings = {}
1415

1516
@staticmethod
1617
def initialize():
18+
SextanteConfig.addSetting(Setting("General", SextanteConfig.USE_SELECTED, "Use only selected features in external application", True))
1719
SextanteConfig.addSetting(Setting("General", SextanteConfig.SHOW_RECENT_ALGORITHMS, "Show recently executed algorithms", True))
1820
SextanteConfig.addSetting(Setting("General", SextanteConfig.OUTPUT_FOLDER,
1921
"Output folder", os.path.join(SextanteUtils.userFolder(),"outputs" )))

src/sextante/core/SextanteUtils.py

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ def setTempOutput(out, alg):
3636
out.value = filename
3737
SextanteUtils.NUM_EXPORTED += 1
3838

39+
@staticmethod
40+
def getTempFilename(ext):
41+
path = SextanteUtils.tempFolder()
42+
filename = path + os.sep + str(time.time()) + str(SextanteUtils.getNumExportedLayers()) + "." + ext
43+
return filename
44+
45+
@staticmethod
46+
def getNumExportedLayers():
47+
SextanteUtils.NUM_EXPORTED += 1
48+
return SextanteUtils.NUM_EXPORTED
3949

4050
def mkdir(newdir):
4151
if os.path.isdir(newdir):

src/sextante/ftools/FToolsAlgorithmProvider.py

-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ def __init__(self):
4242
ConvexHull(), FixedDistanceBuffer(), VariableDistanceBuffer(),
4343
Dissolve(), Difference(), Intersection(), Union(), Clip(), ExtentFromLayer(),
4444
RandomSelection(), RandomSelectionWithinSubsets(), SelectByLocation()]
45-
for alg in self.alglist:
46-
alg.provider = self
4745

4846
def getName(self):
4947
return "ftools"

src/sextante/ftools/FixedDistanceBuffer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from sextante.outputs.OutputVector import OutputVector
1010
from sextante.parameters.ParameterBoolean import ParameterBoolean
1111
from sextante.parameters.ParameterNumber import ParameterNumber
12-
import sextante.ftools.Buffer as buff
12+
from sextante.ftools import Buffer as buff
1313

1414
class FixedDistanceBuffer(GeoAlgorithm):
1515

src/sextante/ftools/VariableDistanceBuffer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from sextante.outputs.OutputVector import OutputVector
1010
from sextante.parameters.ParameterBoolean import ParameterBoolean
1111
from sextante.parameters.ParameterNumber import ParameterNumber
12-
import sextante.ftools.Buffer as buff
12+
from sextante.ftools import Buffer as buff
1313
from sextante.parameters.ParameterTableField import ParameterTableField
1414

1515
class VariableDistanceBuffer(GeoAlgorithm):

src/sextante/gdal/GdalAlgorithm.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from sextante.script.ScriptAlgorithm import ScriptAlgorithm
2+
from PyQt4 import QtGui
3+
import os
4+
5+
class GdalAlgorithm(ScriptAlgorithm):
6+
'''Just a ScriptAlgorithm that automatically takes its icon
7+
filename for the script filename'''
8+
9+
def getIcon(self):
10+
filename = os.path.basename(self.descriptionFile[:-2] + "png")
11+
filepath = os.path.dirname(__file__) + "/icons/" + filename
12+
return QtGui.QIcon(filepath)
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import os
2+
from PyQt4.QtCore import *
3+
from PyQt4.QtGui import *
4+
from sextante.core.AlgorithmProvider import AlgorithmProvider
5+
from sextante.script.WrongScriptException import WrongScriptException
6+
from sextante.core.SextanteLog import SextanteLog
7+
from sextante.gdal.GdalAlgorithm import GdalAlgorithm
8+
from sextante.gdal.nearblack import nearblack
9+
from sextante.gdal.information import information
10+
11+
class GdalAlgorithmProvider(AlgorithmProvider):
12+
13+
'''This provider incorporates GDAL-based algorithms into SEXTANTE.
14+
Algorithms have been implemented using two different mechanisms,
15+
which should serve as an example of different ways of extending
16+
SEXTANTE:
17+
1)when a python script exist for a given process, it has been adapted
18+
as a SEXTANTE python script and loaded using the ScriptAlgorithm class.
19+
This algorithms call GDAL using its Python bindings
20+
2)Other algorithms are called directly using the command line interface,
21+
These have been implemented individually extending the GeoAlgorithm class'''
22+
23+
def __init__(self):
24+
AlgorithmProvider.__init__(self)
25+
self.createAlgsList()
26+
27+
def scriptsFolder(self):
28+
'''The folder where script algorithms are stored'''
29+
return os.path.dirname(__file__) + "/scripts"
30+
31+
def getName(self):
32+
return "Gdal"
33+
34+
def getIcon(self):
35+
return QIcon(os.path.dirname(__file__) + "/icons/gdalicon.png")
36+
37+
def _loadAlgorithms(self):
38+
'''This is called each time there is a change in the SEXTANTE set of algorithm,
39+
for instance, when the users adds a new model or script. Since this provider
40+
cannot be extended by the user, we create the list in advance and then just
41+
assign it to self.algs'''
42+
self.algs = self.preloadedAlgs
43+
44+
def createAlgsList(self):
45+
#First we populate the list of algorihtms with those created extending
46+
#GeoAlgorithm directly (those that execute GDAL using the console)
47+
self.preloadedAlgs = [nearblack(), information()]
48+
#And then we add those that are created as python scripts
49+
folder = self.scriptsFolder()
50+
for descriptionFile in os.listdir(folder):
51+
if descriptionFile.endswith("py"):
52+
try:
53+
fullpath = os.path.join(self.scriptsFolder(), descriptionFile)
54+
alg = GdalAlgorithm(fullpath)
55+
self.preloadedAlgs.append(alg)
56+
except WrongScriptException,e:
57+
SextanteLog.addToLog(SextanteLog.LOG_ERROR,e.msg)

0 commit comments

Comments
 (0)