Prepping for some fixes and removing dead code
[gc-dialer] / src / hildonize.py
1 #!/usr/bin/env python
2
3
4 import gobject
5 import gtk
6 import dbus
7
8
9 class _NullHildonModule(object):
10         pass
11
12
13 try:
14         import hildon as _hildon
15         hildon  = _hildon # Dumb but gets around pyflakiness
16 except (ImportError, OSError):
17         hildon = _NullHildonModule
18
19
20 IS_HILDON_SUPPORTED = hildon is not _NullHildonModule
21
22
23 class _NullHildonProgram(object):
24
25         def add_window(self, window):
26                 pass
27
28
29 def _hildon_get_app_class():
30         return hildon.Program
31
32
33 def _null_get_app_class():
34         return _NullHildonProgram
35
36
37 try:
38         hildon.Program
39         get_app_class = _hildon_get_app_class
40 except AttributeError:
41         get_app_class = _null_get_app_class
42
43
44 def _hildon_set_application_title(window, title):
45         pass
46
47
48 def _null_set_application_title(window, title):
49         window.set_title(title)
50
51
52 if IS_HILDON_SUPPORTED:
53         set_application_title = _hildon_set_application_title
54 else:
55         set_application_title = _null_set_application_title
56
57
58 def _fremantle_hildonize_window(app, window):
59         oldWindow = window
60         newWindow = hildon.StackableWindow()
61         oldWindow.get_child().reparent(newWindow)
62         app.add_window(newWindow)
63         return newWindow
64
65
66 def _hildon_hildonize_window(app, window):
67         oldWindow = window
68         newWindow = hildon.Window()
69         oldWindow.get_child().reparent(newWindow)
70         app.add_window(newWindow)
71         return newWindow
72
73
74 def _null_hildonize_window(app, window):
75         return window
76
77
78 try:
79         hildon.StackableWindow
80         hildonize_window = _fremantle_hildonize_window
81 except AttributeError:
82         try:
83                 hildon.Window
84                 hildonize_window = _hildon_hildonize_window
85         except AttributeError:
86                 hildonize_window = _null_hildonize_window
87
88
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)
95         return appMenu
96
97
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)
103         gtkMenu.destroy()
104         return hildonMenu
105
106
107 def _null_hildonize_menu(window, gtkMenu, ignoredButtons):
108         return gtkMenu
109
110
111 try:
112         hildon.AppMenu
113         GTK_MENU_USED = False
114         IS_FREMANTLE_SUPPORTED = True
115         hildonize_menu = _fremantle_hildonize_menu
116 except AttributeError:
117         GTK_MENU_USED = True
118         IS_FREMANTLE_SUPPORTED = False
119         if IS_HILDON_SUPPORTED:
120                 hildonize_menu = _hildon_hildonize_menu
121         else:
122                 hildonize_menu = _null_hildonize_menu
123
124
125 def _hildon_set_cell_thumb_selectable(renderer):
126         renderer.set_property("scale", 1.5)
127
128
129 def _null_set_cell_thumb_selectable(renderer):
130         pass
131
132
133 if IS_HILDON_SUPPORTED:
134         set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
135 else:
136         set_cell_thumb_selectable = _null_set_cell_thumb_selectable
137
138
139 def _fremantle_show_information_banner(parent, message):
140         hildon.hildon_banner_show_information(parent, "", message)
141
142
143 def _hildon_show_information_banner(parent, message):
144         hildon.hildon_banner_show_information(parent, None, message)
145
146
147 def _null_show_information_banner(parent, message):
148         pass
149
150
151 if IS_FREMANTLE_SUPPORTED:
152         show_information_banner = _fremantle_show_information_banner
153 else:
154         try:
155                 hildon.hildon_banner_show_information
156                 show_information_banner = _hildon_show_information_banner
157         except AttributeError:
158                 show_information_banner = _null_show_information_banner
159
160
161 def _fremantle_show_busy_banner_start(parent, message):
162         hildon.hildon_gtk_window_set_progress_indicator(parent, True)
163         return parent
164
165
166 def _fremantle_show_busy_banner_end(banner):
167         hildon.hildon_gtk_window_set_progress_indicator(banner, False)
168
169
170 def _hildon_show_busy_banner_start(parent, message):
171         return hildon.hildon_banner_show_animation(parent, None, message)
172
173
174 def _hildon_show_busy_banner_end(banner):
175         banner.destroy()
176
177
178 def _null_show_busy_banner_start(parent, message):
179         return None
180
181
182 def _null_show_busy_banner_end(banner):
183         assert banner is None
184
185
186 try:
187         hildon.hildon_gtk_window_set_progress_indicator
188         show_busy_banner_start = _fremantle_show_busy_banner_start
189         show_busy_banner_end = _fremantle_show_busy_banner_end
190 except AttributeError:
191         try:
192                 hildon.hildon_banner_show_animation
193                 show_busy_banner_start = _hildon_show_busy_banner_start
194                 show_busy_banner_end = _hildon_show_busy_banner_end
195         except AttributeError:
196                 show_busy_banner_start = _null_show_busy_banner_start
197                 show_busy_banner_end = _null_show_busy_banner_end
198
199
200 def _hildon_hildonize_text_entry(textEntry):
201         textEntry.set_property('hildon-input-mode', 7)
202
203
204 def _null_hildonize_text_entry(textEntry):
205         pass
206
207
208 if IS_HILDON_SUPPORTED:
209         hildonize_text_entry = _hildon_hildonize_text_entry
210 else:
211         hildonize_text_entry = _null_hildonize_text_entry
212
213
214 def _hildon_mark_window_rotatable(window):
215         # gtk documentation is unclear whether this does a "=" or a "|="
216         window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
217
218
219 def _null_mark_window_rotatable(window):
220         pass
221
222
223 try:
224         hildon.HILDON_PORTRAIT_MODE_SUPPORT
225         mark_window_rotatable = _hildon_mark_window_rotatable
226 except AttributeError:
227         mark_window_rotatable = _null_mark_window_rotatable
228
229
230 def _hildon_window_to_portrait(window):
231         # gtk documentation is unclear whether this does a "=" or a "|="
232         window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
233
234
235 def _hildon_window_to_landscape(window):
236         # gtk documentation is unclear whether this does a "=" or a "&= ~"
237         window.unset_flags(hildon.HILDON_PORTRAIT_MODE_REQUEST)
238
239
240 def _null_window_to_portrait(window):
241         pass
242
243
244 def _null_window_to_landscape(window):
245         pass
246
247
248 try:
249         hildon.HILDON_PORTRAIT_MODE_SUPPORT
250         hildon.HILDON_PORTRAIT_MODE_REQUEST
251
252         window_to_portrait = _hildon_window_to_portrait
253         window_to_landscape = _hildon_window_to_landscape
254 except AttributeError:
255         window_to_portrait = _null_window_to_portrait
256         window_to_landscape = _null_window_to_landscape
257
258
259 def get_device_orientation():
260         bus = dbus.SystemBus()
261         try:
262                 rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
263                 mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
264                 orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
265         except dbus.exception.DBusException:
266                 # catching for documentation purposes that when a system doesn't
267                 # support this, this is what to expect
268                 raise
269
270         if orientation == "":
271                 return gtk.ORIENTATION_HORIZONTAL
272         elif orientation == "":
273                 return gtk.ORIENTATION_VERTICAL
274         else:
275                 raise RuntimeError("Unknown orientation: %s" % orientation)
276
277
278 def _hildon_hildonize_password_entry(textEntry):
279         textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
280
281
282 def _null_hildonize_password_entry(textEntry):
283         pass
284
285
286 if IS_HILDON_SUPPORTED:
287         hildonize_password_entry = _hildon_hildonize_password_entry
288 else:
289         hildonize_password_entry = _null_hildonize_password_entry
290
291
292 def _hildon_hildonize_combo_entry(comboEntry):
293         comboEntry.set_property('hildon-input-mode', 1 << 4)
294
295
296 def _null_hildonize_combo_entry(textEntry):
297         pass
298
299
300 if IS_HILDON_SUPPORTED:
301         hildonize_combo_entry = _hildon_hildonize_combo_entry
302 else:
303         hildonize_combo_entry = _null_hildonize_combo_entry
304
305
306 def _fremantle_hildonize_scrollwindow(scrolledWindow):
307         pannableWindow = hildon.PannableArea()
308
309         child = scrolledWindow.get_child()
310         scrolledWindow.remove(child)
311         pannableWindow.add(child)
312
313         parent = scrolledWindow.get_parent()
314         parent.remove(scrolledWindow)
315         parent.add(pannableWindow)
316
317         return pannableWindow
318
319
320 def _hildon_hildonize_scrollwindow(scrolledWindow):
321         hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
322         return scrolledWindow
323
324
325 def _null_hildonize_scrollwindow(scrolledWindow):
326         return scrolledWindow
327
328
329 try:
330         hildon.PannableArea
331         hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
332         hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
333 except AttributeError:
334         try:
335                 hildon.hildon_helper_set_thumb_scrollbar
336                 hildonize_scrollwindow = _hildon_hildonize_scrollwindow
337                 hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
338         except AttributeError:
339                 hildonize_scrollwindow = _null_hildonize_scrollwindow
340                 hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
341
342
343 def _hildon_request_number(parent, title, range, default):
344         spinner = hildon.NumberEditor(*range)
345         spinner.set_value(default)
346
347         dialog = gtk.Dialog(
348                 title,
349                 parent,
350                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
351                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
352         )
353         dialog.set_default_response(gtk.RESPONSE_CANCEL)
354         dialog.get_child().add(spinner)
355
356         try:
357                 dialog.show_all()
358                 response = dialog.run()
359         finally:
360                 dialog.hide()
361
362         if response == gtk.RESPONSE_OK:
363                 return spinner.get_value()
364         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
365                 raise RuntimeError("User cancelled request")
366         else:
367                 raise RuntimeError("Unrecognized response %r", response)
368
369
370 def _null_request_number(parent, title, range, default):
371         adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
372         spinner = gtk.SpinButton(adjustment, 0, 0)
373         spinner.set_wrap(False)
374
375         dialog = gtk.Dialog(
376                 title,
377                 parent,
378                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
379                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
380         )
381         dialog.set_default_response(gtk.RESPONSE_CANCEL)
382         dialog.get_child().add(spinner)
383
384         try:
385                 dialog.show_all()
386                 response = dialog.run()
387         finally:
388                 dialog.hide()
389
390         if response == gtk.RESPONSE_OK:
391                 return spinner.get_value_as_int()
392         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
393                 raise RuntimeError("User cancelled request")
394         else:
395                 raise RuntimeError("Unrecognized response %r", response)
396
397
398 try:
399         hildon.NumberEditor # TODO deprecated in fremantle
400         request_number = _hildon_request_number
401 except AttributeError:
402         request_number = _null_request_number
403
404
405 def _hildon_touch_selector(parent, title, items, defaultIndex):
406         model = gtk.ListStore(gobject.TYPE_STRING)
407         for item in items:
408                 model.append((item, ))
409
410         selector = hildon.TouchSelector()
411         selector.append_text_column(model, True)
412         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
413         selector.set_active(0, defaultIndex)
414
415         dialog = hildon.PickerDialog(parent)
416         dialog.set_selector(selector)
417
418         try:
419                 dialog.show_all()
420                 response = dialog.run()
421         finally:
422                 dialog.hide()
423
424         if response == gtk.RESPONSE_OK:
425                 return selector.get_active(0)
426         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
427                 raise RuntimeError("User cancelled request")
428         else:
429                 raise RuntimeError("Unrecognized response %r", response)
430
431
432 def _on_null_touch_selector_activated(treeView, path, column, dialog):
433         dialog.response(gtk.RESPONSE_OK)
434
435
436 def _null_touch_selector(parent, title, items, defaultIndex = -1):
437         model = gtk.ListStore(gobject.TYPE_STRING)
438         for item in items:
439                 model.append((item, ))
440
441         cell = gtk.CellRendererText()
442         set_cell_thumb_selectable(cell)
443         column = gtk.TreeViewColumn(title)
444         column .pack_start(cell, expand=True)
445         column.add_attribute(cell, "text", 0)
446
447         treeView = gtk.TreeView()
448         treeView.set_model(model)
449         treeView.append_column(column)
450         selection = treeView.get_selection()
451         selection.set_mode(gtk.SELECTION_SINGLE)
452         if 0 < defaultIndex:
453                 selection.select_path((defaultIndex, ))
454
455         scrolledWin = gtk.ScrolledWindow()
456         scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
457         scrolledWin.add(treeView)
458         hildonize_scrollwindow(scrolledWin)
459
460         dialog = gtk.Dialog(
461                 title,
462                 parent,
463                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
464                 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
465         )
466         dialog.set_default_response(gtk.RESPONSE_CANCEL)
467         dialog.get_child().add(scrolledWin)
468         parentSize = parent.get_size()
469         dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
470         treeView.connect("row-activated", _on_null_touch_selector_activated, dialog)
471
472         try:
473                 dialog.show_all()
474                 response = dialog.run()
475         finally:
476                 dialog.hide()
477
478         if response == gtk.RESPONSE_OK:
479                 model, itr = selection.get_selected()
480                 if itr is None:
481                         raise RuntimeError("No selection made")
482                 return model.get_path(itr)[0]
483         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
484                 raise RuntimeError("User cancelled request")
485         else:
486                 raise RuntimeError("Unrecognized response %r", response)
487
488
489 try:
490         hildon.PickerDialog
491         hildon.TouchSelector
492         touch_selector = _hildon_touch_selector
493 except AttributeError:
494         touch_selector = _null_touch_selector
495
496
497 def _hildon_touch_selector_entry(parent, title, items, defaultItem):
498         # Got a segfault when using append_text_column with TouchSelectorEntry, so using this way
499         selector = hildon.hildon_touch_selector_entry_new_text()
500         defaultIndex = -1
501         for i, item in enumerate(items):
502                 selector.append_text(item)
503                 if item == defaultItem:
504                         defaultIndex = i
505
506         dialog = hildon.PickerDialog(parent)
507         dialog.set_selector(selector)
508
509         if 0 < defaultIndex:
510                 selector.set_active(0, defaultIndex)
511         else:
512                 selector.get_entry().set_text(defaultItem)
513
514         try:
515                 dialog.show_all()
516                 response = dialog.run()
517         finally:
518                 dialog.hide()
519
520         if response == gtk.RESPONSE_OK:
521                 return selector.get_entry().get_text()
522         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
523                 raise RuntimeError("User cancelled request")
524         else:
525                 raise RuntimeError("Unrecognized response %r", response)
526
527
528 def _on_null_touch_selector_entry_entry_activated(entry, dialog, customEntry, result):
529         dialog.response(gtk.RESPONSE_OK)
530         result.append(customEntry.get_text())
531
532
533 def _on_null_touch_selector_entry_tree_activated(treeView, path, column, dialog, selection, result):
534         dialog.response(gtk.RESPONSE_OK)
535         model, itr = selection.get_selected()
536         if itr is not None:
537                 result.append(model.get_value(itr, 0))
538
539
540 def _null_touch_selector_entry(parent, title, items, defaultItem):
541         model = gtk.ListStore(gobject.TYPE_STRING)
542         defaultIndex = -1
543         for i, item in enumerate(items):
544                 model.append((item, ))
545                 if item == defaultItem:
546                         defaultIndex = i
547
548         cell = gtk.CellRendererText()
549         set_cell_thumb_selectable(cell)
550         column = gtk.TreeViewColumn(title)
551         column .pack_start(cell, expand=True)
552         column.add_attribute(cell, "text", 0)
553
554         treeView = gtk.TreeView()
555         treeView.set_model(model)
556         treeView.append_column(column)
557         selection = treeView.get_selection()
558         selection.set_mode(gtk.SELECTION_SINGLE)
559
560         scrolledWin = gtk.ScrolledWindow()
561         scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
562         scrolledWin.add(treeView)
563         hildonize_scrollwindow(scrolledWin)
564
565         customEntry = gtk.Entry()
566
567         layout = gtk.VBox()
568         layout.pack_start(customEntry, expand=False)
569         layout.pack_start(scrolledWin)
570
571         dialog = gtk.Dialog(
572                 title,
573                 parent,
574                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
575                 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
576         )
577         dialog.set_default_response(gtk.RESPONSE_CANCEL)
578         dialog.get_child().add(layout)
579         parentSize = parent.get_size()
580         dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
581
582         if 0 < defaultIndex:
583                 selection.select_path((defaultIndex, ))
584         else:
585                 customEntry.set_text(defaultItem)
586         result = []
587         customEntry.connect("activate", _on_null_touch_selector_entry_entry_activated, dialog, customEntry, result)
588         treeView.connect("row-activated", _on_null_touch_selector_entry_tree_activated, dialog, selection, result)
589
590         try:
591                 dialog.show_all()
592                 response = dialog.run()
593         finally:
594                 dialog.hide()
595
596         if response == gtk.RESPONSE_OK:
597                 model, itr = selection.get_selected()
598                 if len(result) != 1:
599                         raise RuntimeError("No selection made")
600                 else:
601                         return result[0]
602         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
603                 raise RuntimeError("User cancelled request")
604         else:
605                 raise RuntimeError("Unrecognized response %r", response)
606
607
608 try:
609         hildon.PickerDialog
610         hildon.TouchSelectorEntry
611         touch_selector_entry = _hildon_touch_selector_entry
612 except AttributeError:
613         touch_selector_entry = _null_touch_selector_entry
614
615
616 if __name__ == "__main__":
617         app = get_app_class()()
618
619         label = gtk.Label("Hello World from a Label!")
620
621         win = gtk.Window()
622         win.add(label)
623         win = hildonize_window(app, win)
624         if False:
625                 print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)
626         if True:
627                 print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "C")
628                 print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "Blah")
629         if False:
630                 import pprint
631                 name, value = "", ""
632                 goodLocals = [
633                         (name, value) for (name, value) in locals().iteritems()
634                         if not name.startswith("_")
635                 ]
636                 pprint.pprint(goodLocals)
637         if False:
638                 import time
639                 show_information_banner(win, "Hello World")
640                 time.sleep(5)
641         if False:
642                 import time
643                 banner = show_busy_banner_start(win, "Hello World")
644                 time.sleep(5)
645                 show_busy_banner_end(banner)