Fix title. oops
[hermes] / package / src / org / maemo / hermes / gui / searchablelist.py
1 import gtk, hildon
2
3 class SearchableList(hildon.PannableArea):
4     """Widget which exposes a TreeView with find-as-you-type features.
5          
6        Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
7        Released under the Artistic Licence."""
8     
9     
10     # -----------------------------------------------------------------------
11     def __init__(self, search_column):
12         """Constructor. Passed a search column - expected to be exposed from
13            a subclass.
14
15            Subclasses must also initialise self.treestore, self.treeview and
16            then do self.add(self.treeview)."""
17         
18         hildon.PannableArea.__init__(self)
19         self._search_column = search_column
20         self.set_size_request_policy(hildon.SIZE_REQUEST_CHILDREN)
21
22         self.hbox_entry_filter = None
23
24
25     # -----------------------------------------------------------------------
26     def get_search(self):
27         """Return a search box. If added to the tree will handle filtering this
28            treeview automatically."""
29
30         self.hbox_entry_filter = gtk.VBox()
31         real_hbox = gtk.HBox()
32         self.hbox_entry_filter.pack_end(real_hbox, False, False)
33
34         self.entry_filter = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
35         self.entry_filter.connect('changed', lambda w: self.filter.refilter())
36         real_hbox.pack_start(self.entry_filter, True, True)
37
38         #close = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL, title = _('Show all'))
39         #close.connect('clicked', self._hide_search)
40         #real_hbox.pack_end(close, False, False, 0)
41
42         (path, col) = self.treeview.get_cursor()
43         self.filter = self.treeview.get_model().filter_new()
44         self.filter.set_visible_func(self._visible_func, self._search_column)
45         self.treeview.connect('key-press-event', self._on_key_press)
46         self.treeview.set_model(self.filter)
47         if path:
48             self.treeview.scroll_to_cell(path)
49         real_hbox.show_all()
50
51         return self.hbox_entry_filter
52
53
54
55     # -----------------------------------------------------------------------
56     def _on_key_press(self, treeview, event):
57         if event.keyval == gtk.keysyms.Escape or event.keyval == gtk.keysyms.BackSpace:
58             self._hide_search()
59         elif event.state & gtk.gdk.CONTROL_MASK:
60             # Don't handle type-ahead when control is pressed (so shortcuts
61             # with the Ctrl key still work, e.g. Ctrl+A, ...)
62             return True
63         else:
64             unicode_char_id = gtk.gdk.keyval_to_unicode(event.keyval)
65             if unicode_char_id == 0:
66                 return False
67             input_char = unichr(unicode_char_id)
68             self._show_search(input_char)
69         return True
70
71
72
73     # -----------------------------------------------------------------------
74     def _visible_func(self, model, iter, column):
75         text = self.entry_filter.get_text().lower()
76         if not self.hbox_entry_filter.get_property('visible'):
77             return True
78         elif text == '':
79             self._hide_search()
80             return True
81         else:
82             value = model.get_value(iter, column).lower()
83             return text in value
84
85     
86     # -----------------------------------------------------------------------
87     def _hide_search(self, *args):
88         self.hbox_entry_filter.hide()
89         self.entry_filter.set_text('')
90         self.filter.refilter()
91         self.treeview.grab_focus()
92
93
94     # -----------------------------------------------------------------------
95     def _show_search(self, input_char):
96         self.hbox_entry_filter.show_all()
97         self.entry_filter.insert_text(input_char, -1)
98         self.entry_filter.grab_focus()
99         self.entry_filter.set_position(-1)
100