8 from gettext import gettext as _
9 from meabook.ui.ui import MeabookUI
16 def create_button(title, value):
17 """Creates HildonButton."""
19 button = hildon.Button(gtk.HILDON_SIZE_AUTO | \
20 gtk.HILDON_SIZE_FINGER_HEIGHT, \
21 hildon.BUTTON_ARRANGEMENT_VERTICAL, title, value)
22 button.set_style(hildon.BUTTON_STYLE_PICKER)
23 button.set_alignment(0, 0, 0, 0)
27 def create_menu_button(title):
28 """Creates Hildon menu button."""
30 return hildon.Button(gtk.HILDON_SIZE_AUTO, \
31 hildon.BUTTON_ARRANGEMENT_HORIZONTAL, title)
34 class HildonMeabook(MeabookUI):
35 def __init__(self, controller, renderer, config):
36 MeabookUI.__init__(self, controller, renderer, config)
38 self.window = hildon.StackableWindow()
39 self.window.set_title(_('Meabook'))
40 self.window.connect('destroy', self.exit)
43 self.menu = hildon.AppMenu()
44 settings_button = create_menu_button(_('Settings'))
45 about_button = create_menu_button(_('About'))
46 import_button = create_menu_button(_('Import'))
48 # create filter widgets and connect signals
49 self.level1_filter = gtk.RadioButton(None, _('level1'))
50 self.level2_filter = gtk.RadioButton(self.level1_filter, _('level2'))
51 self.level3_filter = gtk.RadioButton(self.level2_filter, _('level3'))
52 for filter_widget in [self.level1_filter, self.level2_filter, \
54 filter_widget.set_mode(False)
55 filter_widget.connect('toggled', self.apply_filter_cb)
58 self.selector = hildon.TouchSelector()
60 widgets_box = gtk.VBox()
61 self.search_entry = hildon.Entry(gtk.HILDON_SIZE_AUTO)
64 settings_button.connect('clicked', self.show_settings_dialog_cb)
65 about_button.connect('clicked', self.show_about_dialog_cb)
66 import_button.connect('clicked', self.show_import_dialog_cb)
67 self.handler = self.selector.connect('changed', self.select_item_cb)
68 self.search_entry.connect('key-release-event', self.search_item_cb)
71 widgets_box.pack_start(self.selector, expand=True)
72 widgets_box.pack_end(self.search_entry, expand=False)
73 self.window.add(widgets_box)
74 self.menu.add_filter(self.level1_filter)
75 self.menu.add_filter(self.level2_filter)
76 self.menu.add_filter(self.level3_filter)
77 self.menu.append(settings_button)
78 self.menu.append(import_button)
79 self.menu.append(about_button)
81 self.window.set_app_menu(self.menu)
82 self.window.show_all()
84 def _unfreeze_ui(self):
85 while gtk.events_pending():
86 gtk.main_iteration(False)
88 def _update_title(self, title):
89 """Set window title text."""
92 self.window.set_title(title)
94 def _set_selector_content(self, selector, handler, items=[]):
95 """Updates selector content."""
97 # temporary block handler
98 selector.handler_block(handler)
100 # setting new content
101 # model: name, internal_name, type
102 model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT, \
106 if selector.get_num_columns():
107 selector.remove_column(0)
108 selector.append_text_column(model, False)
109 selector.unselect_all(0)
112 selector.handler_unblock(handler)
114 def _show_items_dialog(self, title, items):
115 """Creates dialog with items."""
117 selector = hildon.TouchSelector()
118 window = hildon.StackableWindow()
119 window.set_title(title)
121 handler = selector.connect('changed', self.select_item_cb)
122 self._set_selector_content(selector, handler, items)
125 def _show_item_dialog(self, title, entry_id):
126 """Shows detailed item information."""
128 def show_settings_dialog(widget, parent, func1, func2, entry_id):
129 dialog = ConfigurationDialog(self.controller, self.config)
130 response = getattr(dialog, func1)(None, parent)
131 if response == gtk.RESPONSE_OK:
132 func2(parent, entry_id)
134 def update_entry(window, entry_id):
136 entry = self.controller.get_item(entry_id)
137 widgets_table = gtk.Table(rows=1, columns=1)
138 info_box = gtk.VBox()
139 image_box = gtk.VBox()
140 pannable_area = hildon.PannableArea()
141 pannable_area.set_property('mov-mode', hildon.MOVEMENT_MODE_BOTH)
142 image = self.renderer.render_image(dict(entry))
143 for fname, fvalue in entry:
146 button = self.renderer.render_button(_(fname) , fvalue, fname)
147 info_box.pack_start(button, expand=False)
149 image_box.pack_start(image, expand=False)
150 widgets_table.attach(image_box, 0, 1, 0, 1, xoptions=gtk.SHRINK, \
151 yoptions=gtk.FILL, xpadding=4, ypadding=8)
152 pannable_area.add_with_viewport(info_box)
153 widgets_table.attach(pannable_area, 1, 2, 0, 1, ypadding=8)
154 child = window.get_child()
157 window.add(widgets_table)
158 widgets_table.show_all()
162 window = hildon.StackableWindow()
163 window.set_title(title)
164 menu = hildon.AppMenu()
165 fields_button = create_menu_button(_('Fields to show'))
166 order_button = create_menu_button(_('Fields order'))
167 fields_button.connect('clicked', show_settings_dialog, window, \
168 'show_fields_settings_cb', update_entry, entry_id)
169 order_button.connect('clicked', show_settings_dialog, window, \
170 'show_order_settings_cb', update_entry, entry_id)
171 menu.append(fields_button)
172 menu.append(order_button)
174 update_entry(window, entry_id)
175 window.set_app_menu(menu)
180 # Implementation of Base UI interface
182 self.apply_filter_cb(self.level1_filter)
185 def exit(self, event):
187 self.controller.stop()
189 def create_information_dialog(self, title, message):
190 dialog = hildon.Dialog()
191 dialog.set_title(title)
192 label = gtk.Label(message)
193 dialog.vbox.add(label)
194 dialog.vbox.show_all()
198 def create_about_dialog(self):
199 from meabook.version import version
200 dialog = hildon.Dialog()
201 dialog.set_title(_('About'))
202 info_label = gtk.Label()
203 info_label.set_use_markup(True)
204 info_label.set_justify(gtk.JUSTIFY_CENTER)
205 info_label.set_markup("<span foreground='white' size='medium'><b>" \
206 "Meabook</b></span><span foreground='white' size='small'> - " \
207 "Enterprise address book</span>\n<span foreground='white' " \
208 "size='small'>Version %s</span>\n\n\n<span foreground='white'" \
209 "size='small'><b>Developers:</b></span>\n<span foreground=" \
210 "'white' size='small'>Tanya Makova | </span><span foreground=" \
211 "'#299BFC' size='small'>tanyshk@gmail.com</span>\n<span " \
212 "foreground='white' size='small'>Max Usachev | </span><span " \
213 "foreground='#299BFC' size='small'>maxusachev@gmail.com</span>" \
215 dialog.vbox.add(info_label)
216 dialog.vbox.show_all()
220 def create_import_dialog(self):
221 chooser = gobject.new(hildon.FileChooserDialog, \
222 action=gtk.FILE_CHOOSER_ACTION_OPEN)
223 chooser.set_property('show-files', True)
225 path = chooser.get_filename()
229 def create_progress_dialog(self, title=None):
230 self._update_title(title)
232 hildon.hildon_gtk_window_set_progress_indicator(self.window, 1)
235 def create_configuration_dialog(self, controller, config):
236 dialog = ConfigurationDialog(controller, config)
240 # Hildon UI callbacks
241 def show_about_dialog_cb(self, widget):
242 """Shows About Dialog."""
244 self.controller.show_about_dialog()
246 def show_import_dialog_cb(self, widget):
247 """Shows Import Dialog."""
249 if self.controller.show_import_dialog():
250 self.apply_filter_cb(self.level1_filter)
251 self.selector.show_all()
252 hildon.hildon_gtk_window_set_progress_indicator(self.window, 0)
254 def show_settings_dialog_cb(self, widget):
255 """Shows Config dialog."""
257 self.controller.show_configuration_dialog()
259 def apply_filter_cb(self, widget):
260 """Updates toplevel selector with different level items."""
262 if not widget.get_active():
265 self._update_title(' - '.join([_('Meabook'), widget.get_label()]))
266 self.search_entry.hide()
268 if widget == self.level1_filter:
269 self._set_selector_content(self.selector, self.handler, \
270 self.controller.get_all_folders())
271 elif widget == self.level2_filter:
272 self._set_selector_content(self.selector, self.handler, \
273 self.controller.get_all_subfolders())
275 self.search_entry.set_text('')
276 self.search_entry.set_placeholder(_('Enter search text here'))
277 self.search_entry.show()
278 self._set_selector_content(self.selector, self.handler)
280 def select_item_cb(self, widget, column):
282 Emits when changes selector content.
283 Opens new StackableWindow with new content.
286 item_name, internal_name, item_type = \
287 widget.get_model(0)[widget.get_active(0)]
288 if item_type == TYPE_FOLDER:
289 self._show_items_dialog(item_name, self.controller.get_items( \
292 self._show_item_dialog(item_name, internal_name)
294 def search_item_cb(self, widget, event):
295 """Search items from database."""
297 self._set_selector_content(self.selector, self.handler, \
298 self.controller.get_all_files_by_pattern(widget.get_text()))
304 class ConfigurationDialog:
305 """Configuration dialog"""
307 def __init__(self, controller, config):
309 self.controller = controller
312 dialog = hildon.Dialog()
313 dialog.set_title(_('Settings'))
315 button_order = create_button(_('Fields order'), self._update_value( \
316 None, self.config.get_order()))
317 button_order.connect('clicked', self.show_order_settings_cb, dialog)
318 button_fields = create_button(_('Fields to show'), self._update_value( \
319 None, self.config.get_fields()))
320 button_fields.connect('clicked', self.show_fields_settings_cb, dialog)
322 dialog.vbox.pack_start(button_fields, expand=False)
323 dialog.vbox.pack_start(button_order, expand=False)
324 dialog.vbox.show_all()
328 def _update_value(self, widget, fields):
329 """Updates widget title."""
331 value = ', '.join([_(field) for field in fields])
332 if widget is not None:
333 widget.set_value(value)
336 def show_fields_settings_cb(self, widget, parent):
337 """Shows dialog for selecting fields to show."""
339 dialog = hildon.PickerDialog(parent)
340 dialog.set_title(_('Fields to show'))
341 selector = hildon.TouchSelector(text=True)
343 fields = self.controller.get_fields()
346 selector.append_text(_(field))
348 selector.set_column_selection_mode( \
349 hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
350 selector.unselect_all(0)
352 # mark necessary fields
353 fields_to_select = self.config.get_fields()
354 model = selector.get_model(0)
355 for index, field in enumerate(fields):
356 if field in fields_to_select:
357 selector.select_iter(0, model.get_iter(index), False)
359 dialog.set_selector(selector)
360 response = dialog.run()
361 if response == gtk.RESPONSE_OK:
362 model = selector.get_model(0)
363 selected_item_indexes = [index for index in [item[0] for item \
364 in selector.get_selected_rows(0)]]
365 selected_fields = [fields[index] for index in selected_item_indexes]
366 self.config.set_fields(selected_fields)
367 self._update_value(widget, selected_fields)
371 def show_order_settings_cb(self, widget, parent):
372 """Shows dialog for setting fields order."""
375 def show_fields_chooser(widget, parent):
376 """Shows dialog to select field from fields list."""
378 dialog = hildon.PickerDialog(parent)
379 dialog.set_title(_('Fields'))
380 selector = hildon.TouchSelector(text=True)
381 dialog.set_selector(selector)
382 selector.set_column_selection_mode( \
383 hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
385 for field in self.controller.get_fields():
386 selector.append_text(_(field))
388 widget.set_value(selector.get_current_text())
392 dialog = hildon.Dialog()
393 dialog.set_title(_('Fields order'))
394 pannable_area = hildon.PannableArea()
395 pannable_area.set_size_request_policy(hildon.SIZE_REQUEST_CHILDREN)
398 for index, field in enumerate(self.config.get_order()):
399 button = create_button(' '.join([_('Position'), str(index)]), \
401 button.connect('clicked', show_fields_chooser, dialog)
402 vbox.pack_start(button, expand=False)
403 pannable_area.add_with_viewport(vbox)
404 dialog.add_button(_('Done'), gtk.RESPONSE_OK)
405 dialog.vbox.pack_start(pannable_area)
406 dialog.vbox.show_all()
407 response = dialog.run()
408 if response == gtk.RESPONSE_OK:
409 fields_dict = dict([(_(field).decode('utf-8'), field) for field \
410 in self.controller.get_fields()])
411 new_ordered_fields = [fields_dict[button.get_value().decode( \
412 'utf-8')] for button in vbox.get_children()]
413 self.config.set_order(new_ordered_fields)
414 self._update_value(widget, new_ordered_fields)