Skip to content

Commit

Permalink
improved table usage.Added better transparent layer handling for exte…
Browse files Browse the repository at this point in the history
…rnal apps.Started gdal bindings

git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@65 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
  • Loading branch information
volayaf committed Apr 6, 2012
1 parent afdbb21 commit f499c85
Show file tree
Hide file tree
Showing 105 changed files with 672 additions and 361 deletions.
2 changes: 1 addition & 1 deletion src/sextante/SextantePlugin.py
Expand Up @@ -123,7 +123,7 @@ def openHelp(self):
if os.name == "nt":
os.startfile(filename)
elif sys.platform == "darwin":
subprocess.call(('open', filename))
subprocess.Popen(('open', filename))
else:
subprocess.call(('xdg-open', filename))

Expand Down
2 changes: 1 addition & 1 deletion src/sextante/__init__.py
Expand Up @@ -5,7 +5,7 @@ def name():
def description():
return "SEXTANTE Geoprocessing platform for QGIS"
def version():
return "Version 1.0.1"
return "Version 1.0.2"
def icon():
return "icon.png"
def qgisMinimumVersion():
Expand Down
12 changes: 5 additions & 7 deletions src/sextante/core/AlgorithmProvider.py
Expand Up @@ -19,21 +19,21 @@ def loadAlgorithms(self):
return
else:
self._loadAlgorithms()
for alg in self.algs:
alg.provider = self

#methods to be overridden.
#==============================


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

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




def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/alg.png")

Expand Down
49 changes: 49 additions & 0 deletions src/sextante/core/LayerExporter.py
@@ -0,0 +1,49 @@
from sextante.core.SextanteConfig import SextanteConfig
from sextante.core.SextanteUtils import SextanteUtils
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class LayerExporter():

'''This class provides method to export layers so they can be used by third party applications.
These method are used by the GeoAlgorithm class and allow the developer to use transparently
any layer that is loaded into QGIS, without having to worry about its origin'''

@staticmethod
def exportVectorLayer(layer):
'''Takes a QgsVectorLayer and returns the filename to refer to it, which allows external
apps which support only file-based layers to use it. It performs the necessary export
in case the input layer is not in a standard format suitable for most appplications, it is
a remote one or db-based (non-file based) one, or if there is a selection and it should be
used, exporting just the selected features.
Currently, the output is restricted to shapefiles, so anything that is not in a shapefile
will get exported'''
settings = QSettings()
systemEncoding = settings.value( "/UI/encoding", "System" ).toString()
output = SextanteUtils.getTempFilename("shp")
provider = layer.dataProvider()
allAttrs = provider.attributeIndexes()
provider.select( allAttrs )
useSelection = SextanteConfig.getSetting(SextanteConfig.USE_SELECTED)
if useSelection and layer.selectedFeatureCount() != 0:
writer = QgsVectorFileWriter( output, systemEncoding,provider.fields(), provider.geometryType(), provider.crs() )
selection = layer.selectedFeatures()
for feat in selection:
writer.addFeature(feat)
del writer
return output
else:
if (not str(layer.source()).endswith("shp")):
writer = QgsVectorFileWriter( output, systemEncoding,provider.fields(), provider.geometryType(), provider.crs() )
feat = QgsFeature()
while provider.nextFeature(feat):
writer.addFeature(feat)
del writer
return output
else:
return str(layer.source())




75 changes: 36 additions & 39 deletions src/sextante/core/QGisLayers.py
Expand Up @@ -20,7 +20,7 @@ def getRasterLayers():

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

Expand All @@ -31,27 +31,25 @@ def getVectorLayers(shapetype=-1):
for layer in layers:
if layer.type() == layer.VectorLayer:
if shapetype == QGisLayers.ALL_TYPES or layer.geometryType() == shapetype:
if os.path.exists(layer.source()):
vector.append(layer)
#if os.path.exists(layer.source()):
vector.append(layer)
return vector

