mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-10 08:17:49 -06:00
Changed Crash Report layout and new information included - CURA-4195
This commit is contained in:
parent
c9e8f7c743
commit
e2edbd11b6
2 changed files with 135 additions and 70 deletions
|
@ -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,83 +37,145 @@ fatal_exception_types = [
|
||||||
SystemError,
|
SystemError,
|
||||||
]
|
]
|
||||||
|
|
||||||
def show(exception_type, value, tb):
|
class CrashHandler:
|
||||||
Logger.log("c", "An uncaught exception has occurred!")
|
|
||||||
for line in traceback.format_exception(exception_type, value, tb):
|
|
||||||
for part in line.rstrip("\n").split("\n"):
|
|
||||||
Logger.log("c", part)
|
|
||||||
|
|
||||||
if not CuraDebugMode and exception_type not in fatal_exception_types:
|
def __init__(self, exception_type, value, tb):
|
||||||
return
|
|
||||||
|
|
||||||
application = QCoreApplication.instance()
|
self.exception_type = exception_type
|
||||||
if not application:
|
self.value = value
|
||||||
sys.exit(1)
|
self.traceback = tb
|
||||||
|
|
||||||
dialog = QDialog()
|
Logger.log("c", "An uncaught exception has occurred!")
|
||||||
dialog.setMinimumWidth(640)
|
for line in traceback.format_exception(exception_type, value, tb):
|
||||||
dialog.setMinimumHeight(640)
|
for part in line.rstrip("\n").split("\n"):
|
||||||
dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
|
Logger.log("c", part)
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
if not CuraDebugMode and exception_type not in fatal_exception_types:
|
||||||
|
return
|
||||||
|
|
||||||
#label = QLabel(dialog)
|
application = QCoreApplication.instance()
|
||||||
#pixmap = QPixmap()
|
if not application:
|
||||||
#try:
|
sys.exit(1)
|
||||||
# data = urllib.request.urlopen("http://www.randomkittengenerator.com/cats/rotator.php").read()
|
|
||||||
# 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)
|
self._createDialog()
|
||||||
layout.addWidget(label)
|
|
||||||
|
|
||||||
#label.setScaledContents(True)
|
## Creates a modal dialog.
|
||||||
label.setText(catalog.i18nc("@label", """<p>A fatal exception has occurred that we could not recover from!</p>
|
def _createDialog(self):
|
||||||
<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>
|
|
||||||
"""))
|
|
||||||
|
|
||||||
textarea = QTextEdit(dialog)
|
self.dialog = QDialog()
|
||||||
layout.addWidget(textarea)
|
self.dialog.setMinimumWidth(640)
|
||||||
|
self.dialog.setMinimumHeight(640)
|
||||||
|
self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
|
||||||
|
|
||||||
try:
|
layout = QVBoxLayout(self.dialog)
|
||||||
from UM.Application import Application
|
|
||||||
version = Application.getInstance().getVersion()
|
|
||||||
except:
|
|
||||||
version = "Unknown"
|
|
||||||
|
|
||||||
trace = "".join(traceback.format_exception(exception_type, value, tb))
|
layout.addWidget(self._messageWidget())
|
||||||
|
layout.addWidget(self._informationWidget())
|
||||||
|
layout.addWidget(self._exceptionInfoWidget())
|
||||||
|
layout.addWidget(self._logInfoWidget())
|
||||||
|
layout.addWidget(self._userDescriptionWidget())
|
||||||
|
layout.addWidget(self._buttonsWidget())
|
||||||
|
|
||||||
crash_info = "Version: {0}\nPlatform: {1}\nQt: {2}\nPyQt: {3}\n\nException:\n{4}"
|
def _messageWidget(self):
|
||||||
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace)
|
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>
|
||||||
|
"""))
|
||||||
|
|
||||||
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
|
return label
|
||||||
os.close(tmp_file_fd)
|
|
||||||
with open(tmp_file_path, "w") as f:
|
|
||||||
faulthandler.dump_traceback(f, all_threads=True)
|
|
||||||
with open(tmp_file_path, "r") as f:
|
|
||||||
data = f.read()
|
|
||||||
|
|
||||||
msg = "-------------------------\n"
|
def _informationWidget(self):
|
||||||
msg += data
|
group = QGroupBox()
|
||||||
crash_info += "\n\n" + msg
|
group.setTitle("System information")
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
label = QLabel()
|
||||||
|
|
||||||
textarea.setText(crash_info)
|
try:
|
||||||
|
from UM.Application import Application
|
||||||
|
version = Application.getInstance().getVersion()
|
||||||
|
except:
|
||||||
|
version = "Unknown"
|
||||||
|
|
||||||
buttons = QDialogButtonBox(QDialogButtonBox.Close, dialog)
|
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}"
|
||||||
layout.addWidget(buttons)
|
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, self._getOpenGLInfo())
|
||||||
buttons.addButton(catalog.i18nc("@action:button", "Open Web Page"), QDialogButtonBox.HelpRole)
|
label.setText(crash_info)
|
||||||
buttons.rejected.connect(dialog.close)
|
|
||||||
buttons.helpRequested.connect(lambda: webbrowser.open("http://github.com/Ultimaker/Cura/issues"))
|
|
||||||
|
|
||||||
dialog.exec_()
|
layout.addWidget(label)
|
||||||
sys.exit(1)
|
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)
|
||||||
|
os.close(tmp_file_fd)
|
||||||
|
with open(tmp_file_path, "w") as f:
|
||||||
|
faulthandler.dump_traceback(f, all_threads=True)
|
||||||
|
with open(tmp_file_path, "r") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
text_area.setText(data)
|
||||||
|
|
||||||
|
layout.addWidget(text_area)
|
||||||
|
group.setLayout(layout)
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue