diff --git a/python/plugins/sextante/core/AlgorithmProvider.py b/python/plugins/sextante/core/AlgorithmProvider.py index ff276e7e3be..99409c6686d 100644 --- a/python/plugins/sextante/core/AlgorithmProvider.py +++ b/python/plugins/sextante/core/AlgorithmProvider.py @@ -83,23 +83,7 @@ class AlgorithmProvider(): def getDescription(self): '''Returns the full name of the provider''' - return "Generic algorithm provider" - - def getPostProcessingErrorMessage(self, wrongLayers): - '''Returns the message to be shown to the user when after running an algorithm for this provider, - there is a problem loading the resulting layer. - This method should analyze if the problem is caused by wrong entry data, a wrong or missing - installation of a required 3rd party app, or any other cause, and create an error response accordingly. - Message is provided as an HTML code that will be displayed to the user, and which might contains - links to installation paths for missing 3rd party apps. - - wrongLayers: a list of Output objects that could not be loaded.''' - - html ="

Oooops! SEXTANTE could not open the following output layers

The above files could not be opened, which probably indicates that they were not correctly produced by the executed algorithm

" - html +="

Checking the log information might help you see why those layers were not created as expected

" - return html + return "Generic algorithm provider" def getIcon(self): return QtGui.QIcon(os.path.dirname(__file__) + "/../images/alg.png") diff --git a/python/plugins/sextante/core/GeoAlgorithm.py b/python/plugins/sextante/core/GeoAlgorithm.py index 33498aba5ae..dbcda8d91ea 100644 --- a/python/plugins/sextante/core/GeoAlgorithm.py +++ b/python/plugins/sextante/core/GeoAlgorithm.py @@ -408,5 +408,21 @@ class GeoAlgorithm: s+=out.getValueAsCommandLineParameter() + "," s= s[:-1] + ")" return s + + def getPostProcessingErrorMessage(self, wrongLayers): + '''Returns the message to be shown to the user when, after running this algorithm, + there is a problem loading the resulting layer. + This method should analyze if the problem is caused by wrong entry data, a wrong or missing + installation of a required 3rd party app, or any other cause, and create an error response accordingly. + Message is provided as an HTML code that will be displayed to the user, and which might contains + links to installation paths for missing 3rd party apps. + - wrongLayers: a list of Output objects that could not be loaded.''' + + html ="

Oooops! SEXTANTE could not open the following output layers

The above files could not be opened, which probably indicates that they were not correctly produced by the executed algorithm

" + html +="

Checking the log information might help you see why those layers were not created as expected

" + return html diff --git a/python/plugins/sextante/grass/GrassAlgorithm.py b/python/plugins/sextante/grass/GrassAlgorithm.py index 748ec2f3bfb..70745c32d87 100644 --- a/python/plugins/sextante/grass/GrassAlgorithm.py +++ b/python/plugins/sextante/grass/GrassAlgorithm.py @@ -449,7 +449,7 @@ class GrassAlgorithm(GeoAlgorithm): if msg is not None: html = ("

This algorithm requires GRASS to be run." "Unfortunately, it seems that GRASS is not installed in your system, or it is not correctly configured to be used from QGIS

") - html += '

Click here to know more about how to install and configure GRASS to be used with SEXTANTE

' + html += '

Click here to know more about how to install and configure GRASS to be used with SEXTANTE

' return html @@ -463,3 +463,16 @@ class GrassAlgorithm(GeoAlgorithm): func = getattr(module,'checkParameterValuesBeforeExecuting') return func(self) + + def getPostProcessingErrorMessage(self, wrongLayers): + html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers) + msg = GrassUtils.checkGrassIsInstalled(True) + html += ("

This algorithm requires GRASS to be run. A test to check if GRASS is correctly installed " + "and configured in your system has been performed, with the following result:

" + else: + html += msg + "" + html += '

Click here to know more about how to install and configure GRASS to be used with SEXTANTE

' + + return html diff --git a/python/plugins/sextante/grass/GrassAlgorithmProvider.py b/python/plugins/sextante/grass/GrassAlgorithmProvider.py index 25425007e38..e57fb0662f3 100644 --- a/python/plugins/sextante/grass/GrassAlgorithmProvider.py +++ b/python/plugins/sextante/grass/GrassAlgorithmProvider.py @@ -83,19 +83,6 @@ class GrassAlgorithmProvider(AlgorithmProvider): def getIcon(self): return QIcon(os.path.dirname(__file__) + "/../images/grass.png") - def getPostProcessingErrorMessage(self, wrongLayers): - html = AlgorithmProvider.getPostProcessingErrorMessage(self, wrongLayers) - msg = GrassUtils.checkGrassIsInstalled(True) - html += ("

This algorithm requires GRASS to be run. A test to check if GRASS is correctly installed " - "and configured in your system has been performed, with the following result:

" - else: - html += msg + "" - html += '

Click here to know more about how to install and configure GRASS to be used with SEXTANTE

