Files
2025-03-13 16:17:53 +01:00

102 lines
3.0 KiB
Python

"""
summary: follow the movements of one graph, in another
description:
Since it is possible to be notified of movements that happen
take place in a widget, it's possible to "replay" those
movements in another.
In this case, "IDA View-B" (will be opened if necessary) will
show the same contents as "IDA View-A", slightly zoomed out.
keywords: graph, idaview
see_also: wrap_idaview
level: intermediate
"""
import ida_kernwin
import ida_moves
import ida_graph
#
# Cleanup (in case the script is run more than once)
#
try:
wrap_a.Unbind()
except:
pass
wrap_a = None
#
# The IDA View-A "monitor": changes will be reported into IDA View-B
#
class IDAViewA_monitor_t(ida_kernwin.IDAViewWrapper):
def __init__(self):
ida_kernwin.IDAViewWrapper.__init__(self, "IDA View-A")
def OnViewLocationChanged(self, now, was):
self.update_widget_b()
def update_widget_b(self):
# Make sure we are in the same function
place_a, _, _ = ida_kernwin.get_custom_viewer_place(widget_a, False)
ida_kernwin.jumpto(widget_b, place_a, -1, -1)
# and that we show the right place (slightly zoomed out)
widget_a_center_gli = ida_moves.graph_location_info_t()
if ida_graph.viewer_get_gli(widget_a_center_gli, widget_a, ida_graph.GLICTL_CENTER):
widget_b_center_gli = ida_moves.graph_location_info_t()
widget_b_center_gli.orgx = widget_a_center_gli.orgx
widget_b_center_gli.orgy = widget_a_center_gli.orgy
widget_b_center_gli.zoom = widget_a_center_gli.zoom * 0.5
ida_graph.viewer_set_gli(widget_b, widget_b_center_gli, ida_graph.GLICTL_CENTER)
#
# Make sure both views are opened...
#
for label in ["A", "B"]:
title = "IDA View-%s" % label
if not ida_kernwin.find_widget(title):
print("View %s not available. Opening." % title)
ida_kernwin.open_disasm_window(label)
#
# ...and that they are both in graph mode
#
widget_a = ida_kernwin.find_widget("IDA View-A")
ida_kernwin.set_view_renderer_type(widget_a, ida_kernwin.TCCRT_GRAPH)
widget_b = ida_kernwin.find_widget("IDA View-B")
ida_kernwin.set_view_renderer_type(widget_b, ida_kernwin.TCCRT_GRAPH)
#
# Put view B to the right of view A
#
ida_kernwin.set_dock_pos("IDA View-B", "IDA View-A", ida_kernwin.DP_RIGHT)
#
# Start monitoring IDA View-A
#
wrap_a = IDAViewA_monitor_t()
wrap_a.Bind()
#
# This is to get a properly initialized set of views to begin with.
# At this point, all UI resize/move events resulting of 'set_dock_pos()'
# haven't yet been processed, and thus the views don't know their final
# geometries. We'll give them a bit of time to process those events, and
# then we'll request that "IDA View-A" shows the whole graph (and
# "IDA View-B" will obviously follow.)
#
def fit_widget_a():
def do_fit_widget_a():
ida_graph.viewer_fit_window(widget_a)
ida_kernwin.execute_sync(do_fit_widget_a, ida_kernwin.MFF_FAST)
import threading
threading.Timer(0.25, fit_widget_a).start()