From 2b5a1cc3223062fd3b5563a92aa8708cab7e14d0 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 17 Jun 2014 23:04:58 +0200 Subject: [PATCH] Add wiget/object list to crash dialog --- qutebrowser/app.py | 38 ++++++++++++++++++++++++++++++++++-- qutebrowser/utils/debug.py | 18 +++++------------ qutebrowser/widgets/crash.py | 8 +++++++- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/qutebrowser/app.py b/qutebrowser/app.py index c26b24d62..0856ff982 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -28,7 +28,7 @@ from base64 import b64encode from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths, - qInstallMessageHandler) + qInstallMessageHandler, QObject) import qutebrowser import qutebrowser.commands.utils as cmdutils @@ -390,6 +390,29 @@ class Application(QApplication): # downloads tabs.start_download.connect(self.downloadmanager.fetch) + def get_all_widgets(self): + """Get a string list of all widgets.""" + lines = [] + widgets = self.allWidgets() + widgets.sort(key=lambda e: repr(e)) + lines.append("{} widgets".format(len(widgets))) + for w in widgets: + lines.append(repr(w)) + return '\n'.join(lines) + + def get_all_objects(self, obj=None, depth=0, lines=None): + """Get all children of an object recursively as a string.""" + if lines is None: + lines = [] + if obj is None: + obj = self + for kid in obj.findChildren(QObject): + lines.append(' ' * depth + repr(kid)) + self.get_all_objects(kid, depth + 1, lines) + if depth == 0: + lines.insert(0, '{} objects:'.format(len(lines))) + return '\n'.join(lines) + def _recover_pages(self): """Try to recover all open pages. @@ -467,6 +490,16 @@ class Application(QApplication): except Exception: history = [] + try: + widgets = self.get_all_widgets() + except Exception: + widgets = "" + + try: + objects = self.get_all_objects() + except Exception: + objects = "" + # Try to shutdown gracefully try: self.shutdown(do_quit=False) @@ -477,7 +510,8 @@ class Application(QApplication): except TypeError: log.destroy.warning("Preventing shutdown failed.") QApplication.closeAllWindows() - self._crashdlg = ExceptionCrashDialog(pages, history, exc) + self._crashdlg = ExceptionCrashDialog(pages, history, exc, widgets, + objects) ret = self._crashdlg.exec_() if ret == QDialog.Accepted: # restore self.restart(shutdown=False, pages=pages) diff --git a/qutebrowser/utils/debug.py b/qutebrowser/utils/debug.py index 3ce64ba9d..060bb0e11 100644 --- a/qutebrowser/utils/debug.py +++ b/qutebrowser/utils/debug.py @@ -21,8 +21,7 @@ import sys import types from functools import wraps -from PyQt5.QtCore import (pyqtRemoveInputHook, QEvent, QCoreApplication, - QObject) +from PyQt5.QtCore import pyqtRemoveInputHook, QEvent, QCoreApplication from qutebrowser.utils.log import misc as logger @@ -76,21 +75,14 @@ def debug_crash(typ='exception'): @cmdutils.register(debug=True) def debug_all_widgets(): """Print a list of all widgets to debug log.""" - widgets = QCoreApplication.instance().allWidgets() - logger.debug("{} widgets".format(len(widgets))) - widgets.sort(key=lambda e: repr(e)) - for w in widgets: - logger.debug(repr(w)) - + s = QCoreApplication.instance().get_all_widgets() + logger.debug(s) @cmdutils.register(debug=True) def debug_all_objects(obj=None, depth=0): """Dump all children of an object recursively.""" - if obj is None: - obj = QCoreApplication.instance() - for kid in obj.findChildren(QObject): - logger.debug(' ' * depth + repr(kid)) - debug_all_objects(kid, depth + 1) + s = QCoreApplication.instance().get_all_objects() + logger.debug(s) def log_events(klass): diff --git a/qutebrowser/widgets/crash.py b/qutebrowser/widgets/crash.py index 411bc3f4e..953334378 100644 --- a/qutebrowser/widgets/crash.py +++ b/qutebrowser/widgets/crash.py @@ -148,15 +148,19 @@ class ExceptionCrashDialog(_CrashDialog): _pages: A list of the open pages (URLs as strings) _cmdhist: A list with the command history (as strings) _exc: An exception tuple (type, value, traceback) + _widgets: A list of active widgets as string. + _objects: A list of all QObjects as string. """ - def __init__(self, pages, cmdhist, exc, parent=None): + def __init__(self, pages, cmdhist, exc, widgets, objects, parent=None): self._pages = pages self._cmdhist = cmdhist self._exc = exc self._btn_quit = None self._btn_restore = None self._btn_pastebin = None + self._widgets = widgets + self._objects = objects super().__init__(parent) self.setModal(True) @@ -195,6 +199,8 @@ class ExceptionCrashDialog(_CrashDialog): ("Commandline args", ' '.join(sys.argv[1:])), ("Open Pages", '\n'.join(self._pages)), ("Command history", '\n'.join(self._cmdhist)), + ("Widgets", self._widgets), + ("Objects", self._objects), ] try: self._crash_info.append(("Debug log",