@staticmethod
def getAllLayers():
layers = QGisLayers.iface.legendInterface().layers()
layerslist = list()
for layer in layers:
if os.path.exists(layer.source()):
layerslist.append(layer)
return layerslist
layers = []
layers += QGisLayers.getRasterLayers();
layers += QGisLayers.getVectorLayers();
return layers

@staticmethod
def getTables():
layers = QGisLayers.iface.legendInterface().layers()
tables = list()
for layer in layers:
if layer.type() == layer.VectorLayer :
uri = str(layer.dataProvider().dataSourceUri())
if (uri.endswith("shp")):
uri = str(layer.source())
if uri.endswith("csv") or uri.endswith("dbf"):
tables.append(layer)
return tables

Expand All @@ -71,42 +69,41 @@ def load(layer, name = None, crs = None, style = None):
return
prjSetting = None
settings = QSettings()
try:
if crs != None:
prjSetting = settings.value("/Projections/defaultBehaviour")
settings.setValue("/Projections/defaultBehaviour", QVariant(""))
if name == None:
name = path.split(layer)[1]
qgslayer = QgsVectorLayer(layer, name , 'ogr')
if qgslayer.isValid():
if crs != None:
prjSetting = settings.value("/Projections/defaultBehaviour")
settings.setValue("/Projections/defaultBehaviour", QVariant(""))
if name == None:
name = path.split(layer)[1]
qgslayer = QgsVectorLayer(layer, name , 'ogr')
qgslayer.setCrs(crs,False)
if style == None:
if qgslayer.geometryType == 0:
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POINT_STYLE)
elif qgslayer.geometryType == 1:
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_LINE_STYLE)
else:
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POLYGON_STYLE)
qgslayer.loadNamedStyle(style)
QgsMapLayerRegistry.instance().addMapLayer(qgslayer)
else:
qgslayer = QgsRasterLayer(layer, name)
if qgslayer.isValid():
if crs != None:
qgslayer.setCrs(crs,False)
if style == None:
if qgslayer.geometryType == 0:
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POINT_STYLE)
elif qgslayer.geometryType == 1:
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_LINE_STYLE)
else:
style = SextanteConfig.getSetting(SextanteConfig.VECTOR_POLYGON_STYLE)
style = SextanteConfig.getSetting(SextanteConfig.RASTER_STYLE)
qgslayer.loadNamedStyle(style)
QgsMapLayerRegistry.instance().addMapLayer(qgslayer)
QGisLayers.iface.legendInterface().refreshLayerSymbology(qgslayer)
else:
qgslayer = QgsRasterLayer(layer, name)
if qgslayer.isValid():
if crs != None:
qgslayer.setCrs(crs,False)
if style == None:
style = SextanteConfig.getSetting(SextanteConfig.RASTER_STYLE)
qgslayer.loadNamedStyle(style)
QgsMapLayerRegistry.instance().addMapLayer(qgslayer)
QGisLayers.iface.legendInterface().refreshLayerSymbology(qgslayer)
else:
QtGui.QMessageBox.critical(None, "Error", "Could not load layer: " + str(layer))
except Exception, e:
QtGui.QMessageBox.critical(None, "Error", "Could not load layer: " + str(layer))
finally:
if prjSetting:
settings.setValue("/Projections/defaultBehaviour", prjSetting)
if prjSetting:
settings.setValue("/Projections/defaultBehaviour", prjSetting)
raise RuntimeError("Could not load layer: " + str(layer)
+"\nCheck the SEXTANTE log to look for errors in algorithm execution")
if prjSetting:
settings.setValue("/Projections/defaultBehaviour", prjSetting)


