9 class _NullHildonModule(object):
14 import hildon as _hildon
15 hildon = _hildon # Dumb but gets around pyflakiness
16 except (ImportError, OSError):
17 hildon = _NullHildonModule
20 IS_HILDON_SUPPORTED = hildon is not _NullHildonModule
23 class _NullHildonProgram(object):
25 def add_window(self, window):
29 def _hildon_get_app_class():
33 def _null_get_app_class():
34 return _NullHildonProgram
39 get_app_class = _hildon_get_app_class
40 except AttributeError:
41 get_app_class = _null_get_app_class
44 def _hildon_set_application_title(window, title):
48 def _null_set_application_title(window, title):
49 window.set_title(title)
52 if IS_HILDON_SUPPORTED:
53 set_application_title = _hildon_set_application_title
55 set_application_title = _null_set_application_title
58 def _fremantle_hildonize_window(app, window):
60 newWindow = hildon.StackableWindow()
61 oldWindow.get_child().reparent(newWindow)
62 app.add_window(newWindow)
66 def _hildon_hildonize_window(app, window):
68 newWindow = hildon.Window()
69 oldWindow.get_child().reparent(newWindow)
70 app.add_window(newWindow)
74 def _null_hildonize_window(app, window):
79 hildon.StackableWindow
80 hildonize_window = _fremantle_hildonize_window
81 except AttributeError:
84 hildonize_window = _hildon_hildonize_window
85 except AttributeError:
86 hildonize_window = _null_hildonize_window
89 def _fremantle_hildonize_menu(window, gtkMenu, buttons):
90 appMenu = hildon.AppMenu()
91 for button in buttons:
92 appMenu.append(button)
93 window.set_app_menu(appMenu)
94 gtkMenu.get_parent().remove(gtkMenu)
98 def _hildon_hildonize_menu(window, gtkMenu, ignoredButtons):
99 hildonMenu = gtk.Menu()
100 for child in gtkMenu.get_children():
101 child.reparent(hildonMenu)
102 window.set_menu(hildonMenu)
107 def _null_hildonize_menu(window, gtkMenu, ignoredButtons):
113 GTK_MENU_USED = False
114 IS_FREMANTLE_SUPPORTED = True
115 hildonize_menu = _fremantle_hildonize_menu
116 except AttributeError:
118 IS_FREMANTLE_SUPPORTED = False
119 if IS_HILDON_SUPPORTED:
120 hildonize_menu = _hildon_hildonize_menu
122 hildonize_menu = _null_hildonize_menu
125 def _hildon_set_button_auto_selectable(button):
126 button.set_theme_size(hildon.HILDON_SIZE_AUTO_HEIGHT)
129 def _null_set_button_auto_selectable(button):
134 hildon.HILDON_SIZE_AUTO_HEIGHT
135 gtk.Button.set_theme_size
136 set_button_auto_selectable = _hildon_set_button_auto_selectable
137 except AttributeError:
138 set_button_auto_selectable = _null_set_button_auto_selectable
141 def _hildon_set_button_finger_selectable(button):
142 button.set_theme_size(hildon.HILDON_SIZE_FINGER_HEIGHT)
145 def _null_set_button_finger_selectable(button):
150 hildon.HILDON_SIZE_FINGER_HEIGHT
151 gtk.Button.set_theme_size
152 set_button_finger_selectable = _hildon_set_button_finger_selectable
153 except AttributeError:
154 set_button_finger_selectable = _null_set_button_finger_selectable
157 def _hildon_set_button_thumb_selectable(button):
158 button.set_theme_size(hildon.HILDON_SIZE_THUMB_HEIGHT)
161 def _null_set_button_thumb_selectable(button):
166 hildon.HILDON_SIZE_THUMB_HEIGHT
167 gtk.Button.set_theme_size
168 set_button_thumb_selectable = _hildon_set_button_thumb_selectable
169 except AttributeError:
170 set_button_thumb_selectable = _null_set_button_thumb_selectable
173 def _hildon_set_cell_thumb_selectable(renderer):
174 renderer.set_property("scale", 1.5)
177 def _null_set_cell_thumb_selectable(renderer):
181 if IS_HILDON_SUPPORTED:
182 set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
184 set_cell_thumb_selectable = _null_set_cell_thumb_selectable
187 def _hildon_set_pix_cell_thumb_selectable(renderer):
188 renderer.set_property("stock-size", 48)
191 def _null_set_pix_cell_thumb_selectable(renderer):
195 if IS_HILDON_SUPPORTED:
196 set_pix_cell_thumb_selectable = _hildon_set_pix_cell_thumb_selectable
198 set_pix_cell_thumb_selectable = _null_set_pix_cell_thumb_selectable
201 def _fremantle_show_information_banner(parent, message):
202 hildon.hildon_banner_show_information(parent, "", message)
205 def _hildon_show_information_banner(parent, message):
206 hildon.hildon_banner_show_information(parent, None, message)
209 def _null_show_information_banner(parent, message):
213 if IS_FREMANTLE_SUPPORTED:
214 show_information_banner = _fremantle_show_information_banner
217 hildon.hildon_banner_show_information
218 show_information_banner = _hildon_show_information_banner
219 except AttributeError:
220 show_information_banner = _null_show_information_banner
223 def _fremantle_show_busy_banner_start(parent, message):
224 hildon.hildon_gtk_window_set_progress_indicator(parent, True)
228 def _fremantle_show_busy_banner_end(banner):
229 hildon.hildon_gtk_window_set_progress_indicator(banner, False)
232 def _hildon_show_busy_banner_start(parent, message):
233 return hildon.hildon_banner_show_animation(parent, None, message)
236 def _hildon_show_busy_banner_end(banner):
240 def _null_show_busy_banner_start(parent, message):
244 def _null_show_busy_banner_end(banner):
245 assert banner is None
249 hildon.hildon_gtk_window_set_progress_indicator
250 show_busy_banner_start = _fremantle_show_busy_banner_start
251 show_busy_banner_end = _fremantle_show_busy_banner_end
252 except AttributeError:
254 hildon.hildon_banner_show_animation
255 show_busy_banner_start = _hildon_show_busy_banner_start
256 show_busy_banner_end = _hildon_show_busy_banner_end
257 except AttributeError:
258 show_busy_banner_start = _null_show_busy_banner_start
259 show_busy_banner_end = _null_show_busy_banner_end
262 def _hildon_hildonize_text_entry(textEntry):
263 textEntry.set_property('hildon-input-mode', 7)
266 def _null_hildonize_text_entry(textEntry):
270 if IS_HILDON_SUPPORTED:
271 hildonize_text_entry = _hildon_hildonize_text_entry
273 hildonize_text_entry = _null_hildonize_text_entry
276 def _hildon_mark_window_rotatable(window):
277 # gtk documentation is unclear whether this does a "=" or a "|="
278 window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
281 def _null_mark_window_rotatable(window):
286 hildon.HILDON_PORTRAIT_MODE_SUPPORT
287 mark_window_rotatable = _hildon_mark_window_rotatable
288 except AttributeError:
289 mark_window_rotatable = _null_mark_window_rotatable
292 def _hildon_window_to_portrait(window):
293 # gtk documentation is unclear whether this does a "=" or a "|="
294 window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
297 def _hildon_window_to_landscape(window):
298 # gtk documentation is unclear whether this does a "=" or a "&= ~"
299 window.unset_flags(hildon.HILDON_PORTRAIT_MODE_REQUEST)
302 def _null_window_to_portrait(window):
306 def _null_window_to_landscape(window):
311 hildon.HILDON_PORTRAIT_MODE_SUPPORT
312 hildon.HILDON_PORTRAIT_MODE_REQUEST
314 window_to_portrait = _hildon_window_to_portrait
315 window_to_landscape = _hildon_window_to_landscape
316 except AttributeError:
317 window_to_portrait = _null_window_to_portrait
318 window_to_landscape = _null_window_to_landscape
321 def get_device_orientation():
322 bus = dbus.SystemBus()
324 rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
325 mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
326 orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
327 except dbus.exception.DBusException:
328 # catching for documentation purposes that when a system doesn't
329 # support this, this is what to expect
332 if orientation == "":
333 return gtk.ORIENTATION_HORIZONTAL
334 elif orientation == "":
335 return gtk.ORIENTATION_VERTICAL
337 raise RuntimeError("Unknown orientation: %s" % orientation)
340 def _hildon_hildonize_password_entry(textEntry):
341 textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
344 def _null_hildonize_password_entry(textEntry):
348 if IS_HILDON_SUPPORTED:
349 hildonize_password_entry = _hildon_hildonize_password_entry
351 hildonize_password_entry = _null_hildonize_password_entry
354 def _hildon_hildonize_combo_entry(comboEntry):
355 comboEntry.set_property('hildon-input-mode', 1 << 4)
358 def _null_hildonize_combo_entry(textEntry):
362 if IS_HILDON_SUPPORTED:
363 hildonize_combo_entry = _hildon_hildonize_combo_entry
365 hildonize_combo_entry = _null_hildonize_combo_entry
368 def _fremantle_hildonize_scrollwindow(scrolledWindow):
369 pannableWindow = hildon.PannableArea()
371 child = scrolledWindow.get_child()
372 scrolledWindow.remove(child)
373 pannableWindow.add(child)
375 parent = scrolledWindow.get_parent()
376 if parent is not None:
377 parent.remove(scrolledWindow)
378 parent.add(pannableWindow)
380 return pannableWindow
383 def _hildon_hildonize_scrollwindow(scrolledWindow):
384 hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
385 return scrolledWindow
388 def _null_hildonize_scrollwindow(scrolledWindow):
389 return scrolledWindow
394 hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
395 hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
396 except AttributeError:
398 hildon.hildon_helper_set_thumb_scrollbar
399 hildonize_scrollwindow = _hildon_hildonize_scrollwindow
400 hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
401 except AttributeError:
402 hildonize_scrollwindow = _null_hildonize_scrollwindow
403 hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
406 def _hildon_request_number(parent, title, range, default):
407 spinner = hildon.NumberEditor(*range)
408 spinner.set_value(default)
413 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
414 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
416 dialog.set_default_response(gtk.RESPONSE_CANCEL)
417 dialog.get_child().add(spinner)
421 response = dialog.run()
423 if response == gtk.RESPONSE_OK:
424 return spinner.get_value()
425 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
426 raise RuntimeError("User cancelled request")
428 raise RuntimeError("Unrecognized response %r", response)
434 def _null_request_number(parent, title, range, default):
435 adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
436 spinner = gtk.SpinButton(adjustment, 0, 0)
437 spinner.set_wrap(False)
442 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
443 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
445 dialog.set_default_response(gtk.RESPONSE_CANCEL)
446 dialog.get_child().add(spinner)
450 response = dialog.run()
452 if response == gtk.RESPONSE_OK:
453 return spinner.get_value_as_int()
454 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
455 raise RuntimeError("User cancelled request")
457 raise RuntimeError("Unrecognized response %r", response)
464 hildon.NumberEditor # TODO deprecated in fremantle
465 request_number = _hildon_request_number
466 except AttributeError:
467 request_number = _null_request_number
470 def _hildon_touch_selector(parent, title, items, defaultIndex):
471 model = gtk.ListStore(gobject.TYPE_STRING)
473 model.append((item, ))
475 selector = hildon.TouchSelector()
476 selector.append_text_column(model, True)
477 selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
478 selector.set_active(0, defaultIndex)
480 dialog = hildon.PickerDialog(parent)
481 dialog.set_selector(selector)
485 response = dialog.run()
487 if response == gtk.RESPONSE_OK:
488 return selector.get_active(0)
489 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
490 raise RuntimeError("User cancelled request")
492 raise RuntimeError("Unrecognized response %r", response)
498 def _on_null_touch_selector_activated(treeView, path, column, dialog, pathData):
499 dialog.response(gtk.RESPONSE_OK)
503 def _null_touch_selector(parent, title, items, defaultIndex = -1):
504 parentSize = parent.get_size()
506 model = gtk.ListStore(gobject.TYPE_STRING)
508 model.append((item, ))
510 cell = gtk.CellRendererText()
511 set_cell_thumb_selectable(cell)
512 column = gtk.TreeViewColumn(title)
513 column.pack_start(cell, expand=True)
514 column.add_attribute(cell, "text", 0)
516 treeView = gtk.TreeView()
517 treeView.set_model(model)
518 treeView.append_column(column)
519 selection = treeView.get_selection()
520 selection.set_mode(gtk.SELECTION_SINGLE)
522 selection.select_path((defaultIndex, ))
524 scrolledWin = gtk.ScrolledWindow()
525 scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
526 scrolledWin.add(treeView)
531 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
532 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
534 dialog.set_default_response(gtk.RESPONSE_CANCEL)
535 dialog.get_child().add(scrolledWin)
536 dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
538 scrolledWin = hildonize_scrollwindow(scrolledWin)
540 treeView.connect("row-activated", _on_null_touch_selector_activated, dialog, pathData)
544 response = dialog.run()
546 if response == gtk.RESPONSE_OK:
547 if pathData[0] is None:
548 raise RuntimeError("No selection made")
549 return pathData[0][0]
550 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
551 raise RuntimeError("User cancelled request")
553 raise RuntimeError("Unrecognized response %r", response)
562 touch_selector = _hildon_touch_selector
563 except AttributeError:
564 touch_selector = _null_touch_selector
567 def _hildon_touch_selector_entry(parent, title, items, defaultItem):
568 # Got a segfault when using append_text_column with TouchSelectorEntry, so using this way
570 selector = hildon.TouchSelectorEntry(text=True)
572 selector = hildon.hildon_touch_selector_entry_new_text()
574 for i, item in enumerate(items):
575 selector.append_text(item)
576 if item == defaultItem:
579 dialog = hildon.PickerDialog(parent)
580 dialog.set_selector(selector)
583 selector.set_active(0, defaultIndex)
585 selector.get_entry().set_text(defaultItem)
589 response = dialog.run()
593 if response == gtk.RESPONSE_OK:
594 return selector.get_entry().get_text()
595 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
596 raise RuntimeError("User cancelled request")
598 raise RuntimeError("Unrecognized response %r", response)
601 def _on_null_touch_selector_entry_entry_changed(entry, result, selection, defaultIndex):
602 custom = entry.get_text().strip()
605 selection.unselect_all()
608 selection.select_path((defaultIndex, ))
611 def _on_null_touch_selector_entry_entry_activated(customEntry, dialog, result):
612 dialog.response(gtk.RESPONSE_OK)
613 result[0] = customEntry.get_text()
616 def _on_null_touch_selector_entry_tree_activated(treeView, path, column, dialog, result):
617 dialog.response(gtk.RESPONSE_OK)
618 model = treeView.get_model()
619 itr = model.get_iter(path)
621 result[0] = model.get_value(itr, 0)
624 def _null_touch_selector_entry(parent, title, items, defaultItem):
625 parentSize = parent.get_size()
627 model = gtk.ListStore(gobject.TYPE_STRING)
629 for i, item in enumerate(items):
630 model.append((item, ))
631 if item == defaultItem:
634 cell = gtk.CellRendererText()
635 set_cell_thumb_selectable(cell)
636 column = gtk.TreeViewColumn(title)
637 column.pack_start(cell, expand=True)
638 column.add_attribute(cell, "text", 0)
640 treeView = gtk.TreeView()
641 treeView.set_model(model)
642 treeView.append_column(column)
643 selection = treeView.get_selection()
644 selection.set_mode(gtk.SELECTION_SINGLE)
646 scrolledWin = gtk.ScrolledWindow()
647 scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
648 scrolledWin.add(treeView)
650 customEntry = gtk.Entry()
653 layout.pack_start(customEntry, expand=False)
654 layout.pack_start(scrolledWin)
659 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
660 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
662 dialog.set_default_response(gtk.RESPONSE_CANCEL)
663 dialog.get_child().add(layout)
664 dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
666 scrolledWin = hildonize_scrollwindow(scrolledWin)
670 selection.select_path((defaultIndex, ))
671 result[0] = defaultItem
673 customEntry.set_text(defaultItem)
675 customEntry.connect("activate", _on_null_touch_selector_entry_entry_activated, dialog, result)
676 customEntry.connect("changed", _on_null_touch_selector_entry_entry_changed, result, selection, defaultIndex)
677 treeView.connect("row-activated", _on_null_touch_selector_entry_tree_activated, dialog, result)
681 response = dialog.run()
683 if response == gtk.RESPONSE_OK:
684 _, itr = selection.get_selected()
686 return model.get_value(itr, 0)
688 enteredText = customEntry.get_text().strip()
691 elif result[0] is not None:
694 raise RuntimeError("No selection made")
695 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
696 raise RuntimeError("User cancelled request")
698 raise RuntimeError("Unrecognized response %r", response)
706 hildon.TouchSelectorEntry
707 touch_selector_entry = _hildon_touch_selector_entry
708 except AttributeError:
709 touch_selector_entry = _null_touch_selector_entry
712 if __name__ == "__main__":
713 app = get_app_class()()
715 label = gtk.Label("Hello World from a Label!")
719 win = hildonize_window(app, win)
721 print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)
723 print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "C")
724 print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "Blah")
729 (name, value) for (name, value) in locals().iteritems()
730 if not name.startswith("_")
732 pprint.pprint(goodLocals)
735 show_information_banner(win, "Hello World")
739 banner = show_busy_banner_start(win, "Hello World")
741 show_busy_banner_end(banner)