CrashHandler.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import sys
  2. import platform
  3. import traceback
  4. import webbrowser
  5. import urllib
  6. from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, Qt, QCoreApplication
  7. from PyQt5.QtGui import QPixmap
  8. from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QVBoxLayout, QLabel, QTextEdit
  9. from UM.Logger import Logger
  10. from UM.i18n import i18nCatalog
  11. catalog = i18nCatalog("cura")
  12. MYPY = False
  13. if MYPY:
  14. CuraDebugMode = False
  15. else:
  16. try:
  17. from cura.CuraVersion import CuraDebugMode
  18. except ImportError:
  19. CuraDebugMode = False # [CodeStyle: Reflecting imported value]
  20. # List of exceptions that should be considered "fatal" and abort the program.
  21. # These are primarily some exception types that we simply cannot really recover from
  22. # (MemoryError and SystemError) and exceptions that indicate grave errors in the
  23. # code that cause the Python interpreter to fail (SyntaxError, ImportError).
  24. fatal_exception_types = [
  25. MemoryError,
  26. SyntaxError,
  27. ImportError,
  28. SystemError,
  29. ]
  30. def show(exception_type, value, tb):
  31. Logger.log("c", "An uncaught exception has occurred!")
  32. for line in traceback.format_exception(exception_type, value, tb):
  33. for part in line.rstrip("\n").split("\n"):
  34. Logger.log("c", part)
  35. if not CuraDebugMode and exception_type not in fatal_exception_types:
  36. return
  37. application = QCoreApplication.instance()
  38. if not application:
  39. sys.exit(1)
  40. dialog = QDialog()
  41. dialog.setMinimumWidth(640)
  42. dialog.setMinimumHeight(640)
  43. dialog.setWindowTitle(catalog.i18nc("@title:window", "Oops!"))
  44. layout = QVBoxLayout(dialog)
  45. label = QLabel(dialog)
  46. pixmap = QPixmap()
  47. try:
  48. data = urllib.request.urlopen("http://www.randomkittengenerator.com/cats/rotator.php").read()
  49. pixmap.loadFromData(data)
  50. except:
  51. try:
  52. from UM.Resources import Resources
  53. path = Resources.getPath(Resources.Images, "kitten.jpg")
  54. pixmap.load(path)
  55. except:
  56. pass
  57. pixmap = pixmap.scaled(150, 150)
  58. label.setPixmap(pixmap)
  59. label.setAlignment(Qt.AlignCenter)
  60. layout.addWidget(label)
  61. label = QLabel(dialog)
  62. layout.addWidget(label)
  63. #label.setScaledContents(True)
  64. label.setText(catalog.i18nc("@label", """<p>A fatal exception has occurred that we could not recover from!</p>
  65. <p>We hope this picture of a kitten helps you recover from the shock.</p>
  66. <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>
  67. """))
  68. textarea = QTextEdit(dialog)
  69. layout.addWidget(textarea)
  70. try:
  71. from UM.Application import Application
  72. version = Application.getInstance().getVersion()
  73. except:
  74. version = "Unknown"
  75. trace = "".join(traceback.format_exception(exception_type, value, tb))
  76. crash_info = "Version: {0}\nPlatform: {1}\nQt: {2}\nPyQt: {3}\n\nException:\n{4}"
  77. crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace)
  78. textarea.setText(crash_info)
  79. buttons = QDialogButtonBox(QDialogButtonBox.Close, dialog)
  80. layout.addWidget(buttons)
  81. buttons.addButton(catalog.i18nc("@action:button", "Open Web Page"), QDialogButtonBox.HelpRole)
  82. buttons.rejected.connect(dialog.close)
  83. buttons.helpRequested.connect(lambda: webbrowser.open("http://github.com/Ultimaker/Cura/issues"))
  84. dialog.exec_()
  85. sys.exit(1)