Files
idapython-src/pywraps/py_kernwin_plgform.py
2025-03-13 16:17:53 +01:00

210 lines
7.0 KiB
Python

from __future__ import print_function
#<pycode(py_kernwin_plgform)>
import sys
import ida_idaapi
class PluginForm(object):
"""
PluginForm class.
This form can be used to host additional controls. Please check the PyQt example.
"""
WOPN_MDI = 0x01 # no-op
WOPN_TAB = 0x02 # no-op
WOPN_RESTORE = _ida_kernwin.WOPN_RESTORE
"""
if the widget is the only widget in a floating area when
it is closed, remember that area's geometry. The next
time that widget is created as floating (i.e., WOPN_DP_FLOATING)
its geometry will be restored (e.g., "Execute script"
"""
WOPN_ONTOP = 0x08 # no-op
WOPN_MENU = 0x10 # no-op
WOPN_CENTERED = 0x20 # no-op
WOPN_PERSIST = _ida_kernwin.WOPN_PERSIST
"""form will persist until explicitly closed with Close()"""
WOPN_DP_LEFT = _ida_kernwin.WOPN_DP_LEFT
""" Dock widget to the left of dest_ctrl"""
WOPN_DP_TOP = _ida_kernwin.WOPN_DP_TOP
""" Dock widget above dest_ctrl"""
WOPN_DP_RIGHT = _ida_kernwin.WOPN_DP_RIGHT
""" Dock widget to the right of dest_ctrl"""
WOPN_DP_BOTTOM = _ida_kernwin.WOPN_DP_BOTTOM
""" Dock widget below dest_ctrl"""
WOPN_DP_INSIDE = _ida_kernwin.WOPN_DP_INSIDE
""" Create a new tab bar with both widget and dest_ctrl"""
WOPN_DP_TAB = _ida_kernwin.WOPN_DP_TAB
"""
Place widget into a tab next to dest_ctrl,
if dest_ctrl is in a tab bar
(otherwise the same as #WOPN_DP_INSIDE)
"""
WOPN_DP_BEFORE = _ida_kernwin.WOPN_DP_BEFORE
"""
place widget before dst_form in the tab bar instead of after
used with #WOPN_DP_INSIDE and #WOPN_DP_TAB
"""
WOPN_DP_FLOATING = _ida_kernwin.WOPN_DP_FLOATING
"""
When floating or in a splitter (i.e., not tabbed),
use the widget's size hint to determine the best
geometry (Qt only)
"""
WOPN_DP_SZHINT = _ida_kernwin.WOPN_DP_SZHINT
""" Make widget floating"""
WOPN_DP_INSIDE_BEFORE = _ida_kernwin.WOPN_DP_INSIDE_BEFORE
WOPN_DP_TAB_BEFORE = _ida_kernwin.WOPN_DP_TAB_BEFORE
WOPN_CREATE_ONLY = {}
def __init__(self):
"""
"""
self.__clink__ = _ida_kernwin.plgform_new()
def Show(self, caption, options=0):
"""
Creates the form if not was not created or brings to front if it was already created
@param caption: The form caption
@param options: One of PluginForm.WOPN_ constants
"""
if options == self.WOPN_CREATE_ONLY:
options = -1
else:
options |= PluginForm.WOPN_DP_TAB|PluginForm.WOPN_RESTORE
return _ida_kernwin.plgform_show(self.__clink__, self, caption, options)
@staticmethod
def _ensure_widget_deps(ctx):
for modname in ["sip", "QtWidgets"]:
if not hasattr(ctx, modname):
import importlib
setattr(ctx, modname, importlib.import_module("PyQt5." + modname))
VALID_CAPSULE_NAME = b"$valid$"
@staticmethod
def TWidgetToQtPythonWidget(tw, ctx = sys.modules['__main__']):
"""
Convert a TWidget* to a QWidget to be used by the Qt Python bindings
"""
if type(tw).__name__ == 'SwigPyObject':
ptr_l = int(tw)
else:
import ctypes
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
ptr_l = ctypes.pythonapi.PyCapsule_GetPointer(tw, PluginForm.VALID_CAPSULE_NAME)
try:
import shiboken6.Shiboken
import PySide6.QtWidgets
return shiboken6.Shiboken.wrapInstance(ptr_l, PySide6.QtWidgets.QWidget)
except ImportError:
# Assume PyQt5
PluginForm._ensure_widget_deps(ctx)
vptr = ctx.sip.voidptr(ptr_l)
return ctx.sip.wrapinstance(vptr.__int__(), ctx.QtWidgets.QWidget)
TWidgetToPyQtWidget = TWidgetToQtPythonWidget
FormToPyQtWidget = TWidgetToQtPythonWidget
@staticmethod
def QtWidgetToTWidget(w, ctx = sys.modules['__main__']):
"""
Convert a QWidget to a TWidget* to be used by IDA
@param ctx: Context. Reference to a module that already imported SIP and QtWidgets modules
"""
PluginForm._ensure_widget_deps(ctx)
as_long = ida_idaapi.long_type(ctx.sip.unwrapinstance(w))
return TWidget__from_ptrval__(as_long)
@staticmethod
def TWidgetToPySideWidget(tw, ctx = sys.modules['__main__']):
"""
Use this method to convert a TWidget* to a QWidget to be used by PySide
@param ctx: Context. Reference to a module that already imported QtWidgets module
"""
if tw is None:
return None
if type(tw).__name__ == "SwigPyObject":
# Since 'tw' is a SwigPyObject, we first need to convert it to a PyCapsule.
# However, there's no easy way of doing it, so we'll use a rather brutal approach:
# converting the SwigPyObject to a 'long' (will go through 'SwigPyObject_long',
# that will return the pointer's value as a long), and then convert that value
# back to a pointer into a PyCapsule.
ptr_l = ida_idaapi.long_type(tw)
# Warning: this is untested
import ctypes
ctypes.pythonapi.PyCapsule_New.restype = ctypes.py_object
ctypes.pythonapi.PyCapsule_New.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p]
tw = ctypes.pythonapi.PyCapsule_New(ptr_l, PluginForm.VALID_CAPSULE_NAME, 0)
return ctx.QtGui.QWidget.FromCapsule(tw)
FormToPySideWidget = TWidgetToPySideWidget
def OnCreate(self, form):
"""
This event is called when the plugin form is created.
The programmer should populate the form when this event is triggered.
@return: None
"""
pass
def OnClose(self, form):
"""
Called when the plugin form is closed
@return: None
"""
pass
def Close(self, options):
"""
Closes the form.
@param options: Close options (WCLS_SAVE, WCLS_NO_CONTEXT, ...)
@return: None
"""
return _ida_kernwin.plgform_close(self.__clink__, options)
def GetWidget(self):
"""
Return the TWidget underlying this view.
@return: The TWidget underlying this view, or None.
"""
return _ida_kernwin.plgform_get_widget(self.__clink__)
WCLS_SAVE = _ida_kernwin.WCLS_SAVE
"""Save state in desktop config"""
WCLS_NO_CONTEXT = _ida_kernwin.WCLS_NO_CONTEXT
"""Don't change the current context (useful for toolbars)"""
WCLS_DONT_SAVE_SIZE = _ida_kernwin.WCLS_DONT_SAVE_SIZE
"""Don't save size of the window"""
WCLS_DELETE_LATER = _ida_kernwin.WCLS_DELETE_LATER
"""This flag should be used when Close() is called from an event handler"""
WCLS_CLOSE_LATER = WCLS_DELETE_LATER
#</pycode(py_kernwin_plgform)>