r19058: Implement "user cannot change password", and complete "user must change
[Samba.git] / source / python / gtkdictbrowser.py
blobdd8bed8f47874fbc939c9c57b76c6c4997399550
1 #!/usr/bin/python
3 # Browse a Python dictionary in a two pane graphical interface written
4 # in GTK.
6 # The GtkDictBrowser class is supposed to be generic enough to allow
7 # applications to override enough methods and produce a
8 # domain-specific browser provided the information is presented as a
9 # Python dictionary.
11 # Possible applications:
13 # - Windows registry browser
14 # - SPOOLSS printerdata browser
15 # - tdb file browser
18 from gtk import *
19 import string, re
21 class GtkDictBrowser:
23 def __init__(self, dict):
24 self.dict = dict
26 # This variable stores a list of (regexp, function) used to
27 # convert the raw value data to a displayable string.
29 self.get_value_text_fns = []
30 self.get_key_text = lambda x: x
32 # We can filter the list of keys displayed using a regex
34 self.filter_regex = ""
36 # Create and configure user interface widgets. A string argument is
37 # used to set the window title.
39 def build_ui(self, title):
40 win = GtkWindow()
41 win.set_title(title)
43 win.connect("destroy", mainquit)
45 hpaned = GtkHPaned()
46 win.add(hpaned)
47 hpaned.set_border_width(5)
48 hpaned.show()
50 vbox = GtkVBox()
51 hpaned.add1(vbox)
52 vbox.show()
54 scrolled_win = GtkScrolledWindow()
55 scrolled_win.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
56 vbox.pack_start(scrolled_win)
57 scrolled_win.show()
59 hbox = GtkHBox()
60 vbox.pack_end(hbox, expand = 0, padding = 5)
61 hbox.show()
63 label = GtkLabel("Filter:")
64 hbox.pack_start(label, expand = 0, padding = 5)
65 label.show()
67 self.entry = GtkEntry()
68 hbox.pack_end(self.entry, padding = 5)
69 self.entry.show()
71 self.entry.connect("activate", self.filter_activated)
73 self.list = GtkList()
74 self.list.set_selection_mode(SELECTION_MULTIPLE)
75 self.list.set_selection_mode(SELECTION_BROWSE)
76 scrolled_win.add_with_viewport(self.list)
77 self.list.show()
79 self.list.connect("select_child", self.key_selected)
81 scrolled_win = GtkScrolledWindow()
82 scrolled_win.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
83 hpaned.add2(scrolled_win)
84 scrolled_win.set_usize(500,400)
85 scrolled_win.show()
87 self.text = GtkText()
88 self.text.set_editable(FALSE)
89 scrolled_win.add_with_viewport(self.text)
90 self.text.show()
92 self.text.connect("event", self.event_handler)
94 self.menu = GtkMenu()
95 self.menu.show()
97 self.font = load_font("fixed")
99 self.update_keylist()
101 win.show()
103 # Add a key to the left hand side of the user interface
105 def add_key(self, key):
106 display_key = self.get_key_text(key)
107 list_item = GtkListItem(display_key)
108 list_item.set_data("raw_key", key) # Store raw key in item data
109 self.list.add(list_item)
110 list_item.show()
112 # Event handler registered by build_ui()
114 def event_handler(self, event, menu):
115 return FALSE
117 # Set the text to appear in the right hand side of the user interface
119 def set_value_text(self, item):
121 # Clear old old value in text window
123 self.text.delete_text(0, self.text.get_length())
125 if type(item) == str:
127 # The text widget has trouble inserting text containing NULL
128 # characters.
130 item = string.replace(item, "\x00", ".")
132 self.text.insert(self.font, None, None, item)
134 else:
136 # A non-text item
138 self.text.insert(self.font, None, None, repr(item))
140 # This function is called when a key is selected in the left hand side
141 # of the user interface.
143 def key_selected(self, list, list_item):
144 key = list_item.children()[0].get()
146 # Look for a match in the value display function list
148 text = self.dict[list_item.get_data("raw_key")]
150 for entry in self.get_value_text_fns:
151 if re.match(entry[0], key):
152 text = entry[1](text)
153 break
155 self.set_value_text(text)
157 # Refresh the key list by removing all items and re-inserting them.
158 # Items are only inserted if they pass through the filter regexp.
160 def update_keylist(self):
161 self.list.remove_items(self.list.children())
162 self.set_value_text("")
163 for k in self.dict.keys():
164 if re.match(self.filter_regex, k):
165 self.add_key(k)
167 # Invoked when the user hits return in the filter text entry widget.
169 def filter_activated(self, entry):
170 self.filter_regex = entry.get_text()
171 self.update_keylist()
173 # Register a key display function
175 def register_get_key_text_fn(self, fn):
176 self.get_key_text = fn
178 # Register a value display function
180 def register_get_value_text_fn(self, regexp, fn):
181 self.get_value_text_fns.append((regexp, fn))
184 # A utility function to convert a string to the standard hex + ascii format.
185 # To display all values in hex do:
186 # register_get_value_text_fn("", gtkdictbrowser.hex_string)
189 def hex_string(data):
190 """Return a hex dump of a string as a string.
192 The output produced is in the standard 16 characters per line hex +
193 ascii format:
195 00000000: 40 00 00 00 00 00 00 00 40 00 00 00 01 00 04 80 @....... @.......
196 00000010: 01 01 00 00 00 00 00 01 00 00 00 00 ........ ....
199 pos = 0 # Position in data
200 line = 0 # Line of data
202 hex = "" # Hex display
203 ascii = "" # ASCII display
205 result = ""
207 while pos < len(data):
209 # Start with header
211 if pos % 16 == 0:
212 hex = "%08x: " % (line * 16)
213 ascii = ""
215 # Add character
217 hex = hex + "%02x " % (ord(data[pos]))
219 if ord(data[pos]) < 32 or ord(data[pos]) > 176:
220 ascii = ascii + '.'
221 else:
222 ascii = ascii + data[pos]
224 pos = pos + 1
226 # Add separator if half way
228 if pos % 16 == 8:
229 hex = hex + " "
230 ascii = ascii + " "
232 # End of line
234 if pos % 16 == 0:
235 result = result + "%s %s\n" % (hex, ascii)
236 line = line + 1
238 # Leftover bits
240 if pos % 16 != 0:
242 # Pad hex string
244 for i in range(0, (16 - (pos % 16))):
245 hex = hex + " "
247 # Half way separator
249 if (pos % 16) < 8:
250 hex = hex + " "
252 result = result + "%s %s\n" % (hex, ascii)
254 return result
256 # For testing purposes, create a fixed dictionary to browse with
258 if __name__ == "__main__":
260 dict = {"chicken": "ham", "spam": "fun", "subdict": {"a": "b", "c": "d"}}
262 db = GtkDictBrowser(dict)
264 db.build_ui("GtkDictBrowser")
266 # Override Python's handling of ctrl-c so we can break out of the
267 # gui from the command line.
269 import signal
270 signal.signal(signal.SIGINT, signal.SIG_DFL)
272 mainloop()