10 # The gdbtool user interface. The design here is to keep all the gtk stuff
11 # separate from the tdb stuff so all the user interface magic is stored
17 # Initialise the user interface. A dictionary argument is passed
18 # in which is the dictionary to display keys and values on the left
19 # hand and right hand side of the user interface respectively."""
21 def __init__(self
, dict):
23 self
.value_display_fns
= []
24 self
.filter_regex
= ""
26 # Create and configure user interface widgets. A string argument is
27 # used to set the window title.
29 def build_ui(self
, title
):
33 win
.connect("destroy", mainquit
)
37 hpaned
.set_border_width(5)
44 scrolled_win
= GtkScrolledWindow()
45 scrolled_win
.set_policy(POLICY_AUTOMATIC
, POLICY_AUTOMATIC
)
46 vbox
.pack_start(scrolled_win
)
50 vbox
.pack_end(hbox
, expand
= 0, padding
= 5)
53 label
= GtkLabel("Filter:")
54 hbox
.pack_start(label
, expand
= 0, padding
= 5)
57 self
.entry
= GtkEntry()
58 hbox
.pack_end(self
.entry
, padding
= 5)
61 self
.entry
.connect("activate", self
.filter_activated
)
64 self
.list.set_selection_mode(SELECTION_MULTIPLE
)
65 self
.list.set_selection_mode(SELECTION_BROWSE
)
66 scrolled_win
.add_with_viewport(self
.list)
69 self
.list.connect("select_child", self
.key_selected
)
71 scrolled_win
= GtkScrolledWindow()
72 scrolled_win
.set_policy(POLICY_AUTOMATIC
, POLICY_AUTOMATIC
)
73 hpaned
.add2(scrolled_win
)
74 scrolled_win
.set_usize(500,400)
78 self
.text
.set_editable(FALSE
)
79 scrolled_win
.add_with_viewport(self
.text
)
82 self
.text
.connect("event", self
.event_handler
)
87 self
.font
= load_font("fixed")
93 # Add a key to the left hand side of the user interface
95 def add_key(self
, key
):
96 display_key
= self
.display_key(key
)
97 list_item
= GtkListItem(display_key
)
98 list_item
.set_data("raw_key", key
) # Store raw key in item data
99 self
.list.add(list_item
)
102 # Event handler registered by build_ui()
104 def event_handler(self
, event
, menu
):
107 # Set the text to appear in the right hand side of the user interface
109 def set_value_text(self
, text
):
110 self
.text
.delete_text(0, self
.text
.get_length())
112 # The text widget has trouble inserting text containing NULL
115 text
= string
.replace(text
, "\x00", ".")
117 self
.text
.insert(self
.font
, None, None, text
)
119 # This function is called when a key is selected in the left hand side
120 # of the user interface.
122 def key_selected(self
, list, list_item
):
123 key
= list_item
.children()[0].get()
125 # Look for a match in the value display function list
127 text
= t
[list_item
.get_data("raw_key")]
129 for entry
in self
.value_display_fns
:
130 if re
.match(entry
[0], key
):
131 text
= entry
[1](text
)
134 self
.set_value_text(text
)
136 # Refresh the key list by removing all items and re-inserting them.
137 # Items are only inserted if they pass through the filter regexp.
139 def update_keylist(self
):
140 self
.list.remove_items(self
.list.children())
141 self
.set_value_text("")
142 for k
in self
.dict.keys():
143 if re
.match(self
.filter_regex
, k
):
146 # Invoked when the user hits return in the filter text entry widget.
148 def filter_activated(self
, entry
):
149 self
.filter_regex
= entry
.get_text()
150 self
.update_keylist()
156 # Set a function that translates between how keys look in the user
157 # interface (displayed keys) versus how they are represented in the tdb
160 def set_display_key_fn(self
, fn
):
161 self
.display_key
= fn
163 # Register a value display function for a key. The first argument is a
164 # regex that matches key values, and the second argument is a function
165 # to call to convert the raw value data to a string to display in the
166 # right hand side of the UI.
168 def register_display_value_fn(self
, key_regexp
, fn
):
169 self
.value_display_fns
.append((key_regexp
, fn
))
171 def display_value_hex(self
, value
):
174 def convert_to_hex(data
):
175 """Return a hex dump of a string as a string.
177 The output produced is in the standard 16 characters per line hex +
180 00000000: 40 00 00 00 00 00 00 00 40 00 00 00 01 00 04 80 @....... @.......
181 00000010: 01 01 00 00 00 00 00 01 00 00 00 00 ........ ....
184 pos
= 0 # Position in data
185 line
= 0 # Line of data
187 hex = "" # Hex display
188 ascii
= "" # ASCII display
192 while pos
< len(data
):
197 hex = "%08x: " % (line
* 16)
202 hex = hex + "%02x " % (ord(data
[pos
]))
204 if ord(data
[pos
]) < 32 or ord(data
[pos
]) > 176:
207 ascii
= ascii
+ data
[pos
]
211 # Add separator if half way
220 result
= result
+ "%s %s\n" % (hex, ascii
)
229 for i
in range(0, (16 - (pos
% 16))):
237 result
= result
+ "%s %s\n" % (hex, ascii
)
243 if len(sys
.argv
) != 2:
244 print "Usage: gdbtool <tdbfile>"
248 t
= tdb
.open(sys
.argv
[1])
250 print "gtdbtool: error opening %s: %s" % (sys
.argv
[1], t
)
253 # Create user interface
257 # Set up a key display function. A lot of keys have \x00 appended to the
258 # end which mucks up gtk.
260 def display_key_x00(key
):
261 return string
.replace(key
, "\x00", "")
263 w
.set_display_key_fn(display_key_x00
)
265 def display_value_hex(value
):
268 w
.register_display_value_fn("DRIVERS/", convert_to_hex
)
269 w
.register_display_value_fn("SECDESC/", convert_to_hex
)
270 w
.register_display_value_fn("PRINTERS/", convert_to_hex
)
272 # Show user interface
274 w
.build_ui("gtdbtool: %s" % sys
.argv
[1])
276 # Override Python's handling of ctrl-c so we can break out of the gui
277 # from the command line.
280 signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
)