import gdb
+import gdb.types
import gtk
import pango
import pangocairo
import math
+def type_has_fields(t):
+ basic_type = gdb.types.get_basic_type(t)
+ return basic_type.code == gdb.TYPE_CODE_STRUCT or basic_type.code == gdb.TYPE_CODE_UNION
+
def segment_intersection(A, B, C, D):
"""Computes the intersection between the rect segment AB and the rect segment CD.
All parameters are 2D points expressed as (x,y) tuples. Result is also a (x,y) tuple, or
self.name = name
self.gdb_value = gdb_value
self.connections = [] # outgoing pointers to other nodes, to draw arrows
- self.fill_color = (0.8, 0.4, 0)
+ self.fill_color = (0.4, 0.4, 0.5)
class GraphViewer(gtk.DrawingArea):
- def __init__(self):
+ def __init__(self, value_viewer):
super(gtk.DrawingArea, self).__init__()
self.nodes = []
- self.connect("expose_event", self.expose)
+ self.selected_node = None
+ self.value_viewer = value_viewer
+ self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ self.connect("expose_event", self.on_expose)
+ self.connect("button_press_event", self.on_click)
- def expose(self, widget, event):
+ def on_expose(self, widget, event):
context = pangocairo.CairoContext(widget.window.cairo_create())
context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
context.clip()
self.draw(context)
return False
+ def on_click(self, widget, event):
+ self.selected_node = None
+ for node in self.nodes:
+ if event.x >= node.x and event.x < node.x + node.width and event.y >= node.y and event.y < node.y + node.height:
+ self.selected_node = node
+
+ if self.selected_node != None:
+ self.value_viewer.set_value(self.selected_node.gdb_value)
+
+ self.queue_draw()
+ return False
+
def draw_node(self, context, node):
# draw node name
context.show_layout(name_layout)
# draw node rect
+ context.save()
context.rectangle(node.x, node.y, node.width, node.height)
context.set_source_rgb(*node.fill_color)
context.fill()
- context.set_source_rgb(0,0,0)
- context.set_line_width(1)
+ if node is self.selected_node:
+ context.set_source_rgb(1,0,0)
+ context.set_line_width(3)
context.rectangle(node.x, node.y, node.width, node.height)
context.stroke()
+ context.restore()
def draw_connection(self, context, n1, n2):
(p1, p2) = node_connection_points(n1, n2)
+ context.set_source_rgb(0,0,0)
+ context.set_line_width(1)
context.move_to(*p1)
context.line_to(*p2)
context.stroke()
for other in node.connections:
self.draw_connection(context, node, other)
+class GdbValueViewer(gtk.TreeView):
+ def __init__(self):
+ super(gtk.TreeView, self).__init__()
+ self.store = gtk.TreeStore(str, str)
+ self.set_model(self.store)
+ # column setup
+ # column 0
+ self.field_column = gtk.TreeViewColumn("Field")
+ self.field_cell = gtk.CellRendererText()
+ self.field_column.pack_start(self.field_cell)
+ self.append_column(self.field_column)
+ self.field_column.add_attribute(self.field_cell, 'text', 0)
+ # column 1
+ self.value_column = gtk.TreeViewColumn("Value")
+ self.value_cell = gtk.CellRendererText()
+ self.value_column.pack_start(self.value_cell)
+ self.append_column(self.value_column)
+ self.value_column.add_attribute(self.value_cell, 'text', 1)
+
+ # make column 0 searchable and sortable
+ self.set_search_column(0)
+ self.field_column.set_sort_column_id(0)
+
+ def visit_value(self, value, store_iter):
+ if type_has_fields(value.type):
+ for f in value.type.fields():
+ field_value = value[f.name]
+ if type_has_fields(field_value.type) > 0:
+ child_iter = self.store.append(store_iter, (f.name, str(f.type)))
+ self.visit_value(field_value, child_iter)
+ else:
+ self.store.append(store_iter, (f.name, str(field_value)))
+ else:
+ self.store.append(None, ("<value>", str(value)))
+
+
+ def set_value(self, value):
+ self.store.clear()
+ self.visit_value(value, None)
+ # fill the TreeStore with value fields
+ self.queue_draw()
+
class ViewerWindow(gtk.Window):
def __init__(self):
super(gtk.Window, self).__init__()
self.entry = gtk.Entry()
- self.viewer = GraphViewer()
- self.properties = gtk.TreeView()
+ self.properties = GdbValueViewer()
+ self.viewer = GraphViewer(self.properties)
self.vbox = gtk.VBox()
self.paned = gtk.HPaned()
labelhbox = gtk.HBox()
pointee_width, pointee_height, pointee_nodes = visit_values(pointee, children_x, children_y, recursion_level - 1)
merge_dict(result, pointee_nodes)
return NODE_SPACING+pointee_width, max(NODE_SPACING, pointee_height), result
- elif len(value.type.fields()) > 0:
+ elif type_has_fields(value.type):
for f in value.type.fields():
child = value[f.name]
if child.type.code == gdb.TYPE_CODE_PTR:
window.viewer.queue_draw()
gtk.main()
except:
- print "trololo"
window.destroy()
raise