mirror of
https://github.com/vivisect/vivisect
synced 2026-06-08 18:04:23 +00:00
ef475af564
* initial migration to PyQt6 * QContextMenuEvents still use globalPos() instead of globalPosition() * Apply suggestion from @atlas0fd00m * migration notes added to vivisect/notes/pyqt6.md * De-racify per Rakuy0 * handle special keys robustly * minor bugfixes: * Reverse Sorting in Tree Views * Scroll-zoom in FuncgraphView * Scrolling past end/beginning in MemoryView enhancement: * Auto-sort in Tree Views during load-time (now works, never did in PyQt5) * need the necessary libs to run unittests on pyqt6 modules * Second lib --------- Co-authored-by: James Gross <45212823+rakuy0@users.noreply.github.com>
88 lines
2.5 KiB
Python
88 lines
2.5 KiB
Python
'''
|
|
Home of some helpers for python interactive stuff.
|
|
'''
|
|
import types
|
|
import traceback
|
|
|
|
from threading import Thread
|
|
from PyQt6.QtWidgets import *
|
|
|
|
from vqt.main import idlethread
|
|
from vqt.basics import *
|
|
from vqt.common import scripterr
|
|
|
|
|
|
class ScriptThread(Thread):
|
|
|
|
def __init__(self, cobj, locals):
|
|
Thread.__init__(self, daemon=True)
|
|
self.cobj = cobj
|
|
self.locals = locals
|
|
|
|
def run(self):
|
|
try:
|
|
exec(self.cobj, self.locals)
|
|
except Exception as e:
|
|
scripterr(str(e), traceback.format_exc())
|
|
|
|
|
|
class VQPythonView(QWidget):
|
|
|
|
def __init__(self, locals=None, parent=None):
|
|
if locals is None:
|
|
locals = {}
|
|
|
|
self._locals = locals
|
|
|
|
QWidget.__init__(self, parent=parent)
|
|
|
|
self._textWidget = QTextEdit(parent=self)
|
|
self._botWidget = QWidget(parent=self)
|
|
self._help_button = QPushButton('?', parent=self._botWidget)
|
|
self._run_button = QPushButton('Run', parent=self._botWidget)
|
|
self._run_button.clicked.connect(self._okClicked)
|
|
self._help_button.clicked.connect(self._helpClicked)
|
|
|
|
self._help_text = None
|
|
|
|
hbox = HBox(None, self._help_button, self._run_button)
|
|
self._botWidget.setLayout(hbox)
|
|
|
|
vbox = VBox(self._textWidget, self._botWidget)
|
|
self.setLayout(vbox)
|
|
|
|
self.setWindowTitle('Python Interactive')
|
|
|
|
def _okClicked(self):
|
|
pycode = str(self._textWidget.document().toPlainText())
|
|
try:
|
|
cobj = compile(pycode, "vqpython_exec.py", "exec")
|
|
sthr = ScriptThread(cobj, self._locals)
|
|
sthr.start()
|
|
except:
|
|
exceptstr = traceback.format_exc()
|
|
scripterr("Can't Compile", exceptstr)
|
|
|
|
def _helpClicked(self):
|
|
withhelp = []
|
|
for lname, lval in self._locals.items():
|
|
if type(lval) in (types.ModuleType, ):
|
|
continue
|
|
doc = getattr(lval, '__doc__', '\nNo Documentation\n')
|
|
if doc is None:
|
|
doc = '\nNo Documentation\n'
|
|
withhelp.append((lname, doc))
|
|
|
|
withhelp.sort()
|
|
|
|
txt = 'Objects/Functions in the namespace:\n'
|
|
for name, doc in withhelp:
|
|
txt += ('====== %s\n' % name)
|
|
txt += ('%s\n' % doc)
|
|
|
|
self._help_text = QTextEdit()
|
|
self._help_text.setReadOnly(True)
|
|
self._help_text.setWindowTitle('Python Interactive Help')
|
|
self._help_text.setText(txt)
|
|
self._help_text.show()
|