mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-14 02:45:55 +08:00
Make crash dialog available before Application starts
CURA-4895
This commit is contained in:
parent
8e86c49c81
commit
1d946085d3
@ -1,7 +1,6 @@
|
|||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import sys
|
|
||||||
import platform
|
import platform
|
||||||
import traceback
|
import traceback
|
||||||
import faulthandler
|
import faulthandler
|
||||||
@ -14,7 +13,7 @@ import ssl
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.error
|
import urllib.error
|
||||||
|
|
||||||
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication
|
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
|
||||||
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox
|
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
@ -49,10 +48,11 @@ fatal_exception_types = [
|
|||||||
class CrashHandler:
|
class CrashHandler:
|
||||||
crash_url = "https://stats.ultimaker.com/api/cura"
|
crash_url = "https://stats.ultimaker.com/api/cura"
|
||||||
|
|
||||||
def __init__(self, exception_type, value, tb):
|
def __init__(self, exception_type, value, tb, has_started = True):
|
||||||
self.exception_type = exception_type
|
self.exception_type = exception_type
|
||||||
self.value = value
|
self.value = value
|
||||||
self.traceback = tb
|
self.traceback = tb
|
||||||
|
self.has_started = has_started
|
||||||
self.dialog = None # Don't create a QDialog before there is a QApplication
|
self.dialog = None # Don't create a QDialog before there is a QApplication
|
||||||
|
|
||||||
# While we create the GUI, the information will be stored for sending afterwards
|
# While we create the GUI, the information will be stored for sending afterwards
|
||||||
@ -67,10 +67,6 @@ class CrashHandler:
|
|||||||
if not CuraDebugMode and exception_type not in fatal_exception_types:
|
if not CuraDebugMode and exception_type not in fatal_exception_types:
|
||||||
return
|
return
|
||||||
|
|
||||||
application = QCoreApplication.instance()
|
|
||||||
if not application:
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
self.dialog = QDialog()
|
self.dialog = QDialog()
|
||||||
self._createDialog()
|
self._createDialog()
|
||||||
|
|
||||||
@ -79,6 +75,7 @@ class CrashHandler:
|
|||||||
self.dialog.setMinimumWidth(640)
|
self.dialog.setMinimumWidth(640)
|
||||||
self.dialog.setMinimumHeight(640)
|
self.dialog.setMinimumHeight(640)
|
||||||
self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
|
self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
|
||||||
|
self.dialog.finished.connect(self._close)
|
||||||
|
|
||||||
layout = QVBoxLayout(self.dialog)
|
layout = QVBoxLayout(self.dialog)
|
||||||
|
|
||||||
@ -89,6 +86,9 @@ class CrashHandler:
|
|||||||
layout.addWidget(self._userDescriptionWidget())
|
layout.addWidget(self._userDescriptionWidget())
|
||||||
layout.addWidget(self._buttonsWidget())
|
layout.addWidget(self._buttonsWidget())
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
os._exit(1)
|
||||||
|
|
||||||
def _messageWidget(self):
|
def _messageWidget(self):
|
||||||
label = QLabel()
|
label = QLabel()
|
||||||
label.setText(catalog.i18nc("@label crash message", """<p><b>A fatal error has occurred. Please send us this Crash Report to fix the problem</p></b>
|
label.setText(catalog.i18nc("@label crash message", """<p><b>A fatal error has occurred. Please send us this Crash Report to fix the problem</p></b>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from PyQt5.QtNetwork import QLocalServer
|
from PyQt5.QtNetwork import QLocalServer
|
||||||
from PyQt5.QtNetwork import QLocalSocket
|
from PyQt5.QtNetwork import QLocalSocket
|
||||||
@ -113,6 +112,8 @@ class CuraApplication(QtApplication):
|
|||||||
# changes of the settings.
|
# changes of the settings.
|
||||||
SettingVersion = 4
|
SettingVersion = 4
|
||||||
|
|
||||||
|
Created = False
|
||||||
|
|
||||||
class ResourceTypes:
|
class ResourceTypes:
|
||||||
QmlFiles = Resources.UserType + 1
|
QmlFiles = Resources.UserType + 1
|
||||||
Firmware = Resources.UserType + 2
|
Firmware = Resources.UserType + 2
|
||||||
@ -256,7 +257,7 @@ class CuraApplication(QtApplication):
|
|||||||
self._center_after_select = False
|
self._center_after_select = False
|
||||||
self._camera_animation = None
|
self._camera_animation = None
|
||||||
self._cura_actions = None
|
self._cura_actions = None
|
||||||
self._started = False
|
self.started = False
|
||||||
|
|
||||||
self._message_box_callback = None
|
self._message_box_callback = None
|
||||||
self._message_box_callback_arguments = []
|
self._message_box_callback_arguments = []
|
||||||
@ -409,6 +410,8 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
self.getCuraSceneController().setActiveBuildPlate(0) # Initialize
|
self.getCuraSceneController().setActiveBuildPlate(0) # Initialize
|
||||||
|
|
||||||
|
CuraApplication.Created = True
|
||||||
|
|
||||||
def _onEngineCreated(self):
|
def _onEngineCreated(self):
|
||||||
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
|
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
|
||||||
|
|
||||||
@ -503,7 +506,7 @@ class CuraApplication(QtApplication):
|
|||||||
#
|
#
|
||||||
# Note that the AutoSave plugin also calls this method.
|
# Note that the AutoSave plugin also calls this method.
|
||||||
def saveSettings(self):
|
def saveSettings(self):
|
||||||
if not self._started: # Do not do saving during application start
|
if not self.started: # Do not do saving during application start
|
||||||
return
|
return
|
||||||
|
|
||||||
ContainerRegistry.getInstance().saveDirtyContainers()
|
ContainerRegistry.getInstance().saveDirtyContainers()
|
||||||
@ -732,7 +735,7 @@ class CuraApplication(QtApplication):
|
|||||||
for file_name in self._open_file_queue: #Open all the files that were queued up while plug-ins were loading.
|
for file_name in self._open_file_queue: #Open all the files that were queued up while plug-ins were loading.
|
||||||
self._openFile(file_name)
|
self._openFile(file_name)
|
||||||
|
|
||||||
self._started = True
|
self.started = True
|
||||||
|
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
|
||||||
|
36
cura_app.py
36
cura_app.py
@ -71,8 +71,40 @@ if "PYTHONPATH" in os.environ.keys(): # If PYTHONPATH is u
|
|||||||
|
|
||||||
def exceptHook(hook_type, value, traceback):
|
def exceptHook(hook_type, value, traceback):
|
||||||
from cura.CrashHandler import CrashHandler
|
from cura.CrashHandler import CrashHandler
|
||||||
_crash_handler = CrashHandler(hook_type, value, traceback)
|
from cura.CuraApplication import CuraApplication
|
||||||
_crash_handler.show()
|
has_started = False
|
||||||
|
if CuraApplication.Created:
|
||||||
|
has_started = CuraApplication.getInstance().started
|
||||||
|
|
||||||
|
#
|
||||||
|
# When the exception hook is triggered, the QApplication may not have been initialized yet. In this case, we don't
|
||||||
|
# have an QApplication to handle the event loop, which is required by the Crash Dialog.
|
||||||
|
# The flag "CuraApplication.Created" is set to True when CuraApplication finishes its constructor call.
|
||||||
|
#
|
||||||
|
# Before the "started" flag is set to True, the Qt event loop has not started yet. The event loop is a blocking
|
||||||
|
# call to the QApplication.exec_(). In this case, we need to:
|
||||||
|
# 1. Remove all scheduled events so no more unnecessary events will be processed, such as loading the main dialog,
|
||||||
|
# loading the machine, etc.
|
||||||
|
# 2. Start the Qt event loop with exec_() and show the Crash Dialog.
|
||||||
|
#
|
||||||
|
# If the application has finished its initialization and was running fine, and then something causes a crash,
|
||||||
|
# we run the old routine to show the Crash Dialog.
|
||||||
|
#
|
||||||
|
from PyQt5.Qt import QApplication
|
||||||
|
if CuraApplication.Created:
|
||||||
|
_crash_handler = CrashHandler(hook_type, value, traceback, has_started)
|
||||||
|
if not has_started:
|
||||||
|
CuraApplication.getInstance().removePostedEvents(None)
|
||||||
|
_crash_handler.show()
|
||||||
|
sys.exit(CuraApplication.getInstance().exec_())
|
||||||
|
else:
|
||||||
|
_crash_handler.show()
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
application = QApplication(sys.argv)
|
||||||
|
_crash_handler = CrashHandler(hook_type, value, traceback, has_started)
|
||||||
|
_crash_handler.dialog.show()
|
||||||
|
sys.exit(application.exec_())
|
||||||
|
|
||||||
if not known_args["debug"]:
|
if not known_args["debug"]:
|
||||||
sys.excepthook = exceptHook
|
sys.excepthook = exceptHook
|
||||||
|
Loading…
x
Reference in New Issue
Block a user