mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[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
This commit is contained in:
parent
2e7f344214
commit
5a00912b3d
@ -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)
|
||||
|
@ -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(
|
||||
'<p>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:</p><ul><i>')
|
||||
if msg is None:
|
||||
html += self.tr('GRASS seems to be correctly installed and '
|
||||
'configured</i></li></ul>')
|
||||
else:
|
||||
html += msg + '</i></li></ul>'
|
||||
html += self.tr(
|
||||
'<p><a href="http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Click here</a> '
|
||||
'to know more about how to install and configure GRASS to be used with QGIS</p>')
|
||||
|
||||
return html
|
||||
|
@ -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(
|
||||
'<p>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:</p><ul><i>')
|
||||
if msg is None:
|
||||
html += self.tr(
|
||||
'GRASS GIS 7 seems to be correctly installed and configured</i></li></ul>')
|
||||
else:
|
||||
html += msg + '</i></li></ul>'
|
||||
html += self.tr(
|
||||
'<p><a href="http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Click here</a> '
|
||||
'to know more about how to install and configure GRASS GIS 7 to be used with QGIS</p>')
|
||||
|
||||
return html
|
||||
|
@ -415,27 +415,4 @@ class RAlgorithm(GeoAlgorithm):
|
||||
'to know more about how to install and configure R to be used with QGIS</p>')
|
||||
return html
|
||||
|
||||
def getPostProcessingErrorMessage(self, wrongLayers):
|
||||
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
|
||||
msg = RUtils.checkRIsInstalled(True)
|
||||
html += self.tr(
|
||||
'<p>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:</p><ul><i>')
|
||||
if msg is None:
|
||||
html += self.tr(
|
||||
'R seems to be correctly installed and configured</i></li></ul>'
|
||||
'<p>The script you have executed needs the following packages:</p><ul>')
|
||||
packages = RUtils.getRequiredPackages(self.script)
|
||||
for p in packages:
|
||||
html += '<li>' + p + '</li>'
|
||||
html += self.tr(
|
||||
'</ul><p>Make sure they are installed in your R '
|
||||
'environment before trying to execute this script.</p>')
|
||||
else:
|
||||
html += msg + '</i></li></ul>'
|
||||
html += self.tr(
|
||||
'<p><a href= "http://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html">Click here</a> '
|
||||
'to know more about how to install and configure R to be used with QGIS</p>')
|
||||
|
||||
return html
|
||||
|
@ -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('<p>Oooops! The following output layers could not be '
|
||||
'open</p><ul>\n')
|
||||
for layer in wrongLayers:
|
||||
html += self.tr('<li>%s: <font size=3 face="Courier New" '
|
||||
'color="#ff0000">%s</font></li>\n') % (
|
||||
layer.description, layer.value
|
||||
)
|
||||
html += self.tr('</ul><p>The above files could not be opened, which '
|
||||
'probably indicates that they were not correctly '
|
||||
'produced by the executed algorithm</p>'
|
||||
'<p>Checking the log information might help you see '
|
||||
'why those layers were not created as expected</p>')
|
||||
return html
|
||||
|
||||
def tr(self, string, context=''):
|
||||
if context == '':
|
||||
context = self.__class__.__name__
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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.<ul>"
|
||||
msg += "".join(["<li>%s</li>" % lay for lay in wrongLayers]) + "</ul>"
|
||||
msg += "You can check the <a href='log'>log messages</a> to find more information about the execution of the algorithm"
|
||||
dlg.setMessage(msg)
|
||||
dlg.exec_()
|
||||
|
||||
if showResults and htmlResults and not wrongLayers:
|
||||
|
Loading…
x
Reference in New Issue
Block a user