From e2edbd11b66e828fce6c024765753a8fa2fcdf43 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 9 Oct 2017 11:50:30 +0200 Subject: [PATCH 1/6] Changed Crash Report layout and new information included - CURA-4195 --- cura/CrashHandler.py | 200 ++++++++++++++++++++++++++++--------------- cura_app.py | 5 +- 2 files changed, 135 insertions(+), 70 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index 7008ba64d2..dbf931b37e 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -5,14 +5,15 @@ import webbrowser import faulthandler import tempfile import os -import urllib -from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, Qt, QCoreApplication -from PyQt5.QtGui import QPixmap -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QVBoxLayout, QLabel, QTextEdit +from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox +from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply from UM.Logger import Logger +from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog + catalog = i18nCatalog("cura") MYPY = False @@ -23,6 +24,7 @@ else: from cura.CuraVersion import CuraDebugMode except ImportError: 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. # These are primarily some exception types that we simply cannot really recover from @@ -35,83 +37,145 @@ fatal_exception_types = [ SystemError, ] -def show(exception_type, value, tb): - 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) +class CrashHandler: - if not CuraDebugMode and exception_type not in fatal_exception_types: - return + def __init__(self, exception_type, value, tb): - application = QCoreApplication.instance() - if not application: - sys.exit(1) + self.exception_type = exception_type + self.value = value + self.traceback = tb - dialog = QDialog() - dialog.setMinimumWidth(640) - dialog.setMinimumHeight(640) - dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report")) + 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) - layout = QVBoxLayout(dialog) + if not CuraDebugMode and exception_type not in fatal_exception_types: + return - #label = QLabel(dialog) - #pixmap = QPixmap() - #try: - # 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) + application = QCoreApplication.instance() + if not application: + sys.exit(1) - label = QLabel(dialog) - layout.addWidget(label) + self._createDialog() - #label.setScaledContents(True) - label.setText(catalog.i18nc("@label", """

A fatal exception has occurred that we could not recover from!

-

Please use the information below to post a bug report at http://github.com/Ultimaker/Cura/issues

- """)) + ## Creates a modal dialog. + def _createDialog(self): - textarea = QTextEdit(dialog) - layout.addWidget(textarea) + self.dialog = QDialog() + self.dialog.setMinimumWidth(640) + self.dialog.setMinimumHeight(640) + self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report")) - try: - from UM.Application import Application - version = Application.getInstance().getVersion() - except: - version = "Unknown" + layout = QVBoxLayout(self.dialog) - 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}" - crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace) + def _messageWidget(self): + label = QLabel() + label.setText(catalog.i18nc("@label", """

A fatal exception has occurred that we could not recover from!

+

Please use the button below to post a bug report automatically to our servers