' - - return html - def getSupportedOutputVectorLayerExtensions(self): return ["shp"] diff --git a/python/plugins/sextante/grass/GrassUtils.py b/python/plugins/sextante/grass/GrassUtils.py index 40e55f9fec2..c2dcafb2bd7 100644 --- a/python/plugins/sextante/grass/GrassUtils.py +++ b/python/plugins/sextante/grass/GrassUtils.py @@ -325,7 +325,6 @@ class GrassUtils: if not ignoreRegistrySettings: if settings.contains(GRASS_INSTALLED): return - try: from sextante import runalg result = runalg("grass:v.voronoi", points(),False,False,"270778.60198,270855.745301,4458921.97814,4458983.8488",-1,0.0001, 0, None) diff --git a/python/plugins/sextante/gui/CouldNotLoadResultsDialog.py b/python/plugins/sextante/gui/CouldNotLoadResultsDialog.py index 539efa19d0d..6c20279f736 100644 --- a/python/plugins/sextante/gui/CouldNotLoadResultsDialog.py +++ b/python/plugins/sextante/gui/CouldNotLoadResultsDialog.py @@ -42,7 +42,7 @@ class CouldNotLoadResultsDialog(QtGui.QDialog): webView = QtWebKit.QWebView() webView.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks) webView.connect(webView, SIGNAL("linkClicked(const QUrl&)"), self.linkClicked) - html = self.alg.provider.getPostProcessingErrorMessage(self.wrongLayers) + html = self.alg.getPostProcessingErrorMessage(self.wrongLayers) webView.setHtml(html) closeButton = QtGui.QPushButton() closeButton.setText("Close") diff --git a/python/plugins/sextante/r/RAlgorithm.py b/python/plugins/sextante/r/RAlgorithm.py index c405af5bfc5..aad6472ac6b 100644 --- a/python/plugins/sextante/r/RAlgorithm.py +++ b/python/plugins/sextante/r/RAlgorithm.py @@ -270,22 +270,19 @@ class RAlgorithm(GeoAlgorithm): def getImportCommands(self): commands = [] - # if rgdal is not available, try to install it + # just use main mirror commands.append('options("repos"="http://cran.at.r-project.org/")') - rLibDir = "%s/rlibs" % SextanteUtils.userFolder().replace("\\","/") - if not os.path.isdir(rLibDir): - os.mkdir(rLibDir) - # .libPaths("%s") substitutes the personal libPath with "%s"! With '.libPaths(c("%s",deflibloc))' it is added without replacing and we can use all installed R packages! - commands.append('deflibloc <- .libPaths()[1]') - commands.append('.libPaths(c("%s",deflibloc))' % rLibDir ) - commands.append( - 'tryCatch(find.package("rgdal"), error=function(e) install.packages("rgdal", dependencies=TRUE, lib="%s"))' % rLibDir) - commands.append("library(\"rgdal\")"); - #if not self.useRasterPackage or self.passFileNames: - commands.append( - 'tryCatch(find.package("raster"), error=function(e) install.packages("raster", dependencies=TRUE, lib="%s"))' % rLibDir) - commands.append("library(\"raster\")"); + + # try to install packages if needed + packages = RUtils.getRequiredPackages(self.script) + packages.extend(['rgdal', 'raster']) + for p in packages: + commands.append( + 'tryCatch(find.package("' + p + + '"), error=function(e) install.packages("' + p +'", dependencies=TRUE))') + commands.append('library("raster")') + commands.append('library("rgdal")') for param in self.parameters: if isinstance(param, ParameterRaster): @@ -386,28 +383,28 @@ class RAlgorithm(GeoAlgorithm): return None def checkBeforeOpeningParametersDialog(self): - if SextanteUtils.isWindows(): - path = RUtils.RFolder() - if path == "": - return "R folder is not configured.\nPlease configure it before running R scripts." + msg = RUtils.checkRIsInstalled() + if msg is not None: + html = ("

This algorithm requires R to be run." + "Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS

") + html += '

Click here to know more about how to install and configure R to be used with SEXTANTE

' + return html - R_INSTALLED = "R_INSTALLED" - settings = QSettings() - if settings.contains(R_INSTALLED): - return - if SextanteUtils.isWindows(): - if SextanteConfig.getSetting(RUtils.R_USE64): - execDir = "x64" - else: - execDir = "i386" - command = [RUtils.RFolder() + os.sep + "bin" + os.sep + execDir + os.sep + "R.exe", "--version"] + + def getPostProcessingErrorMessage(self, wrongLayers): + html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers) + msg = RUtils.checkRIsInstalled(True) + html += ("

This algorithm requires R to be run. A test to check if R is correctly installed " + "and configured in your system has been performed, with the following result:

" + html += "

The script you have executed needs the following packages:

Make sure they are installed in your R environment before trying to execute this script.

