From 5a00912b3dc9494a54c71a24e5a6dc4e2670064e Mon Sep 17 00:00:00 2001 From: volaya Date: Wed, 20 May 2015 19:33:47 +0200 Subject: [PATCH] [processing] more friendly error message when layers not created This commit includes changes to the log system as well, which now logs only algorithms. Messages are logged to the QGIS logging system --- python/plugins/processing/ProcessingPlugin.py | 2 +- .../processing/algs/grass/GrassAlgorithm.py | 17 ---------- .../processing/algs/grass7/Grass7Algorithm.py | 17 ---------- .../plugins/processing/algs/r/RAlgorithm.py | 23 ------------- .../plugins/processing/core/GeoAlgorithm.py | 32 ------------------- .../plugins/processing/core/ProcessingLog.py | 32 +++++++++---------- .../plugins/processing/gui/HistoryDialog.py | 7 ++-- .../plugins/processing/gui/MessageDialog.py | 11 +++++-- .../plugins/processing/gui/Postprocessing.py | 7 ++-- 9 files changed, 35 insertions(+), 113 deletions(-) diff --git a/python/plugins/processing/ProcessingPlugin.py b/python/plugins/processing/ProcessingPlugin.py index 968b8a45052..01139e0ef80 100644 --- a/python/plugins/processing/ProcessingPlugin.py +++ b/python/plugins/processing/ProcessingPlugin.py @@ -81,7 +81,7 @@ class ProcessingPlugin: self.historyAction = QAction( QIcon(os.path.join(cmd_folder, 'images', 'history.gif')), - self.tr('&History and Log...'), self.iface.mainWindow()) + self.tr('&History...'), self.iface.mainWindow()) self.historyAction.setObjectName('historyAction') self.historyAction.triggered.connect(self.openHistory) self.menu.addAction(self.historyAction) diff --git a/python/plugins/processing/algs/grass/GrassAlgorithm.py b/python/plugins/processing/algs/grass/GrassAlgorithm.py index 6ca45701d10..d865b27dc50 100644 --- a/python/plugins/processing/algs/grass/GrassAlgorithm.py +++ b/python/plugins/processing/algs/grass/GrassAlgorithm.py @@ -510,20 +510,3 @@ class GrassAlgorithm(GeoAlgorithm): func = getattr(module, 'checkParameterValuesBeforeExecuting') return func(self) - def getPostProcessingErrorMessage(self, wrongLayers): - html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers) - msg = GrassUtils.checkGrassIsInstalled(True) - html += self.tr( - '

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 += self.tr( - '

Click here ' - 'to know more about how to install and configure GRASS to be used with QGIS

') - - return html diff --git a/python/plugins/processing/algs/grass7/Grass7Algorithm.py b/python/plugins/processing/algs/grass7/Grass7Algorithm.py index 4e559b4f342..558a4ac9cb1 100644 --- a/python/plugins/processing/algs/grass7/Grass7Algorithm.py +++ b/python/plugins/processing/algs/grass7/Grass7Algorithm.py @@ -519,20 +519,3 @@ class Grass7Algorithm(GeoAlgorithm): func = getattr(module, 'checkParameterValuesBeforeExecuting') return func(self) - def getPostProcessingErrorMessage(self, wrongLayers): - html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers) - msg = Grass7Utils.checkGrass7IsInstalled(True) - html += self.tr( - '

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

') - else: - html += msg + '' - html += self.tr( - '

Click here ' - 'to know more about how to install and configure GRASS GIS 7 to be used with QGIS

') - - return html diff --git a/python/plugins/processing/algs/r/RAlgorithm.py b/python/plugins/processing/algs/r/RAlgorithm.py index 08e452ea56c..eafaf429e4e 100644 --- a/python/plugins/processing/algs/r/RAlgorithm.py +++ b/python/plugins/processing/algs/r/RAlgorithm.py @@ -415,27 +415,4 @@ class RAlgorithm(GeoAlgorithm): 'to know more about how to install and configure R to be used with QGIS

') return html - def getPostProcessingErrorMessage(self, wrongLayers): - html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers) - msg = RUtils.checkRIsInstalled(True) - html += self.tr( - '

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:

' - '

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: - html += msg + '' - html += self.tr( - '

Click here ' - 'to know more about how to install and configure R to be used with QGIS

') - return html diff --git a/python/plugins/processing/core/GeoAlgorithm.py b/python/plugins/processing/core/GeoAlgorithm.py index 3973da6f539..523c4142ded 100644 --- a/python/plugins/processing/core/GeoAlgorithm.py +++ b/python/plugins/processing/core/GeoAlgorithm.py @@ -525,38 +525,6 @@ class GeoAlgorithm: 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 = self.tr('

Oooops! The following output layers could not be ' - 'open

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

' - '

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

') - return html - def tr(self, string, context=''): if context == '': context = self.__class__.__name__ diff --git a/python/plugins/processing/core/ProcessingLog.py b/python/plugins/processing/core/ProcessingLog.py index f7262265670..24ccb0b4b65 100644 --- a/python/plugins/processing/core/ProcessingLog.py +++ b/python/plugins/processing/core/ProcessingLog.py @@ -31,6 +31,7 @@ import codecs import datetime from processing.tools.system import userFolder from processing.core.ProcessingConfig import ProcessingConfig +from qgis.core import * class ProcessingLog: @@ -66,20 +67,15 @@ class ProcessingLog: # added. To avoid it stopping the normal functioning of the # algorithm, we catch all errors, assuming that is better # to miss some log info that breaking the algorithm. - if isinstance(msg, list): - a = '|'.join(m.strip('\n') for m in msg) - text = a - else: - text = msg.replace('\n', '|') - line = msgtype + '|' + datetime.datetime.now().strftime( - ProcessingLog.DATE_FORMAT).decode('utf-8') + '|' \ - + text + '\n' - logfile = codecs.open(ProcessingLog.logFilename(), 'a', - encoding='utf-8') - logfile.write(line) - logfile.close() if msgtype == ProcessingLog.LOG_ALGORITHM: - algname = text[len('Processing.runalg("'):] + line = msgtype + '|' + datetime.datetime.now().strftime( + ProcessingLog.DATE_FORMAT).decode('utf-8') + '|' \ + + msg + '\n' + logfile = codecs.open(ProcessingLog.logFilename(), 'a', + encoding='utf-8') + logfile.write(line) + logfile.close() + algname = msg[len('Processing.runalg("'):] algname = algname[:algname.index('"')] if algname not in ProcessingLog.recentAlgs: ProcessingLog.recentAlgs.append(algname) @@ -87,6 +83,13 @@ class ProcessingLog: ProcessingConfig.setSettingValue( ProcessingConfig.RECENT_ALGORITHMS, recentAlgsString) + else: + if isinstance(msg, list): + msg = '\n'.join([m for m in msg]) + msgtypes = {ProcessingLog.LOG_ERROR: QgsMessageLog.CRITICAL, + ProcessingLog.LOG_INFO: QgsMessageLog.INFO, + ProcessingLog.LOG_WARNING: QgsMessageLog.WARNING,} + QgsMessageLog.logMessage(msg, "Processing", msgtypes[msgtype]) except: pass @@ -113,10 +116,7 @@ class ProcessingLog: elif line.startswith(ProcessingLog.LOG_INFO): info.append(LogEntry(tokens[1], text)) - entries[ProcessingLog.LOG_ERROR] = errors entries[ProcessingLog.LOG_ALGORITHM] = algorithms - entries[ProcessingLog.LOG_INFO] = info - entries[ProcessingLog.LOG_WARNING] = warnings return entries @staticmethod diff --git a/python/plugins/processing/gui/HistoryDialog.py b/python/plugins/processing/gui/HistoryDialog.py index 006b5d4f5f8..608769ea6b4 100644 --- a/python/plugins/processing/gui/HistoryDialog.py +++ b/python/plugins/processing/gui/HistoryDialog.py @@ -54,11 +54,11 @@ class HistoryDialog(BASE, WIDGET): self.keyIcon.addPixmap(self.style().standardPixmap(QStyle.SP_FileIcon)) self.clearButton = QPushButton(self.tr('Clear')) - self.clearButton.setToolTip(self.tr('Clear history and log')) + self.clearButton.setToolTip(self.tr('Clear history')) self.buttonBox.addButton(self.clearButton, QDialogButtonBox.ActionRole) self.saveButton = QPushButton(self.tr('Save As...')) - self.saveButton.setToolTip(self.tr('Save history and log')) + self.saveButton.setToolTip(self.tr('Save history')) self.buttonBox.addButton(self.saveButton, QDialogButtonBox.ActionRole) self.tree.doubleClicked.connect(self.executeAlgorithm) @@ -74,7 +74,7 @@ class HistoryDialog(BASE, WIDGET): def clearLog(self): reply = QMessageBox.question(self, self.tr('Confirmation'), - self.tr('Are you sure you want to clear log?'), + self.tr('Are you sure you want to clear the history?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No ) @@ -128,6 +128,7 @@ class HistoryDialog(BASE, WIDGET): TestTools.createTest(item.entry.text) def showPopupMenu(self, point): + return item = self.tree.currentItem() if isinstance(item, TreeLogEntryItem): if item.isAlg: diff --git a/python/plugins/processing/gui/MessageDialog.py b/python/plugins/processing/gui/MessageDialog.py index d4777e1ab5a..85e4dcb77bc 100644 --- a/python/plugins/processing/gui/MessageDialog.py +++ b/python/plugins/processing/gui/MessageDialog.py @@ -29,7 +29,9 @@ import os from PyQt4 import uic from PyQt4.QtCore import QUrl -from PyQt4.QtGui import QDesktopServices +from PyQt4.QtGui import QDesktopServices, QDockWidget + +from qgis.utils import iface pluginPath = os.path.split(os.path.dirname(__file__))[0] WIDGET, BASE = uic.loadUiType( @@ -51,4 +53,9 @@ class MessageDialog(BASE, WIDGET): self.txtMessage.setHtml(message) def openLink(self, url): - QDesktopServices.openUrl(QUrl(url)) + if url.toString() == "log": + self.close() + logDock = iface.mainWindow().findChild(QDockWidget, 'MessageLog') + logDock.show() + else: + QDesktopServices.openUrl(url) diff --git a/python/plugins/processing/gui/Postprocessing.py b/python/plugins/processing/gui/Postprocessing.py index e867a8142d3..cb224837ecf 100644 --- a/python/plugins/processing/gui/Postprocessing.py +++ b/python/plugins/processing/gui/Postprocessing.py @@ -71,7 +71,7 @@ def handleAlgorithmResults(alg, progress=None, showResults=True): RenderingStyles.getStyle(alg.commandLineName(), out.name)) except Exception, e: - wrongLayers.append(out) + wrongLayers.append(out.description) elif isinstance(out, OutputHTML): ProcessingResults.addResult(out.description, out.value) htmlResults = True @@ -80,7 +80,10 @@ def handleAlgorithmResults(alg, progress=None, showResults=True): QApplication.restoreOverrideCursor() dlg = MessageDialog() dlg.setTitle(QCoreApplication.translate('Postprocessing', 'Problem loading output layers')) - dlg.setMessage(alg.getPostProcessingErrorMessage(wrongLayers)) + msg = "The following layers were not correctly generated." + msg += "You can check the log messages to find more information about the execution of the algorithm" + dlg.setMessage(msg) dlg.exec_() if showResults and htmlResults and not wrongLayers: