Add wiget/object list to crash dialog

This commit is contained in:
Florian Bruhin 2014-06-17 23:04:58 +02:00
parent 87ddfc418e
commit 2b5a1cc322
3 changed files with 48 additions and 16 deletions

View File

@ -28,7 +28,7 @@ from base64 import b64encode
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths, from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths,
qInstallMessageHandler) qInstallMessageHandler, QObject)
import qutebrowser import qutebrowser
import qutebrowser.commands.utils as cmdutils import qutebrowser.commands.utils as cmdutils
@ -390,6 +390,29 @@ class Application(QApplication):
# downloads # downloads
tabs.start_download.connect(self.downloadmanager.fetch) 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): def _recover_pages(self):
"""Try to recover all open pages. """Try to recover all open pages.
@ -467,6 +490,16 @@ class Application(QApplication):
except Exception: except Exception:
history = [] history = []
try:
widgets = self.get_all_widgets()
except Exception:
widgets = ""
try:
objects = self.get_all_objects()
except Exception:
objects = ""
# Try to shutdown gracefully # Try to shutdown gracefully
try: try:
self.shutdown(do_quit=False) self.shutdown(do_quit=False)
@ -477,7 +510,8 @@ class Application(QApplication):
except TypeError: except TypeError:
log.destroy.warning("Preventing shutdown failed.") log.destroy.warning("Preventing shutdown failed.")
QApplication.closeAllWindows() QApplication.closeAllWindows()
self._crashdlg = ExceptionCrashDialog(pages, history, exc) self._crashdlg = ExceptionCrashDialog(pages, history, exc, widgets,
objects)
ret = self._crashdlg.exec_() ret = self._crashdlg.exec_()
if ret == QDialog.Accepted: # restore if ret == QDialog.Accepted: # restore
self.restart(shutdown=False, pages=pages) self.restart(shutdown=False, pages=pages)

View File

@ -21,8 +21,7 @@ import sys
import types import types
from functools import wraps from functools import wraps
from PyQt5.QtCore import (pyqtRemoveInputHook, QEvent, QCoreApplication, from PyQt5.QtCore import pyqtRemoveInputHook, QEvent, QCoreApplication
QObject)
from qutebrowser.utils.log import misc as logger from qutebrowser.utils.log import misc as logger
@ -76,21 +75,14 @@ def debug_crash(typ='exception'):
@cmdutils.register(debug=True) @cmdutils.register(debug=True)
def debug_all_widgets(): def debug_all_widgets():
"""Print a list of all widgets to debug log.""" """Print a list of all widgets to debug log."""
widgets = QCoreApplication.instance().allWidgets() s = QCoreApplication.instance().get_all_widgets()
logger.debug("{} widgets".format(len(widgets))) logger.debug(s)
widgets.sort(key=lambda e: repr(e))
for w in widgets:
logger.debug(repr(w))
@cmdutils.register(debug=True) @cmdutils.register(debug=True)
def debug_all_objects(obj=None, depth=0): def debug_all_objects(obj=None, depth=0):
"""Dump all children of an object recursively.""" """Dump all children of an object recursively."""
if obj is None: s = QCoreApplication.instance().get_all_objects()
obj = QCoreApplication.instance() logger.debug(s)
for kid in obj.findChildren(QObject):
logger.debug(' ' * depth + repr(kid))
debug_all_objects(kid, depth + 1)
def log_events(klass): def log_events(klass):

View File

@ -148,15 +148,19 @@ class ExceptionCrashDialog(_CrashDialog):
_pages: A list of the open pages (URLs as strings) _pages: A list of the open pages (URLs as strings)
_cmdhist: A list with the command history (as strings) _cmdhist: A list with the command history (as strings)
_exc: An exception tuple (type, value, traceback) _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._pages = pages
self._cmdhist = cmdhist self._cmdhist = cmdhist
self._exc = exc self._exc = exc
self._btn_quit = None self._btn_quit = None
self._btn_restore = None self._btn_restore = None
self._btn_pastebin = None self._btn_pastebin = None
self._widgets = widgets
self._objects = objects
super().__init__(parent) super().__init__(parent)
self.setModal(True) self.setModal(True)
@ -195,6 +199,8 @@ class ExceptionCrashDialog(_CrashDialog):
("Commandline args", ' '.join(sys.argv[1:])), ("Commandline args", ' '.join(sys.argv[1:])),
("Open Pages", '\n'.join(self._pages)), ("Open Pages", '\n'.join(self._pages)),
("Command history", '\n'.join(self._cmdhist)), ("Command history", '\n'.join(self._cmdhist)),
("Widgets", self._widgets),
("Objects", self._objects),
] ]
try: try:
self._crash_info.append(("Debug log", self._crash_info.append(("Debug log",