Add broken debugging console.

This commit is contained in:
Florian Bruhin 2014-08-07 14:43:45 +02:00
parent 0233d2b561
commit 07fda5818c
3 changed files with 142 additions and 1 deletions

View File

@ -69,3 +69,12 @@ Completion view (not QTreeView)
Perhaps using a QHBoxLayout of QTableViews and creating/destroying them based
on the completion would be a better idea?
Debug console
=============
https://github.com/karelklic/flashfit/blob/1a2393cb2fb3e44d2e34bf568386d9d4a9b22148/gui_console.py
http://code.google.com/p/pyqtlive/source/browse/pycute4.py
http://stackoverflow.com/questions/12431555/enabling-code-completion-in-an-embedded-python-interpreter
http://docs.projexsoftware.com/wp-content/docs/projexui/0.5.1/api/projexui/widgets/xconsoleedit-source.html

View File

@ -51,6 +51,7 @@ import qutebrowser.utils.utilcmds as utilcmds
from qutebrowser.config.config import ConfigManager
from qutebrowser.keyinput.modeman import ModeManager
from qutebrowser.widgets.mainwindow import MainWindow
from qutebrowser.widgets.console import ConsoleWidget
from qutebrowser.widgets.crash import (ExceptionCrashDialog, FatalCrashDialog,
ReportDialog)
from qutebrowser.keyinput.modeparsers import (NormalKeyParser, HintKeyParser,
@ -73,6 +74,7 @@ class Application(QApplication):
Attributes:
mainwindow: The MainWindow QWidget.
debugconsole: The ConsoleWidget for debugging.
commandrunner: The main CommandRunner instance.
searchrunner: The main SearchRunner instance.
config: The main ConfigManager
@ -154,8 +156,9 @@ class Application(QApplication):
self.downloadmanager = DownloadManager(self)
log.init.debug("Initializing main window...")
self.mainwindow = MainWindow()
self.modeman.mainwindow = self.mainwindow
log.init.debug("Initializing debug console...")
self.debugconsole = ConsoleWidget()
log.init.debug("Initializing eventfilter...")
self.installEventFilter(self.modeman)
self.setQuitOnLastWindowClosed(False)
@ -655,6 +658,11 @@ class Application(QApplication):
self._crashdlg = ReportDialog(pages, history, widgets, objects)
self._crashdlg.show()
@cmdutils.register(debug=True, name='debug-console')
def show_debugconsole(self):
"""Show the debugging console."""
self.debugconsole.show()
def interrupt(self, signum, _frame):
"""Handler for signals to gracefully shutdown (SIGINT/SIGTERM).

View File

@ -0,0 +1,124 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Debugging console."""
from code import InteractiveInterpreter
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject
from PyQt5.QtWidgets import QLineEdit, QTextEdit, QWidget, QVBoxLayout
from qutebrowser.models.cmdhistory import (History, HistoryEmptyError,
HistoryEndReachedError)
class ConsoleInteractiveInterpreter(InteractiveInterpreter, QObject):
"""Subclass of InteractiveInterpreter to use a signal instead of stderr.
FIXME: This approach doesn't actually work.
"""
write_output = pyqtSignal(str)
def __init__(self, parent=None):
QObject.__init__(self, parent)
InteractiveInterpreter.__init__(self)
def write(self, data):
self.write_output.emit(data)
class ConsoleLineEdit(QLineEdit):
"""A QLineEdit which executes entered code and provides a history."""
write = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._more = False
self._buffer = []
self._interpreter = ConsoleInteractiveInterpreter()
self._interpreter.write_output.connect(self.write)
self.history = History()
self.returnPressed.connect(self.execute)
@pyqtSlot(str)
def execute(self):
"""Execute the line of code which was entered."""
text = self.text()
self.history.append(text)
self.push(text)
self.setText('')
def push(self, line):
"""Push a line to the interpreter."""
self._buffer.append(line)
source = '\n'.join(self._buffer)
self._more = self._interpreter.runsource(source, '<console>')
if not self._more:
self._buffer = []
def history_prev(self):
"""Go back in the history."""
try:
if not self.history.browsing:
item = self.history.start(self.text().strip())
else:
item = self.history.previtem()
except (HistoryEmptyError, HistoryEndReachedError):
return
self.setText(item)
def history_next(self):
"""Go forward in the history."""
if not self.history.browsing:
return
try:
item = self.history.nextitem()
except HistoryEndReachedError:
return
self.setText(item)
def keyPressEvent(self, e):
"""Override keyPressEvent to handle up/down keypresses."""
if e.key() == Qt.Key_Up:
self.history_prev()
e.accept()
elif e.key() == Qt.Key_Down:
self.history_next()
e.accept()
else:
super().keyPressEvent(e)
class ConsoleWidget(QWidget):
"""A widget with an interactive Python console."""
def __init__(self, parent=None):
super().__init__(parent)
self.lineedit = ConsoleLineEdit()
self.output = QTextEdit(acceptRichText=True, readOnly=True)
self.lineedit.write.connect(self.output.append)
self.vbox = QVBoxLayout()
self.vbox.setSpacing(0)
self.vbox.addWidget(self.output)
self.vbox.addWidget(self.lineedit)
self.setLayout(self.vbox)