Switching to a touch selector for the addressbook selector
[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         hildonize_menu = _fremantle_hildonize_menu
115 except AttributeError:
116         GTK_MENU_USED = True
117         if IS_HILDON_SUPPORTED:
118                 hildonize_menu = _hildon_hildonize_menu
119         else:
120                 hildonize_menu = _null_hildonize_menu
121
122
123 def _hildon_set_cell_thumb_selectable(renderer):
124         renderer.set_property("scale", 1.5)
125
126
127 def _null_set_cell_thumb_selectable(renderer):
128         pass
129
130
131 if IS_HILDON_SUPPORTED:
132         set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
133 else:
134         set_cell_thumb_selectable = _null_set_cell_thumb_selectable
135
136
137 def _hildon_hildonize_text_entry(textEntry):
138         textEntry.set_property('hildon-input-mode', 7)
139
140
141 def _null_hildonize_text_entry(textEntry):
142         pass
143
144
145 if IS_HILDON_SUPPORTED:
146         hildonize_text_entry = _hildon_hildonize_text_entry
147 else:
148         hildonize_text_entry = _null_hildonize_text_entry
149
150
151 def _hildon_mark_window_rotatable(window):
152         # gtk documentation is unclear whether this does a "=" or a "|="
153         window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
154
155
156 def _null_mark_window_rotatable(window):
157         pass
158
159
160 try:
161         hildon.HILDON_PORTRAIT_MODE_SUPPORT
162         mark_window_rotatable = _hildon_mark_window_rotatable
163 except AttributeError:
164         mark_window_rotatable = _null_mark_window_rotatable
165
166
167 def _hildon_window_to_portrait(window):
168         # gtk documentation is unclear whether this does a "=" or a "|="
169         window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
170
171
172 def _hildon_window_to_landscape(window):
173         # gtk documentation is unclear whether this does a "=" or a "&= ~"
174         window.unset_flags(hildon.HILDON_PORTRAIT_MODE_REQUEST)
175
176
177 def _null_window_to_portrait(window):
178         pass
179
180
181 def _null_window_to_landscape(window):
182         pass
183
184
185 try:
186         hildon.HILDON_PORTRAIT_MODE_SUPPORT
187         hildon.HILDON_PORTRAIT_MODE_REQUEST
188
189         window_to_portrait = _hildon_window_to_portrait
190         window_to_landscape = _hildon_window_to_landscape
191 except AttributeError:
192         window_to_portrait = _null_window_to_portrait
193         window_to_landscape = _null_window_to_landscape
194
195
196 def get_device_orientation():
197         bus = dbus.SystemBus()
198         try:
199                 rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
200                 mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
201                 orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
202         except dbus.exception.DBusException:
203                 # catching for documentation purposes that when a system doesn't
204                 # support this, this is what to expect
205                 raise
206
207         if orientation == "":
208                 return gtk.ORIENTATION_HORIZONTAL
209         elif orientation == "":
210                 return gtk.ORIENTATION_VERTICAL
211         else:
212                 raise RuntimeError("Unknown orientation: %s" % orientation)
213
214
215 def _hildon_hildonize_password_entry(textEntry):
216         textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
217
218
219 def _null_hildonize_password_entry(textEntry):
220         pass
221
222
223 if IS_HILDON_SUPPORTED:
224         hildonize_password_entry = _hildon_hildonize_password_entry
225 else:
226         hildonize_password_entry = _null_hildonize_password_entry
227
228
229 def _hildon_hildonize_combo_entry(comboEntry):
230         comboEntry.set_property('hildon-input-mode', 1 << 4)
231
232
233 def _null_hildonize_combo_entry(textEntry):
234         pass
235
236
237 if IS_HILDON_SUPPORTED:
238         hildonize_combo_entry = _hildon_hildonize_combo_entry
239 else:
240         hildonize_combo_entry = _null_hildonize_combo_entry
241
242
243 def _fremantle_hildonize_scrollwindow(scrolledWindow):
244         pannableWindow = hildon.PannableArea()
245
246         child = scrolledWindow.get_child()
247         scrolledWindow.remove(child)
248         pannableWindow.add(child)
249
250         parent = scrolledWindow.get_parent()
251         parent.remove(scrolledWindow)
252         parent.add(pannableWindow)
253
254         return pannableWindow
255
256
257 def _hildon_hildonize_scrollwindow(scrolledWindow):
258         hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
259         return scrolledWindow
260
261
262 def _null_hildonize_scrollwindow(scrolledWindow):
263         return scrolledWindow
264
265
266 try:
267         hildon.PannableArea
268         hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
269         hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
270 except AttributeError:
271         try:
272                 hildon.hildon_helper_hildonize_scrollwindow
273                 hildonize_scrollwindow = _hildon_hildonize_scrollwindow
274                 hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
275         except AttributeError:
276                 hildonize_scrollwindow = _null_hildonize_scrollwindow
277                 hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
278
279
280 def _hildon_request_number(parent, title, range, default):
281         spinner = hildon.NumberEditor(*range)
282         spinner.set_value(default)
283
284         dialog = gtk.Dialog(
285                 title,
286                 parent,
287                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
288                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
289         )
290         dialog.set_default_response(gtk.RESPONSE_CANCEL)
291         dialog.get_child().add(spinner)
292
293         try:
294                 dialog.show_all()
295                 response = dialog.run()
296         finally:
297                 dialog.hide()
298
299         if response == gtk.RESPONSE_OK:
300                 return spinner.get_value()
301         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
302                 raise RuntimeError("User cancelled request")
303         else:
304                 raise RuntimeError("Unrecognized response %r", response)
305
306
307 def _null_request_number(parent, title, range, default):
308         adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
309         spinner = gtk.SpinButton(adjustment, 0, 0)
310         spinner.set_wrap(False)
311
312         dialog = gtk.Dialog(
313                 title,
314                 parent,
315                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
316                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
317         )
318         dialog.set_default_response(gtk.RESPONSE_CANCEL)
319         dialog.get_child().add(spinner)
320
321         try:
322                 dialog.show_all()
323                 response = dialog.run()
324         finally:
325                 dialog.hide()
326
327         if response == gtk.RESPONSE_OK:
328                 return spinner.get_value_as_int()
329         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
330                 raise RuntimeError("User cancelled request")
331         else:
332                 raise RuntimeError("Unrecognized response %r", response)
333
334
335 try:
336         hildon.NumberEditor # TODO deprecated in fremantle
337         request_number = _hildon_request_number
338 except AttributeError:
339         request_number = _null_request_number
340
341
342 def _hildon_touch_selector(parent, title, items, defaultIndex):
343         model = gtk.ListStore(gobject.TYPE_STRING)
344         for item in items:
345                 model.append((item, ))
346
347         selector = hildon.TouchSelector()
348         selector.append_text_column(model, True)
349         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
350         selector.set_active(0, defaultIndex)
351
352         dialog = hildon.PickerDialog(parent)
353         dialog.set_selector(selector)
354
355         try:
356                 dialog.show_all()
357                 response = dialog.run()
358         finally:
359                 dialog.hide()
360
361         if response == gtk.RESPONSE_OK:
362                 return selector.get_active(0)
363         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
364                 raise RuntimeError("User cancelled request")
365         else:
366                 raise RuntimeError("Unrecognized response %r", response)
367
368
369 def _on_null_touch_selector_activated(treeView, path, column, dialog):
370         dialog.response(gtk.RESPONSE_OK)
371
372
373 def _null_touch_selector(parent, title, items, defaultIndex = -1):
374         model = gtk.ListStore(gobject.TYPE_STRING)
375         for item in items:
376                 model.append((item, ))
377
378         cell = gtk.CellRendererText()
379         set_cell_thumb_selectable(cell)
380         column = gtk.TreeViewColumn(title)
381         column .pack_start(cell, expand=True)
382         column.add_attribute(cell, "text", 0)
383
384         treeView = gtk.TreeView()
385         treeView.set_model(model)
386         treeView.append_column(column)
387         selection = treeView.get_selection()
388         selection.set_mode(gtk.SELECTION_SINGLE)
389         if 0 < defaultIndex:
390                 selection.select_path((defaultIndex, ))
391
392         scrolledWin = gtk.ScrolledWindow()
393         scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
394         scrolledWin.add(treeView)
395         hildonize_scrollwindow(scrolledWin)
396
397         dialog = gtk.Dialog(
398                 title,
399                 parent,
400                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
401                 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
402         )
403         dialog.set_default_response(gtk.RESPONSE_CANCEL)
404         dialog.get_child().add(scrolledWin)
405         parentSize = parent.get_size()
406         dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
407         treeView.connect("row-activated", _on_null_touch_selector_activated, dialog)
408
409         try:
410                 dialog.show_all()
411                 response = dialog.run()
412         finally:
413                 dialog.hide()
414
415         if response == gtk.RESPONSE_OK:
416                 model, itr = selection.get_selected()
417                 if itr is None:
418                         raise RuntimeError("No selection made")
419                 return model.get_path(itr)[0]
420         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
421                 raise RuntimeError("User cancelled request")
422         else:
423                 raise RuntimeError("Unrecognized response %r", response)
424
425
426 try:
427         hildon.PickerDialog
428         hildon.TouchSelector
429         touch_selector = _hildon_touch_selector
430 except AttributeError:
431         touch_selector = _null_touch_selector
432
433
434 if __name__ == "__main__":
435         app = get_app_class()()
436         win = gtk.Window()
437         win = hildonize_window(app, win)
438         if True:
439                 print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)