@staticmethod
Expand Down
7 changes: 4 additions & 3 deletions src/sextante/core/Sextante.py
Expand Up @@ -5,7 +5,6 @@
import copy
from sextante.core.QGisLayers import QGisLayers
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor, SilentProgress
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from sextante.core.SextanteConfig import SextanteConfig
from sextante.core.SextanteLog import SextanteLog
from sextante.modeler.ModelerAlgorithmProvider import ModelerAlgorithmProvider
Expand All @@ -18,6 +17,7 @@
from sextante.grass.GrassAlgorithmProvider import GrassAlgorithmProvider
from sextante.gui.RenderingStyles import RenderingStyles
from sextante.modeler.ModelerOnlyAlgorithmProvider import ModelerOnlyAlgorithmProvider
from sextante.gdal.GdalAlgorithmProvider import GdalAlgorithmProvider

class Sextante:

Expand Down Expand Up @@ -83,6 +83,7 @@ def initialize():
Sextante.addProvider(RAlgorithmProvider())
Sextante.addProvider(SagaAlgorithmProvider())
Sextante.addProvider(GrassAlgorithmProvider())
Sextante.addProvider(GdalAlgorithmProvider())
Sextante.modeler.initializeSettings();
#and initialize
SextanteLog.startLogging()
Expand Down Expand Up @@ -269,12 +270,12 @@ def runalg(name, *args):

@staticmethod
def load(layer):
'''loads a layer into QGIS'''
'''Loads a layer into QGIS'''
QGisLayers.load(layer)