+ """)) - 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() + return label - msg = "-------------------------\n" - msg += data - crash_info += "\n\n" + msg + def _informationWidget(self): + group = QGroupBox() + 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) - 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")) + crash_info = "Version: {0}
Platform: {1}
Qt: {2}
PyQt: {3}
OpenGL: {4}" + crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, self._getOpenGLInfo()) + label.setText(crash_info) - dialog.exec_() - sys.exit(1) + layout.addWidget(label) + 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 = "" + 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) \ No newline at end of file diff --git a/cura_app.py b/cura_app.py index 6869fd2111..d725bc1200 100755 --- a/cura_app.py +++ b/cura_app.py @@ -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. def exceptHook(hook_type, value, traceback): - import cura.CrashHandler - cura.CrashHandler.show(hook_type, value, traceback) + from cura.CrashHandler import CrashHandler + _crash_handler = CrashHandler(hook_type, value, traceback) + _crash_handler.show() sys.excepthook = exceptHook From cf1f0ffaf11afc0272d799edd4434073a4614798 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 9 Oct 2017 16:05:37 +0200 Subject: [PATCH 2/6] Adding info to be sent as JSON and send when button is pressed - CURA-4195 --- cura/CrashHandler.py | 80 +++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index dbf931b37e..eb1f594c60 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -5,14 +5,19 @@ import webbrowser import faulthandler import tempfile import os +import time +import json +import ssl +import urllib.request +import urllib.error -from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication +from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication, Qt from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox -from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply from UM.Logger import Logger from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog +from UM.Platform import Platform catalog = i18nCatalog("cura") @@ -38,6 +43,7 @@ fatal_exception_types = [ ] class CrashHandler: + crash_url = "https://stats.ultimaker.com/api/cura" def __init__(self, exception_type, value, tb): @@ -45,6 +51,10 @@ class CrashHandler: self.value = value self.traceback = tb + # While we create the GUI, the information will be stored for sending afterwards + self.data = dict() + self.data["time_stamp"] = time.time() + 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"): @@ -103,8 +113,21 @@ class CrashHandler: layout.addWidget(label) group.setLayout(layout) + self.data["cura_version"] = version + self.data["os"] = {"type": platform.system(), "version": platform.version()} + self.data["qt_version"] = QT_VERSION_STR + self.data["pyqt_version"] = PYQT_VERSION_STR + return group + def _getOpenGLInfo(self): + info = "" + info = info.format(OpenGL.getInstance().getGPUVersion(), OpenGL.getInstance().getGPUVendorName(), OpenGL.getInstance().getGPUType()) + + self.data["opengl"] = {"version": OpenGL.getInstance().getGPUVersion(), "vendor": OpenGL.getInstance().getGPUVendorName(), "type": OpenGL.getInstance().getGPUType()} + + return info + def _exceptionInfoWidget(self): group = QGroupBox() group.setTitle("Exception traceback") @@ -113,10 +136,13 @@ class CrashHandler: text_area = QTextEdit() trace = "".join(traceback.format_exception(self.exception_type, self.value, self.traceback)) text_area.setText(trace) + text_area.setReadOnly(True) layout.addWidget(text_area) group.setLayout(layout) + self.data["traceback"] = trace + return group def _logInfoWidget(self): @@ -130,13 +156,16 @@ class CrashHandler: 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() + logdata = f.read() - text_area.setText(data) + text_area.setText(logdata) + text_area.setReadOnly(True) layout.addWidget(text_area) group.setLayout(layout) + self.data["log"] = logdata + return group @@ -145,9 +174,11 @@ class CrashHandler: group.setTitle("User description") layout = QVBoxLayout() - text_area = QTextEdit() + # When sending the report, the user comments will be collected + self.user_description_text_area = QTextEdit() + self.user_description_text_area.setFocus(True) - layout.addWidget(text_area) + layout.addWidget(self.user_description_text_area) group.setLayout(layout) return group @@ -161,20 +192,31 @@ class CrashHandler: return buttons - def _getOpenGLInfo(self): - info = "" - 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) + # Before sending data, the user comments are stored + self.data["user_info"] = self.user_description_text_area.toPlainText() + + # Convert data to bytes + binary_data = json.dumps(self.data).encode("utf-8") + + # Submit data + kwoptions = {"data": binary_data, "timeout": 5} + + if Platform.isOSX(): + kwoptions["context"] = ssl._create_unverified_context() + + Logger.log("i", "Sending crash report info to [%s]...", self.crash_url) + + try: + f = urllib.request.urlopen(self.crash_url, **kwoptions) + Logger.log("i", "Sent crash report info.") + f.close() + except urllib.error.HTTPError: + Logger.logException("e", "An HTTP error occurred while trying to send crash report") + except Exception: # We don't want any exception to cause problems + Logger.logException("e", "An exception occurred while trying to send crash report") + + sys.exit(1) def show(self): self.dialog.exec_() From 72ff384c48910dd96096186f948dd20cfb0152df Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 10 Oct 2017 14:35:44 +0200 Subject: [PATCH 3/6] Parsing traceback to get more information about the crash - CURA-4195 --- cura/CrashHandler.py | 66 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index eb1f594c60..f29efd1019 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -5,6 +5,7 @@ import webbrowser import faulthandler import tempfile import os +import os.path import time import json import ssl @@ -15,6 +16,8 @@ from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication, Qt from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox from UM.Logger import Logger +from UM.PluginError import InvalidMetaDataError +from UM.PluginRegistry import PluginRegistry from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog from UM.Platform import Platform @@ -102,18 +105,18 @@ class CrashHandler: try: from UM.Application import Application - version = Application.getInstance().getVersion() + self.cura_version = Application.getInstance().getVersion() except: - version = "Unknown" + self.cura_version = "Unknown" crash_info = "Version: {0}
Platform: {1}
Qt: {2}
PyQt: {3}
OpenGL: {4}" - crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, self._getOpenGLInfo()) + crash_info = crash_info.format(self.cura_version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, self._getOpenGLInfo()) label.setText(crash_info) layout.addWidget(label) group.setLayout(layout) - self.data["cura_version"] = version + self.data["cura_version"] = self.cura_version self.data["os"] = {"type": platform.system(), "version": platform.version()} self.data["qt_version"] = QT_VERSION_STR self.data["pyqt_version"] = PYQT_VERSION_STR @@ -122,9 +125,9 @@ class CrashHandler: def _getOpenGLInfo(self): info = "
  • OpenGL Version: {0}
  • OpenGL Vendor: {1}
  • OpenGL Renderer: {2}
" - info = info.format(OpenGL.getInstance().getGPUVersion(), OpenGL.getInstance().getGPUVendorName(), OpenGL.getInstance().getGPUType()) + info = info.format(OpenGL.getInstance().getOpenGLVersion(), OpenGL.getInstance().getGPUVendorName(), OpenGL.getInstance().getGPUType()) - self.data["opengl"] = {"version": OpenGL.getInstance().getGPUVersion(), "vendor": OpenGL.getInstance().getGPUVendorName(), "type": OpenGL.getInstance().getGPUType()} + self.data["opengl"] = {"version": OpenGL.getInstance().getOpenGLVersion(), "vendor": OpenGL.getInstance().getGPUVendorName(), "type": OpenGL.getInstance().getGPUType()} return info @@ -134,14 +137,61 @@ class CrashHandler: layout = QVBoxLayout() text_area = QTextEdit() - trace = "".join(traceback.format_exception(self.exception_type, self.value, self.traceback)) + trace_dict = traceback.format_exception(self.exception_type, self.value, self.traceback) + trace = "".join(trace_dict) text_area.setText(trace) text_area.setReadOnly(True) layout.addWidget(text_area) group.setLayout(layout) - self.data["traceback"] = trace + # Parsing all the information to fill the dictionary + summary = trace_dict[len(trace_dict)-1].rstrip("\n") + module = trace_dict[len(trace_dict)-2].rstrip("\n").split("\n") + module_split = module[0].split(", ") + filepath = module_split[0].split("\"")[1] + directory, filename = os.path.split(filepath) + line = int(module_split[1].lstrip("line ")) + function = module_split[2].lstrip("in ") + code = module[1].lstrip(" ") + + # Using this workaround for a cross-platform path splitting + split_path = [] + folder_name = "" + # Split until reach folder "cura" + while folder_name != "cura": + directory, folder_name = os.path.split(directory) + if not folder_name: + break + split_path.append(folder_name) + + # Look for plugins. If it's not a plugin, the current cura version is set + isPlugin = False + module_version = self.cura_version + if split_path.__contains__("plugins"): + isPlugin = True + # Look backwards until plugin.json is found + directory, name = os.path.split(filepath) + while not os.listdir(directory).__contains__("plugin.json"): + directory, name = os.path.split(directory) + + json_metadata_file = os.path.join(directory, "plugin.json") + try: + with open(json_metadata_file, "r") as f: + try: + metadata = json.loads(f.read()) + module_version = metadata["version"] + except json.decoder.JSONDecodeError: + # Not through new exceptions + Logger.logException("e", "Failed to parse plugin.json for plugin %s", name) + except: + # Not through new exceptions + pass + + exception_dict = dict() + exception_dict["traceback"] = {"summary": summary, "full_trace": trace} + exception_dict["location"] = {"path": filepath, "file": filename, "function": function, "code": code, "line": line, "version": module_version, "is_plugin": isPlugin} + self.data["exception"] = exception_dict return group From de260683cfa11cc3c39a78c9fa882b853a9a3448 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 13 Oct 2017 10:43:58 +0200 Subject: [PATCH 4/6] CURA-4195 - Add module name to the crash report --- cura/CrashHandler.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index f29efd1019..bd5349f719 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -32,7 +32,6 @@ else: from cura.CuraVersion import CuraDebugMode except ImportError: 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. # These are primarily some exception types that we simply cannot really recover from @@ -168,6 +167,7 @@ class CrashHandler: # Look for plugins. If it's not a plugin, the current cura version is set isPlugin = False module_version = self.cura_version + module_name = "Cura" if split_path.__contains__("plugins"): isPlugin = True # Look backwards until plugin.json is found @@ -181,16 +181,18 @@ class CrashHandler: try: metadata = json.loads(f.read()) module_version = metadata["version"] + module_name = metadata["name"] except json.decoder.JSONDecodeError: - # Not through new exceptions + # Not throw new exceptions Logger.logException("e", "Failed to parse plugin.json for plugin %s", name) except: - # Not through new exceptions + # Not throw new exceptions pass exception_dict = dict() exception_dict["traceback"] = {"summary": summary, "full_trace": trace} - exception_dict["location"] = {"path": filepath, "file": filename, "function": function, "code": code, "line": line, "version": module_version, "is_plugin": isPlugin} + exception_dict["location"] = {"path": filepath, "file": filename, "function": function, "code": code, "line": line, + "module_name": module_name, "version": module_version, "is_plugin": isPlugin} self.data["exception"] = exception_dict return group From 74c37dfc65baaf10c39c6879959be81c46872332 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 13 Oct 2017 16:32:01 +0200 Subject: [PATCH 5/6] CURA-4195 Add strings for I18N --- cura/CrashHandler.py | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index bd5349f719..249d509674 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -1,7 +1,9 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import sys import platform import traceback -import webbrowser import faulthandler import tempfile import os @@ -12,12 +14,10 @@ import ssl import urllib.request import urllib.error -from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication, Qt -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox +from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QPushButton from UM.Logger import Logger -from UM.PluginError import InvalidMetaDataError -from UM.PluginRegistry import PluginRegistry from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog from UM.Platform import Platform @@ -90,7 +90,7 @@ class CrashHandler: def _messageWidget(self): label = QLabel() - label.setText(catalog.i18nc("@label", """

