1"""
2Exception hook
3If some unexpected error occures it can be shown in a nice looking dialog.
4Especially useful is the traceback view.
5
6Things to extend: Clicking on the filename should open an editor.
7Things to consider: Mail exceptions, copy to clipboard or send to bug tracker.
8"""
9import sys
10import cgitb
11import atexit
12
13from PyQt4.QtCore import pyqtSignature, Qt
14from PyQt4.QtGui import QDialog, QApplication
15
16from excepthook_ui import Ui_ExceptHookDialog
17
18
19
20def on_error(exc_type, exc_obj, exc_tb):
21    """
22    This is the callback function for sys.excepthook
23    """
24    dlg = ExceptHookDialog(exc_type, exc_obj, exc_tb)
25    dlg.show()
26    dlg.exec_()
27
28
29
30def show_current_error(title=None):
31    """
32    Call this function to show the current error.
33    It can be used inside an except-block.
34    """
35    dlg = ExceptHookDialog(sys.exc_type, sys.exc_value, sys.exc_traceback, title)
36    dlg.show()
37    dlg.exec_()
38
39
40def install():
41    "activates the error handler"
42    sys.excepthook = on_error
43
44
45
46def uninstall():
47    "removes the error handler"
48    sys.excepthook = sys.__excepthook__
49
50atexit.register(uninstall)
51
52
53class ExceptHookDialog(QDialog):
54
55
56    def __init__(self, exc_type, exc_obj, exc_tb, title=None):
57        QDialog.__init__(self)
58        self.ui = Ui_ExceptHookDialog()
59        self.ui.setupUi(self)
60        if title:
61            self.setWindowTitle(self.windowTitle() + ": " + title)
62        self.ui.detailsButton.setCheckable(True)
63        self.setExtension(self.ui.tracebackBrowser)
64        self.setOrientation(Qt.Vertical)
65        msg = "%s: %s" % (exc_type.__name__, exc_obj)
66        self.ui.exceptionLabel.setText(msg)
67        html = cgitb.html((exc_type, exc_obj, exc_tb))
68        self.ui.tracebackBrowser.setText(html)
69        self.resize(self.sizeHint())
70
71
72    @pyqtSignature("")
73    def on_closeButton_clicked(self):
74        self.close()
75
76
77    @pyqtSignature("")
78    def on_detailsButton_clicked(self):
79        self.showExtension(self.ui.detailsButton.isChecked())
80
81
82
83if __name__ == "__main__":
84    # Some tests:
85    app = QApplication(sys.argv)
86    install()
87    print "Triggering error 1"
88    try:
89        fail = 1 / 0
90    except:
91        show_current_error("Using inside except")
92    print "Triggering error 2"
93    fail2 = 1 / 0
94    print "This will never be reached because excepthook"
95    print "complains about fail2"
96