@staticmethod
def loadFromAlg(layersdict):
'''load all layer resulting from a given algorithm.
'''Load all layer resulting from a given algorithm.
Layers are passed as a dictionary, obtained from alg.getOutputValuesAsDictionary()'''
QGisLayers.loadFromDict(layersdict)

Expand Down
2 changes: 2 additions & 0 deletions src/sextante/core/SextanteConfig.py
Expand Up @@ -9,11 +9,13 @@ class SextanteConfig():
VECTOR_LINE_STYLE = "VECTOR_LINE_STYLE"
VECTOR_POLYGON_STYLE = "VECTOR_POLYGON_STYLE"
SHOW_RECENT_ALGORITHMS = "SHOW_RECENT_ALGORITHMS"
USE_SELECTED = "USE_SELECTED"

settings = {}

@staticmethod
def initialize():
SextanteConfig.addSetting(Setting("General", SextanteConfig.USE_SELECTED, "Use only selected features in external application", True))
SextanteConfig.addSetting(Setting("General", SextanteConfig.SHOW_RECENT_ALGORITHMS, "Show recently executed algorithms", True))
SextanteConfig.addSetting(Setting("General", SextanteConfig.OUTPUT_FOLDER,
"Output folder", os.path.join(SextanteUtils.userFolder(),"outputs" )))
Expand Down
10 changes: 10 additions & 0 deletions src/sextante/core/SextanteUtils.py
Expand Up @@ -36,6 +36,16 @@ def setTempOutput(out, alg):
out.value = filename
SextanteUtils.NUM_EXPORTED += 1

@staticmethod
def getTempFilename(ext):
path = SextanteUtils.tempFolder()
filename = path + os.sep + str(time.time()) + str(SextanteUtils.getNumExportedLayers()) + "." + ext
return filename

@staticmethod
def getNumExportedLayers():
SextanteUtils.NUM_EXPORTED += 1
return SextanteUtils.NUM_EXPORTED

def mkdir(newdir):
if os.path.isdir(newdir):
Expand Down
2 changes: 0 additions & 2 deletions src/sextante/ftools/FToolsAlgorithmProvider.py
Expand Up @@ -42,8 +42,6 @@ def __init__(self):
ConvexHull(), FixedDistanceBuffer(), VariableDistanceBuffer(),
Dissolve(), Difference(), Intersection(), Union(), Clip(), ExtentFromLayer(),
RandomSelection(), RandomSelectionWithinSubsets(), SelectByLocation()]
for alg in self.alglist:
alg.provider = self

def getName(self):
return "ftools"
Expand Down
2 changes: 1 addition & 1 deletion src/sextante/ftools/FixedDistanceBuffer.py
Expand Up @@ -9,7 +9,7 @@
from sextante.outputs.OutputVector import OutputVector
from sextante.parameters.ParameterBoolean import ParameterBoolean
from sextante.parameters.ParameterNumber import ParameterNumber
import sextante.ftools.Buffer as buff
from sextante.ftools import Buffer as buff

class FixedDistanceBuffer(GeoAlgorithm):

Expand Down
2 changes: 1 addition & 1 deletion src/sextante/ftools/VariableDistanceBuffer.py
Expand Up @@ -9,7 +9,7 @@
from sextante.outputs.OutputVector import OutputVector
from sextante.parameters.ParameterBoolean import ParameterBoolean
from sextante.parameters.ParameterNumber import ParameterNumber
import sextante.ftools.Buffer as buff
from sextante.ftools import Buffer as buff
from sextante.parameters.ParameterTableField import ParameterTableField

class VariableDistanceBuffer(GeoAlgorithm):
Expand Down
12 changes: 12 additions & 0 deletions src/sextante/gdal/GdalAlgorithm.py
@@ -0,0 +1,12 @@
from sextante.script.ScriptAlgorithm import ScriptAlgorithm
from PyQt4 import QtGui
import os

class GdalAlgorithm(ScriptAlgorithm):
'''Just a ScriptAlgorithm that automatically takes its icon
filename for the script filename'''

def getIcon(self):
filename = os.path.basename(self.descriptionFile[:-2] + "png")
filepath = os.path.dirname(__file__) + "/icons/" + filename
return QtGui.QIcon(filepath)
57 changes: 57 additions & 0 deletions src/sextante/gdal/GdalAlgorithmProvider.py
@@ -0,0 +1,57 @@
import os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.AlgorithmProvider import AlgorithmProvider
from sextante.script.WrongScriptException import WrongScriptException
from sextante.core.SextanteLog import SextanteLog
from sextante.gdal.GdalAlgorithm import GdalAlgorithm
from sextante.gdal.nearblack import nearblack
from sextante.gdal.information import information

class GdalAlgorithmProvider(AlgorithmProvider):

'''This provider incorporates GDAL-based algorithms into SEXTANTE.
Algorithms have been implemented using two different mechanisms,
which should serve as an example of different ways of extending
SEXTANTE:
1)when a python script exist for a given process, it has been adapted
as a SEXTANTE python script and loaded using the ScriptAlgorithm class.
This algorithms call GDAL using its Python bindings
2)Other algorithms are called directly using the command line interface,
These have been implemented individually extending the GeoAlgorithm class'''

def __init__(self):
AlgorithmProvider.__init__(self)
self.createAlgsList()

def scriptsFolder(self):
'''The folder where script algorithms are stored'''
return os.path.dirname(__file__) + "/scripts"

def getName(self):
return "Gdal"

def getIcon(self):
return QIcon(os.path.dirname(__file__) + "/icons/gdalicon.png")

def _loadAlgorithms(self):
'''This is called each time there is a change in the SEXTANTE set of algorithm,
for instance, when the users adds a new model or script. Since this provider
cannot be extended by the user, we create the list in advance and then just
assign it to self.algs'''
self.algs = self.preloadedAlgs

def createAlgsList(self):
#First we populate the list of algorihtms with those created extending
#GeoAlgorithm directly (those that execute GDAL using the console)
self.preloadedAlgs = [nearblack(), information()]
#And then we add those that are created as python scripts
folder = self.scriptsFolder()
for descriptionFile in os.listdir(folder):
if descriptionFile.endswith("py"):
try:
fullpath = os.path.join(self.scriptsFolder(), descriptionFile)
alg = GdalAlgorithm(fullpath)
self.preloadedAlgs.append(alg)
except WrongScriptException,e:
SextanteLog.addToLog(SextanteLog.LOG_ERROR,e.msg)

0 comments on commit f499c85

Please sign in to comment.