A fatal exception has occurred that we could not recover from!

+ label.setText(catalog.i18nc("@label crash message", """

A fatal exception has occurred that we could not recover from!

Please use the button below to post a bug report automatically to our servers

""")) @@ -98,7 +98,7 @@ class CrashHandler: def _informationWidget(self): group = QGroupBox() - group.setTitle("System information") + group.setTitle(catalog.i18nc("@title:groupbox", "System information")) layout = QVBoxLayout() label = QLabel() @@ -106,10 +106,13 @@ class CrashHandler: from UM.Application import Application self.cura_version = Application.getInstance().getVersion() except: - self.cura_version = "Unknown" + self.cura_version = catalog.i18nc("@label unknown version of Cura", "Unknown") - crash_info = "Version: {0}
Platform: {1}
Qt: {2}
PyQt: {3}
OpenGL: {4}" - crash_info = crash_info.format(self.cura_version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, self._getOpenGLInfo()) + crash_info = catalog.i18nc("@label Cura version", "Cura version: {version}
").format(version = self.cura_version) + crash_info += catalog.i18nc("@label Platform", "Platform: {platform}
").format(platform = platform.platform()) + crash_info += catalog.i18nc("@label Qt version", "Qt version: {qt}
").format(qt = QT_VERSION_STR) + crash_info += catalog.i18nc("@label PyQt version", "PyQt version: {pyqt}
").format(pyqt = PYQT_VERSION_STR) + crash_info += catalog.i18nc("@label OpenGL", "OpenGL: {opengl}
").format(opengl = self._getOpenGLInfo()) label.setText(crash_info) layout.addWidget(label) @@ -123,8 +126,11 @@ class CrashHandler: return group def _getOpenGLInfo(self): - info = "
  • OpenGL Version: {0}
  • OpenGL Vendor: {1}
  • OpenGL Renderer: {2}