" else: - command = ["R --version"] - proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT, universal_newlines=True).stdout - - for line in iter(proc.readline, ""): - if "R version" in line: - settings.setValue(R_INSTALLED, True) - return - return "It seems that R is not correctly installed in your system.\nPlease install it before running R Scripts." + html += msg + "" + html += '

Click here to know more about how to install and configure R to be used with SEXTANTE

' + return html diff --git a/python/plugins/sextante/r/RUtils.py b/python/plugins/sextante/r/RUtils.py index d7a2a784a9b..0807b8e239d 100644 --- a/python/plugins/sextante/r/RUtils.py +++ b/python/plugins/sextante/r/RUtils.py @@ -16,6 +16,7 @@ * * *************************************************************************** """ +import re __author__ = 'Victor Olaya' __date__ = 'August 2012' @@ -24,6 +25,7 @@ __copyright__ = '(C) 2012, Victor Olaya' __revision__ = '$Format:%H$' from PyQt4.QtGui import * +from PyQt4.QtCore import * from sextante.core.SextanteConfig import SextanteConfig import os from sextante.core.SextanteUtils import mkdir, SextanteUtils @@ -123,3 +125,41 @@ class RUtils: s+="\n" return s + + @staticmethod + def checkRIsInstalled(ignoreRegistrySettings=False): + if SextanteUtils.isWindows(): + path = RUtils.RFolder() + if path == "": + return "R folder is not configured.\nPlease configure it before running R scripts." + + R_INSTALLED = "R_INSTALLED" + settings = QSettings() + if not ignoreRegistrySettings: + if settings.contains(R_INSTALLED): + return + if SextanteUtils.isWindows(): + if SextanteConfig.getSetting(RUtils.R_USE64): + execDir = "x64" + else: + execDir = "i386" + command = [RUtils.RFolder() + os.sep + "bin" + os.sep + execDir + os.sep + "R.exe", "--version"] + else: + command = ["R --version"] + proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT, universal_newlines=True).stdout + + for line in iter(proc.readline, ""): + if "R version" in line: + settings.setValue(R_INSTALLED, True) + return + html = ("

This algorithm requires R to be run." + "Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS

" + '

Click here' + 'to know more about how to install and configure R to be used with SEXTANTE

') + return html + + @staticmethod + def getRequiredPackages(code): + regex = re.compile('library\("?(.*?)"?\)') + return regex.findall(code) + \ No newline at end of file diff --git a/python/plugins/sextante/saga/SagaAlgorithm.py b/python/plugins/sextante/saga/SagaAlgorithm.py index 9aaadd50ad0..793be229e16 100644 --- a/python/plugins/sextante/saga/SagaAlgorithm.py +++ b/python/plugins/sextante/saga/SagaAlgorithm.py @@ -362,7 +362,7 @@ class SagaAlgorithm(GeoAlgorithm): if msg is not None: html = ("

This algorithm requires SAGA to be run." "Unfortunately, it seems that SAGA is not installed in your system, or it is not correctly configured to be used from QGIS

") - html += '

Click here to know more about how to install and configure SAGA to be used with SEXTANTE

' + html += '

Click here to know more about how to install and configure SAGA to be used with SEXTANTE

' return html @@ -379,7 +379,18 @@ class SagaAlgorithm(GeoAlgorithm): def helpFile(self): return os.path.join(os.path.dirname(__file__), "help", self.name.replace(" ", "") + ".html") + def getPostProcessingErrorMessage(self, wrongLayers): + html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers) + msg = SagaUtils.checkSagaIsInstalled(True) + html += ("

This algorithm requires SAGA to be run. A test to check if SAGA is correctly installed " + "and configured in your system has been performed, with the following result:

" + else: + html += msg + "" + html += '

Click here to know more about how to install and configure SAGA to be used with SEXTANTE

' + return html #=========================================================================== # def commandLineName(self): # name = self.provider.getName().lower() + ":" + self.cmdname.lower() diff --git a/python/plugins/sextante/saga/SagaAlgorithmProvider.py b/python/plugins/sextante/saga/SagaAlgorithmProvider.py index bff8cd4163b..c7c14ad569d 100644 --- a/python/plugins/sextante/saga/SagaAlgorithmProvider.py +++ b/python/plugins/sextante/saga/SagaAlgorithmProvider.py @@ -99,19 +99,6 @@ class SagaAlgorithmProvider(AlgorithmProvider): def getName(self): return "saga" - def getPostProcessingErrorMessage(self, wrongLayers): - html = AlgorithmProvider.getPostProcessingErrorMessage(self, wrongLayers) - msg = SagaUtils.checkSagaIsInstalled(True) - html += ("

This algorithm requires SAGA to be run. A test to check if SAGA is correctly installed " - "and configured in your system has been performed, with the following result:

" - else: - html += msg + "" - html += '

Click here to know more about how to install and configure SAGA to be used with SEXTANTE

' - - return html - def getSupportedOutputVectorLayerExtensions(self): return ["shp"]