1 from config.config import *
2 from model.projects import Projects
6 from log.logging import logger
7 from e32 import Ao_lock, in_emulator
8 from key_codes import *
14 for k, v in cfg.items():
15 v = cfg.format_value(v)
16 if isinstance(v, int) or isinstance(v, long):
19 elif isinstance(v, list) or isinstance(v, tuple):
21 if not isinstance(item, unicode):
22 raise Exception("list can contain only unicode objects, "\
23 "object %r is not supported" % item)
26 elif isinstance(v, unicode):
29 raise Exception("%s has non-supported value" % k)
31 fields.append((unicode(k), tname, v))
34 form = appuifw.Form(fields=fields, flags=appuifw.FFormEditModeOnly | \
35 appuifw.FFormDoubleSpaced)
40 form.save_hook = save_hook
44 # return true if user saved, false otherwise
48 for label, tname, value in form:
50 value = (value[0], int(value[1]))
52 cfg[str(label)] = cfg.parse_value(value)
60 def applicable_functions(obj,allowed_function_names):
61 function_names = [function_name for function_name in dir(obj) if function_name in allowed_function_names]
62 return [eval('obj.%s'%function_name) for function_name in function_names]
64 def get_key(key_name):
68 key=eval('EKey%s'%key_name)
72 return filter(lambda entry:entry[0:4]=='EKey',dir(key_codes))
92 object.old_gui = appuifw.app.body
93 object.old_menu = appuifw.app.menu
94 object.old_exit_key_handler = appuifw.app.exit_key_handler
95 object.old_title=appuifw.app.title
97 def restore_gui(object):
98 appuifw.app.body = object.old_gui
99 appuifw.app.menu = object.old_menu
100 appuifw.app.exit_key_handler = object.old_exit_key_handler
101 appuifw.app.title = object.old_title
107 self.lock = Ao_lock()
108 self.exit_flag = False
109 super(View, self).__init__()
111 def set_title(self, title):
114 def set_view(self, view):
116 Sets the main view to be displayed (e.g., an appuifw.Listbox
122 self.adjustment = None
124 appuifw.app.screen=COMMON_CONFIG['screen'].encode('utf-8')
125 appuifw.app.title=self.title
126 appuifw.app.body=self.view
127 appuifw.app.exit_key_handler=self.exit
130 while not self.exit_flag:
138 self.exit_flag = True
141 def update(self,subject=None):
143 Update the current view (e.g., make sure refresh is called). We
144 can't call it directly, since we're in another thread.
151 Called when the current view must be updated. Never call
152 directly. Subclasses should extend this method, not update.
154 appuifw.app.menu=self.get_menu_entries()
156 def get_menu_entries(self):
157 """ Returns a list of menu entries to display. Will be
158 automatically updated on each refresh.
160 Each menu entry is a tuple of a title for the entry and a
161 function to call when the entry is selected.
165 class ListView(View):
167 super(ListView, self).__init__()
168 self.set_view(appuifw.Listbox(self.items(),self.entry_selected))
169 self.view.bind(EKeyUpArrow,lambda: self.arrow_key_pressed(-1))
170 self.view.bind(EKeyDownArrow,lambda: self.arrow_key_pressed(1))
172 def arrow_key_pressed(self, dir):
174 This function is called when an arrow key is pressed. Since we
175 don't get any "current list index has changed" events, we'll
176 have to create these ourselves this way.
178 Since the current index is only updated after the key event,
179 we'll have to adjust the index with the direction of the
180 keypress (-1 for up, +1 for down).
182 new_index = (self.selected_index() + dir) % len(self.items())
183 self.index_changed(new_index)
185 def entry_selected(self):
187 This function is called when the user selects an an entry (e.g.,
188 navigates to it and push the ok button).
192 def index_changed(self,new_index):
194 This function is called when the index changes. The given index
195 is the new index (don't use self.selected_index() here, since it
196 won't be correct yet!).
201 """ This function should return the list of items to display.
202 See appuifw.ListBox for valid elements for this list. """
205 def set_index(self,index):
206 """ Changes the currently selected item to index. """
207 self.view.set_list(self.items(),index % len(self.items()))
209 def selected_index(self):
210 """ Returns the currently selected index. """
211 return self.view.current()
213 class WidgetBasedListView(ListView):
215 self.widgets = self.generate_widgets()
216 super(WidgetBasedListView,self).__init__()
220 self.set_bindings_for_selection(0)
223 def index_changed(self,new_index):
224 self.set_bindings_for_selection(new_index)
225 super(WidgeteBasedListView, self).index_changed(new_index)
227 def notify(self,object,attribute,new=None,old=None):
230 self.widgets = self.generate_widgets()
231 self.redisplay_widgets()
232 super(WidgetBasedListView,self).refresh()
233 def redisplay_widgets(self):
234 self.set_index(self.selected_index())
236 return self.all_widget_texts()
237 def all_widget_texts(self):
238 return [entry.list_repr() for entry in self.widgets]
242 def current_widget(self):
243 return self.widgets[self.selected_index()]
246 class KeyBindingView(View):
249 self.binding_map = {}
250 super(KeyBindingView,self).__init__()
252 def set_keybindings(self, binding_map):
254 Set a new map of key bindings. This map maps method names to a
255 tuple of keyname and description.
257 The method name refers to a method on the selected item, or the
260 Example: { 'search_item' : ('0', 'Search item') }
263 self.binding_map = binding_map
265 def get_menu_entries(self):
267 for key,key_name,description,function in self.key_and_menu_bindings(self.selected_index()):
268 if description != '':
270 if key_name == 'Backspace': key_name='C'
271 description='[%s] '%key_name +description
273 description=' '+description
274 menu_entries.append((description,function))
275 menu_entries.append((u'Exit', self.exit))
276 return menu_entries + super(KeyBindingView, self).get_menu_entries()
278 def set_bindings_for_selection(self,selected_index):
279 self.remove_all_key_bindings()
281 for key,key_name,description,function in self.key_and_menu_bindings(selected_index):
283 self.view.bind(key,function)
285 def remove_all_key_bindings(self):
286 for key in all_key_values():
287 self.view.bind(key,no_action)
289 class SearchableListView(WidgetBasedListView):
291 self.current_entry_filter_index = -1
292 self.entry_filters = []
293 self.filtered_list = lambda:[]
295 super(SearchableListView,self).__init__()
297 def set_filters(self, entry_filters):
299 Set the filters that could be applied to this list. Each filter
300 can be applied in turn by calling switch_entry_filter (for
301 example from a key binding).
303 The entry_filters argument should be a list of filters. The
304 active filter is stored into self.filtered_list and should be
305 processed by generate_widgets in the subclass.
307 self.current_entry_filter_index = 0
308 self.entry_filters = entry_filters
309 self.filtered_list = self.entry_filters[0]
311 def search_item(self):
312 selected_item = appuifw.selection_list(self.all_widget_texts(),search_field=1)
313 if selected_item == None or selected_item == -1:
314 selected_item = self.selected_index()
315 self.view.set_list(self.items(),selected_item)
316 self.set_bindings_for_selection(selected_item)
318 def switch_entry_filter(self):
319 self.current_entry_filter_index += 1
320 self.filtered_list = self.entry_filters[self.current_entry_filter_index % len(self.entry_filters)]
324 class EditableListView(SearchableListView,KeyBindingView):
326 super(EditableListView, self).__init__()
328 def key_and_menu_bindings(self,selected_index):
329 key_and_menu_bindings=[]
330 for function in applicable_functions(self.widgets[selected_index],self.binding_map)+\
331 applicable_functions(self,self.binding_map):
332 execute_and_update_function = self.execute_and_update(function)
333 (key,description) = self.binding_map[function.__name__]
334 key_and_menu_bindings.append((get_key(key),key,description,execute_and_update_function))
335 return key_and_menu_bindings
337 def entry_selected(self):
338 self.current_widget().change()
340 def execute_and_update(self,function):
341 return lambda: (function(),self.refresh(),self.index_changed())
343 def notify(self,item,attribute,new=None,old=None):
346 #class DisplayableFunction:
347 # def __init__(self,display_name,function):
348 # self.display_name = display_name
349 # self.function = function
350 # def list_repr(self):
351 # return self.display_name
356 __all__= ('EditableListView','show_config')