" - info = info.format(OpenGL.getInstance().getOpenGLVersion(), OpenGL.getInstance().getGPUVendorName(), OpenGL.getInstance().getGPUType()) + info = "
    " + info += catalog.i18nc("@label OpenGL version", "
  • OpenGL Version: {version}
  • ").format(version = OpenGL.getInstance().getOpenGLVersion()) + info += catalog.i18nc("@label OpenGL vendor", "
  • OpenGL Vendor: {vendor}
  • ").format(vendor = OpenGL.getInstance().getGPUVendorName()) + info += catalog.i18nc("@label OpenGL renderer", "
  • OpenGL Renderer: {renderer}
  • ").format(renderer = OpenGL.getInstance().getGPUType()) + info += "
" self.data["opengl"] = {"version": OpenGL.getInstance().getOpenGLVersion(), "vendor": OpenGL.getInstance().getGPUVendorName(), "type": OpenGL.getInstance().getGPUType()} @@ -132,7 +138,7 @@ class CrashHandler: def _exceptionInfoWidget(self): group = QGroupBox() - group.setTitle("Exception traceback") + group.setTitle(catalog.i18nc("@title:groupbox", "Exception traceback")) layout = QVBoxLayout() text_area = QTextEdit() @@ -199,7 +205,7 @@ class CrashHandler: def _logInfoWidget(self): group = QGroupBox() - group.setTitle("Logs") + group.setTitle(catalog.i18nc("@title:groupbox", "Logs")) layout = QVBoxLayout() text_area = QTextEdit() @@ -223,7 +229,7 @@ class CrashHandler: def _userDescriptionWidget(self): group = QGroupBox() - group.setTitle("User description") + group.setTitle(catalog.i18nc("@title:groupbox", "User description")) layout = QVBoxLayout() # When sending the report, the user comments will be collected @@ -268,8 +274,8 @@ class CrashHandler: except Exception: # We don't want any exception to cause problems Logger.logException("e", "An exception occurred while trying to send crash report") - sys.exit(1) + os._exit(1) def show(self): self.dialog.exec_() - sys.exit(1) \ No newline at end of file + os._exit(1) \ No newline at end of file From b32f3f9f77453f774d3a2578941e673d040a296c Mon Sep 17 00:00:00 2001 From: "A.Sasin" Date: Mon, 16 Oct 2017 13:42:29 +0200 Subject: [PATCH 6/6] Adjusted Crash report message title CURA-4195 --- cura/CrashHandler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index 249d509674..04f04a1c37 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -90,8 +90,8 @@ class CrashHandler: def _messageWidget(self): label = QLabel() - label.setText(catalog.i18nc("@label crash message", """

A fatal exception has occurred that we could not recover from!

-

Please use the button below to post a bug report automatically to our servers

+ label.setText(catalog.i18nc("@label crash message", """

A fatal exception has occurred. Please send us this Crash Report to fix the problem

+

Please use the "Send report" button to post a bug report automatically to our servers

""")) return label @@ -244,7 +244,7 @@ class CrashHandler: def _buttonsWidget(self): buttons = QDialogButtonBox() buttons.addButton(QDialogButtonBox.Close) - buttons.addButton(catalog.i18nc("@action:button", "Send to developers"), QDialogButtonBox.AcceptRole) + buttons.addButton(catalog.i18nc("@action:button", "Send report"), QDialogButtonBox.AcceptRole) buttons.rejected.connect(self.dialog.close) buttons.accepted.connect(self._sendCrashReport)