adapted HildonUI for MVC pattern
[meabook] / ui / hildon_ui.py
1 """
2 Hildon UI for Meabook
3 """
4
5 import gtk
6 import hildon
7 import gobject
8 import gettext
9 from meabook.ui.ui import MeabookUI
10
11 _ = gettext.gettext
12
13
14 def create_button(title, value):
15     """Create HildonButton."""
16
17     button = hildon.Button(gtk.HILDON_SIZE_AUTO | \
18         gtk.HILDON_SIZE_FINGER_HEIGHT, \
19         hildon.BUTTON_ARRANGEMENT_VERTICAL, title, value)
20     button.set_style(hildon.BUTTON_STYLE_PICKER)
21     button.set_alignment(0, 0, 0, 0)
22     return button
23
24
25 class HildonMeabook(MeabookUI):
26     def __init__(self, controller):
27         MeabookUI.__init__(self, controller)
28         self.internal_names = []
29         self.callback_id = None
30         self.window = hildon.StackableWindow()
31         self.window.set_title(_('Meabook'))
32         self.window.connect('destroy', self.exit)
33
34         # create menu buttons
35         menu = hildon.AppMenu()
36         settings_button = hildon.Button(gtk.HILDON_SIZE_AUTO, \
37             hildon.BUTTON_ARRANGEMENT_HORIZONTAL, _('Settings'))
38         about_button = hildon.Button(gtk.HILDON_SIZE_AUTO, \
39             hildon.BUTTON_ARRANGEMENT_HORIZONTAL, _('About'))
40
41         # create filter widgets
42         self.level1_filter = gtk.RadioButton(None, _('level1'))
43         self.level2_filter = gtk.RadioButton(self.level1_filter, _('level2'))
44         self.level3_filter = gtk.RadioButton(self.level2_filter, _('level3'))
45         for filter_widget in [self.level1_filter, self.level2_filter, \
46             self.level3_filter]:
47             filter_widget.set_mode(False)
48
49         # create items list
50         self.selector = hildon.TouchSelector(text=True)
51
52         # connect signals
53         settings_button.connect('clicked', self.show_settings_dialog_cb)
54         about_button.connect('clicked', self.show_about_dialog_cb)
55         self.level1_filter.connect('toggled', self.apply_filter_cb, \
56             self.controller.get_level1_items)
57         self.level2_filter.connect('toggled', self.apply_filter_cb, \
58             self.controller.get_level2_items)
59         self.level3_filter.connect('toggled', self.apply_filter_cb, \
60             self.controller.get_level3_items)
61
62         # packing widgets
63         self.window.add(self.selector)
64         menu.add_filter(self.level1_filter)
65         menu.add_filter(self.level2_filter)
66         menu.add_filter(self.level3_filter)
67         menu.append(settings_button)
68         menu.append(about_button)
69         menu.show_all()
70         self.window.set_app_menu(menu)
71         self.window.show_all()
72
73     def _set_selector_content(self, items):
74         self.internal_names = []
75         for item in items:
76             self.selector.append_text(item[0])
77             self.internal_names.append(item[1])
78
79     # Implementation of Base UI interface
80     def start(self):
81         gtk.main()
82
83     def exit(self, event):
84         gtk.main_quit()
85         self.controller.stop()
86
87     def get_current_level(self):
88         if self.level1_filter.get_active(): return 1
89         elif self.level2_filter.get_active(): return 2
90         else: return 3
91
92     def show_items(self, items, level):
93         if level == 1:  # level1_button is not in gorup, process separately
94             self.level1_filter.set_active(True)
95             self.apply_filter_cb(self.level1_filter, \
96                 self.controller.get_level1_items, items)
97         elif level == 2:
98             self.level2_filter.set_active(True)
99         else:
100             self.level3_filter.set_active(True)
101
102     def show_about_dialog(self):
103         dialog = hildon.Dialog()
104         dialog.set_title(_('About'))
105         label = gtk.Label('\nMeabook v0.1\n')
106         dialog.vbox.add(label)
107         dialog.vbox.show_all()
108         dialog.run()
109         dialog.destroy()
110
111     def show_fields_to_show_dialog(self):
112         ConfigurationDialog(self.controller, page=1)
113
114     def show_fileds_order_dialog(self):
115         ConfigurationDialog(self.controller, page=2)
116
117
118     # Hildon UI callbacks
119     def show_about_dialog_cb(self, widget):
120         """Shows About Dialog."""
121
122         self.show_about_dialog()
123
124     def show_settings_dialog_cb(self, widget):
125         """Shows Config dialog."""
126
127         ConfigurationDialog(self.controller)
128
129     def apply_filter_cb(self, widget, func, items=None):
130         """Updates toplevel selector with different level items."""
131
132         if not widget.get_active():
133             return
134
135         # blocks 'change' event for selector
136         try:
137             self.selector.handler_block(self.callback_id)
138         except:
139             pass
140
141         # update list content
142         self.selector.get_model(0).clear()
143         self._set_selector_content(items or func())
144         self.selector.unselect_all(0)
145
146         self.window.set_title(' - '.join([_('Meabook'), widget.get_label()]))
147
148     def _create_items_dialog(self, title):
149         """Creates dialog for showing items."""
150
151         selector = hildon.TouchSelector(text=True)
152         window = hildon.StackableWindow()
153         window.set_title(title)
154         window.add(selector)
155         return window, selector
156
157     def show_middlelevel_dialog(self, widget, column):
158         """Shows subitems of selected level1-item."""
159
160         selected_item = widget.get_current_text()
161         window, selector = self._create_items_dialog(selected_item)
162         selector.connect('changed', self.show_lowlevel_dialog)
163         for item in self.database.get_middlelevel_entries(selected_item):
164             selector.append_text(item)
165         window.show_all()
166
167     def show_lowlevel_dialog(self, widget, column):
168         """Shows lowlevel items."""
169
170         selected_item = widget.get_current_text()
171         window, selector = self._create_items_dialog(selected_item)
172         selector.connect('changed', self.show_item_dialog)
173         for item in self.database.get_lowlevel_entries():
174             selector.append_text(item)
175         window.show_all()
176
177     def show_item_dialog(self, widget, column):
178         """Shows detailed item information."""
179
180         selected_item = widget.get_current_text()
181         entry = self.database.get_entry(selected_item)
182         window = hildon.StackableWindow()
183         window.set_title(selected_item)
184         pannable_area = hildon.PannableArea()
185         vbox = gtk.VBox()
186
187         for key, value in entry.items():
188             button = create_button(_(key) , value)
189             vbox.pack_start(button)
190
191         pannable_area.add_with_viewport(vbox)
192         window.add(pannable_area)
193         window.show_all()
194
195
196
197
198 class ConfigurationDialog:
199     """Configuration dialog"""
200
201     def __init__(self, controller, page=1):
202         self.controller = controller
203
204         self.window = hildon.StackableWindow()
205         self.window.set_title(_('Configuration'))
206         self.window.connect('destroy', self.close_dialog_cb)
207
208         # create menu
209         menu = hildon.AppMenu()
210         self.button_order = gtk.RadioButton(None, _('Order'))
211         self.button_fields = gtk.RadioButton(self.button_order, _('Fields'))
212         self.button_order.set_mode(False)
213         self.button_fields.set_mode(False)
214         menu.add_filter(self.button_fields)
215         menu.add_filter(self.button_order)
216         menu.show_all()
217
218         # create other widgets
219         self.window.set_app_menu(menu)
220         self.selector = hildon.TouchSelector(text=True)
221         self.pannable_area = hildon.PannableArea()
222         vbox = gtk.VBox()
223         vbox.pack_start(self.selector)
224         vbox.pack_start(self.pannable_area)
225         self.window.add(vbox)
226
227         self.window.show_all()
228
229         # switches to necessary page
230         if page == 1:
231             self.button_fields.set_active(True)
232             self.show_fields_settings_cb(None)
233         else:
234             self.button_order.set_active(True)
235             self.show_order_settings_cb(None)
236
237         # connect signals
238         self.button_order.connect('clicked', self.show_order_settings_cb)
239         self.button_fields.connect('clicked', self.show_fields_settings_cb)
240
241     def show_fields_settings_cb(self, widget):
242         """Shows dialog for selecting fields to show."""
243
244         self.pannable_area.hide()
245
246         fields = self.controller.get_fields()
247
248         # fill items list
249         self.selector.get_model(0).clear()
250         for field in fields:
251             self.selector.append_text(_(field))
252
253         self.selector.set_column_selection_mode( \
254                 hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
255         self.selector.unselect_all(0)
256
257         # mark necessary fields
258         fields_to_select = self.controller.config.get_fields()
259         model = self.selector.get_model(0)
260         for index, field in enumerate(fields):
261             if field in fields_to_select:
262                 self.selector.select_iter(0, model.get_iter(index), False)
263
264         self.selector.show_all()
265
266     def show_order_settings_cb(self, widget):
267         """Shows dialog for setting fields order."""
268
269
270         def show_fields_chooser(widget):
271             """Shows dialog to select field from fields list."""
272
273             dialog = hildon.PickerDialog(self.window)
274             dialog.set_title(_('Field selection'))
275             selector = hildon.TouchSelector(text=True)
276             dialog.set_selector(selector)
277             selector.set_column_selection_mode( \
278                 hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
279
280             # fill fields list
281             for field in self.controller.get_fields():
282                 selector.append_text(field)
283
284             dialog.run()
285             widget.set_value(selector.get_current_text())
286             dialog.destroy()
287
288         self.selector.hide()
289
290         vbox = gtk.VBox()
291         for index, field in enumerate(self.controller.config.get_order()):
292             button = create_button(' '.join([_('Position'), str(index)]), \
293                 _(field))
294             button.connect('clicked', show_fields_chooser)
295             vbox.pack_start(button)
296
297         self.pannable_area.add_with_viewport(vbox)
298         self.pannable_area.show_all()
299
300     def close_dialog_cb(self, event):
301         """Save selected options."""
302
303         model = self.selector.get_model(0)
304         selected_items = [model[index][0] for index in [item[0] for item in \
305             self.selector.get_selected_rows(0)]]
306         self.controller.config.set_fields(selected_items)
307
308         try:
309             self.controller.config.set_order([button.get_value() for button in \
310                 self.pannable_area.get_child().get_children()[0].get_children()])
311         except AttributeError:
312             pass