mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 21:03:23 +08:00
144 lines
4.6 KiB
Python
144 lines
4.6 KiB
Python
![]() |
# Copyright (c) 2009-2010, Cloud Matrix Pty. Ltd.
|
||
|
# All rights reserved; available under the terms of the BSD License.
|
||
|
"""
|
||
|
PySideKick.Console: a simple embeddable python shell
|
||
|
=====================================================
|
||
|
|
||
|
|
||
|
This module provides the call QPythonConsole, a python shell that can be
|
||
|
embedded in your GUI.
|
||
|
|
||
|
"""
|
||
|
|
||
|
import sys
|
||
|
from code import InteractiveConsole as _InteractiveConsole
|
||
|
|
||
|
from PySideKick import QtCore, QtGui
|
||
|
|
||
|
try:
|
||
|
from cStringIO import StringIO
|
||
|
except ImportError:
|
||
|
from StringIO import StringIO
|
||
|
|
||
|
|
||
|
class _QPythonConsoleInterpreter(_InteractiveConsole):
|
||
|
"""InteractiveConsole subclass that sends all output to the GUI."""
|
||
|
|
||
|
def __init__(self,ui,locals=None):
|
||
|
_InteractiveConsole.__init__(self,locals)
|
||
|
self.ui = ui
|
||
|
|
||
|
def write(self,data):
|
||
|
if data:
|
||
|
if data[-1] == "\n":
|
||
|
data = data[:-1]
|
||
|
self.ui.output.appendPlainText(data)
|
||
|
|
||
|
def runsource(self,source,filename="<input>",symbol="single"):
|
||
|
old_stdout = sys.stdout
|
||
|
old_stderr = sys.stderr
|
||
|
sys.stdout = sys.stderr = collector = StringIO()
|
||
|
try:
|
||
|
more = _InteractiveConsole.runsource(self,source,filename,symbol)
|
||
|
finally:
|
||
|
if sys.stdout is collector:
|
||
|
sys.stdout = old_stdout
|
||
|
if sys.stderr is collector:
|
||
|
sys.stderr = old_stderr
|
||
|
self.write(collector.getvalue())
|
||
|
return more
|
||
|
|
||
|
|
||
|
class _QPythonConsoleUI(object):
|
||
|
"""UI layout container for QPythonConsole."""
|
||
|
def __init__(self,parent):
|
||
|
if parent.layout() is None:
|
||
|
parent.setLayout(QtGui.QHBoxLayout())
|
||
|
layout = QtGui.QVBoxLayout()
|
||
|
layout.setSpacing(0)
|
||
|
# Output console: a fixed-pitch-font text area.
|
||
|
self.output = QtGui.QPlainTextEdit(parent)
|
||
|
self.output.setReadOnly(True)
|
||
|
self.output.setUndoRedoEnabled(False)
|
||
|
self.output.setMaximumBlockCount(5000)
|
||
|
fmt = QtGui.QTextCharFormat()
|
||
|
fmt.setFontFixedPitch(True)
|
||
|
self.output.setCurrentCharFormat(fmt)
|
||
|
layout.addWidget(self.output)
|
||
|
parent.layout().addLayout(layout)
|
||
|
# Input console, a prompt displated next to a lineedit
|
||
|
layout2 = QtGui.QHBoxLayout()
|
||
|
self.prompt = QtGui.QLabel(parent)
|
||
|
self.prompt.setText(">>> ")
|
||
|
layout2.addWidget(self.prompt)
|
||
|
self.input = QtGui.QLineEdit(parent)
|
||
|
layout2.addWidget(self.input)
|
||
|
layout.addLayout(layout2)
|
||
|
|
||
|
|
||
|
class QPythonConsole(QtGui.QWidget):
|
||
|
"""A simple python console to embed in your GUI.
|
||
|
|
||
|
This widget provides a simple interactive python console that you can
|
||
|
embed in your GUI (e.g. for debugging purposes). Use it like so:
|
||
|
|
||
|
self.debug_window.layout().addWidget(QPythonConsole())
|
||
|
|
||
|
You can customize the variables that are available in the shell by
|
||
|
passing a dict as the "locals" argument.
|
||
|
"""
|
||
|
|
||
|
def __init__(self,parent=None,locals=None):
|
||
|
super(QPythonConsole,self).__init__(parent)
|
||
|
self.ui = _QPythonConsoleUI(self)
|
||
|
self.interpreter = _QPythonConsoleInterpreter(self.ui,locals)
|
||
|
self.ui.input.returnPressed.connect(self._on_enter_line)
|
||
|
self.ui.input.installEventFilter(self)
|
||
|
self.history = []
|
||
|
self.history_pos = 0
|
||
|
|
||
|
def _on_enter_line(self):
|
||
|
line = self.ui.input.text()
|
||
|
self.ui.input.setText("")
|
||
|
self.interpreter.write(self.ui.prompt.text() + line)
|
||
|
more = self.interpreter.push(line)
|
||
|
if line:
|
||
|
self.history.append(line)
|
||
|
self.history_pos = len(self.history)
|
||
|
while len(self.history) > 100:
|
||
|
self.history = self.history[1:]
|
||
|
self.history_pos -= 1
|
||
|
if more:
|
||
|
self.ui.prompt.setText("... ")
|
||
|
else:
|
||
|
self.ui.prompt.setText(">>> ")
|
||
|
|
||
|
def eventFilter(self,obj,event):
|
||
|
if event.type() == QtCore.QEvent.KeyPress:
|
||
|
if event.key() == QtCore.Qt.Key_Up:
|
||
|
self.go_history(-1)
|
||
|
elif event.key() == QtCore.Qt.Key_Down:
|
||
|
self.go_history(1)
|
||
|
return False
|
||
|
|
||
|
def go_history(self,offset):
|
||
|
if offset < 0:
|
||
|
self.history_pos = max(0,self.history_pos + offset)
|
||
|
elif offset > 0:
|
||
|
self.history_pos = min(len(self.history),self.history_pos + offset)
|
||
|
try:
|
||
|
line = self.history[self.history_pos]
|
||
|
except IndexError:
|
||
|
line = ""
|
||
|
self.ui.input.setText(line)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
import sys, os
|
||
|
app = QtGui.QApplication(sys.argv)
|
||
|
win = QtGui.QMainWindow()
|
||
|
win.setCentralWidget(QPythonConsole())
|
||
|
win.show()
|
||
|
app.exec_()
|
||
|
|