Changed Crash Report layout and new information included - CURA-4195

This commit is contained in:
Diego Prado Gesto 2017-10-09 11:50:30 +02:00
parent c9e8f7c743
commit e2edbd11b6
2 changed files with 135 additions and 70 deletions

View file

@ -5,14 +5,15 @@ import webbrowser
import faulthandler import faulthandler
import tempfile import tempfile
import os import os
import urllib
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, Qt, QCoreApplication from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication
from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QVBoxLayout, QLabel, QTextEdit from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply
from UM.Logger import Logger from UM.Logger import Logger
from UM.View.GL.OpenGL import OpenGL
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
MYPY = False MYPY = False
@ -23,6 +24,7 @@ else:
from cura.CuraVersion import CuraDebugMode from cura.CuraVersion import CuraDebugMode
except ImportError: except ImportError:
CuraDebugMode = False # [CodeStyle: Reflecting imported value] CuraDebugMode = False # [CodeStyle: Reflecting imported value]
CuraDebugMode = True ## TODO Remove when done. Just for debug purposes
# List of exceptions that should be considered "fatal" and abort the program. # List of exceptions that should be considered "fatal" and abort the program.
# These are primarily some exception types that we simply cannot really recover from # These are primarily some exception types that we simply cannot really recover from
@ -35,7 +37,14 @@ fatal_exception_types = [
SystemError, SystemError,
] ]
def show(exception_type, value, tb): class CrashHandler:
def __init__(self, exception_type, value, tb):
self.exception_type = exception_type
self.value = value
self.traceback = tb
Logger.log("c", "An uncaught exception has occurred!") Logger.log("c", "An uncaught exception has occurred!")
for line in traceback.format_exception(exception_type, value, tb): for line in traceback.format_exception(exception_type, value, tb):
for part in line.rstrip("\n").split("\n"): for part in line.rstrip("\n").split("\n"):
@ -48,40 +57,38 @@ def show(exception_type, value, tb):
if not application: if not application:
sys.exit(1) sys.exit(1)
dialog = QDialog() self._createDialog()
dialog.setMinimumWidth(640)
dialog.setMinimumHeight(640)
dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
layout = QVBoxLayout(dialog) ## Creates a modal dialog.
def _createDialog(self):
#label = QLabel(dialog) self.dialog = QDialog()
#pixmap = QPixmap() self.dialog.setMinimumWidth(640)
#try: self.dialog.setMinimumHeight(640)
# data = urllib.request.urlopen("http://www.randomkittengenerator.com/cats/rotator.php").read() self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
# pixmap.loadFromData(data)
#except:
# try:
# from UM.Resources import Resources
# path = Resources.getPath(Resources.Images, "kitten.jpg")
# pixmap.load(path)
# except:
# pass
#pixmap = pixmap.scaled(150, 150)
#label.setPixmap(pixmap)
#label.setAlignment(Qt.AlignCenter)
#layout.addWidget(label)
label = QLabel(dialog) layout = QVBoxLayout(self.dialog)
layout.addWidget(label)
#label.setScaledContents(True) layout.addWidget(self._messageWidget())
label.setText(catalog.i18nc("@label", """<p>A fatal exception has occurred that we could not recover from!</p> layout.addWidget(self._informationWidget())
<p>Please use the information below to post a bug report at <a href=\"http://github.com/Ultimaker/Cura/issues\">http://github.com/Ultimaker/Cura/issues</a></p> layout.addWidget(self._exceptionInfoWidget())
layout.addWidget(self._logInfoWidget())
layout.addWidget(self._userDescriptionWidget())
layout.addWidget(self._buttonsWidget())
def _messageWidget(self):
label = QLabel()
label.setText(catalog.i18nc("@label", """<p><b>A fatal exception has occurred that we could not recover from!</p></b>
<p>Please use the button below to post a bug report automatically to our servers</p>
""")) """))
textarea = QTextEdit(dialog) return label
layout.addWidget(textarea)
def _informationWidget(self):
group = QGroupBox()
group.setTitle("System information")
layout = QVBoxLayout()
label = QLabel()
try: try:
from UM.Application import Application from UM.Application import Application
@ -89,11 +96,35 @@ def show(exception_type, value, tb):
except: except:
version = "Unknown" version = "Unknown"
trace = "".join(traceback.format_exception(exception_type, value, tb)) crash_info = "<b>Version:</b> {0}<br/><b>Platform:</b> {1}<br/><b>Qt:</b> {2}<br/><b>PyQt:</b> {3}<br/><b>OpenGL:</b> {4}"
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, self._getOpenGLInfo())
label.setText(crash_info)
crash_info = "Version: {0}\nPlatform: {1}\nQt: {2}\nPyQt: {3}\n\nException:\n{4}" layout.addWidget(label)
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace) group.setLayout(layout)
return group
def _exceptionInfoWidget(self):
group = QGroupBox()
group.setTitle("Exception traceback")
layout = QVBoxLayout()
text_area = QTextEdit()
trace = "".join(traceback.format_exception(self.exception_type, self.value, self.traceback))
text_area.setText(trace)
layout.addWidget(text_area)
group.setLayout(layout)
return group
def _logInfoWidget(self):
group = QGroupBox()
group.setTitle("Logs")
layout = QVBoxLayout()
text_area = QTextEdit()
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True) tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
os.close(tmp_file_fd) os.close(tmp_file_fd)
with open(tmp_file_path, "w") as f: with open(tmp_file_path, "w") as f:
@ -101,17 +132,50 @@ def show(exception_type, value, tb):
with open(tmp_file_path, "r") as f: with open(tmp_file_path, "r") as f:
data = f.read() data = f.read()
msg = "-------------------------\n" text_area.setText(data)
msg += data
crash_info += "\n\n" + msg
textarea.setText(crash_info) layout.addWidget(text_area)
group.setLayout(layout)
buttons = QDialogButtonBox(QDialogButtonBox.Close, dialog) return group
layout.addWidget(buttons)
buttons.addButton(catalog.i18nc("@action:button", "Open Web Page"), QDialogButtonBox.HelpRole)
buttons.rejected.connect(dialog.close)
buttons.helpRequested.connect(lambda: webbrowser.open("http://github.com/Ultimaker/Cura/issues"))
dialog.exec_()
def _userDescriptionWidget(self):
group = QGroupBox()
group.setTitle("User description")
layout = QVBoxLayout()
text_area = QTextEdit()
layout.addWidget(text_area)
group.setLayout(layout)
return group
def _buttonsWidget(self):
buttons = QDialogButtonBox()
buttons.addButton(QDialogButtonBox.Close)
buttons.addButton(catalog.i18nc("@action:button", "Send to developers"), QDialogButtonBox.AcceptRole)
buttons.rejected.connect(self.dialog.close)
buttons.accepted.connect(self._sendCrashReport)
return buttons
def _getOpenGLInfo(self):
info = "<ul><li>OpenGL Version: {0}</li><li>OpenGL Vendor: {1}</li><li>OpenGL Renderer: {2}</li></ul>"
info = info.format(OpenGL.getInstance().getGPUVersion(), OpenGL.getInstance().getGPUVendorName(), OpenGL.getInstance().getGPUType())
return info
def _sendCrashReport(self):
print("Hello")
# _manager = QNetworkAccessManager()
# api_url = QUrl("url")
# put_request = QNetworkRequest(api_url)
# put_request.setHeader(QNetworkRequest.ContentTypeHeader, "text/plain")
# _manager.put(put_request, crash_info.encode())
#
# sys.exit(1)
def show(self):
self.dialog.exec_()
sys.exit(1) sys.exit(1)

View file

@ -41,8 +41,9 @@ if "PYTHONPATH" in os.environ.keys(): # If PYTHONPATH is u
sys.path.insert(1, PATH_real) # Insert it at 1 after os.curdir, which is 0. sys.path.insert(1, PATH_real) # Insert it at 1 after os.curdir, which is 0.
def exceptHook(hook_type, value, traceback): def exceptHook(hook_type, value, traceback):
import cura.CrashHandler from cura.CrashHandler import CrashHandler
cura.CrashHandler.show(hook_type, value, traceback) _crash_handler = CrashHandler(hook_type, value, traceback)
_crash_handler.show()
sys.excepthook = exceptHook sys.excepthook = exceptHook