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
140 super(View, self).exit()
144 Update the gui after a change in model or some user interaction.
145 Should be filled by subclasses.
147 super(View, self).refresh()
149 def get_menu_entries(self):
150 """ Returns a list of menu entries to display. Will be
151 automatically updated on each refresh.
153 Each menu entry is a tuple of a title for the entry and a
154 function to call when the entry is selected.
158 class ListView(View):
160 super(ListView, self).__init__()
161 self.set_view(appuifw.Listbox(self.items(),self.entry_selected))
163 def entry_selected(self):
165 This function is called when the user selects an an entry (e.g.,
166 navigates to it and push the ok button).
168 super(ListView).entry_selected()
170 def update(self,subject=None):
171 #logger.log(u'Updated %s'%repr(self))
176 def index_changed(self,adjustment=None):
178 index = self.selected_index() + adjustment
180 index = self.selected_index()
182 index = len(self.widgets) - 1
183 if index >= len(self.widgets):
185 self.set_bindings_for_selection(index)
188 appuifw.app.menu=self.get_menu_entries()
190 def set_index(self,index):
191 if index > len(self.widgets):
192 index = len(self.widgets)
195 self.view.set_list(self.items(),index)
197 def selected_index(self):
198 return self.view.current()
200 class WidgetBasedListView(ListView):
202 self.widgets = self.generate_widgets()
203 super(WidgetBasedListView,self).__init__()
207 self.set_bindings_for_selection(0)
210 def notify(self,object,attribute,new=None,old=None):
213 self.widgets = self.generate_widgets()
214 self.redisplay_widgets()
215 super(WidgetBasedListView,self).refresh()
216 def redisplay_widgets(self):
217 self.set_index(self.selected_index())
219 return self.all_widget_texts()
220 def all_widget_texts(self):
221 return [entry.list_repr() for entry in self.widgets]
225 def current_widget(self):
226 return self.widgets[self.selected_index()]
229 class KeyBindingView(View):
232 self.binding_map = {}
233 super(KeyBindingView,self).__init__()
235 def set_keybindings(self, binding_map):
237 Set a new map of key bindings. This map maps method names to a
238 tuple of keyname and description.
240 The method name refers to a method on the selected item, or the
243 Example: { 'search_item' : ('0', 'Search item') }
246 self.binding_map = binding_map
248 def get_menu_entries(self):
250 for key,key_name,description,function in self.key_and_menu_bindings(self.selected_index()):
251 if description != '':
253 if key_name == 'Backspace': key_name='C'
254 description='[%s] '%key_name +description
256 description=' '+description
257 menu_entries.append((description,function))
258 menu_entries.append((u'Exit', self.exit))
259 return menu_entries + super(KeyBindingView, self).get_menu_entries()
261 def set_bindings_for_selection(self,selected_index):
262 self.remove_all_key_bindings()
264 for key,key_name,description,function in self.key_and_menu_bindings(selected_index):
266 self.view.bind(key,function)
267 self.view.bind(EKeyUpArrow,lambda: self.index_changed(-1))
268 self.view.bind(EKeyDownArrow,lambda: self.index_changed(1))
270 def remove_all_key_bindings(self):
271 for key in all_key_values():
272 self.view.bind(key,no_action)
274 class SearchableListView(WidgetBasedListView):
276 self.current_entry_filter_index = -1
277 self.entry_filters = []
278 self.filtered_list = lambda:[]
280 super(SearchableListView,self).__init__()
282 def set_filters(self, entry_filters):
284 Set the filters that could be applied to this list. Each filter
285 can be applied in turn by calling switch_entry_filter (for
286 example from a key binding).
288 The entry_filters argument should be a list of filters. The
289 active filter is stored into self.filtered_list and should be
290 processed by generate_widgets in the subclass.
292 self.current_entry_filter_index = 0
293 self.entry_filters = entry_filters
294 self.filtered_list = self.entry_filters[0]
296 def search_item(self):
297 selected_item = appuifw.selection_list(self.all_widget_texts(),search_field=1)
298 if selected_item == None or selected_item == -1:
299 selected_item = self.selected_index()
300 self.view.set_list(self.items(),selected_item)
301 self.set_bindings_for_selection(selected_item)
303 def switch_entry_filter(self):
304 self.current_entry_filter_index += 1
305 self.filtered_list = self.entry_filters[self.current_entry_filter_index % len(self.entry_filters)]
309 class EditableListView(SearchableListView,KeyBindingView):
311 super(EditableListView, self).__init__()
313 def key_and_menu_bindings(self,selected_index):
314 key_and_menu_bindings=[]
315 for function in applicable_functions(self.widgets[selected_index],self.binding_map)+\
316 applicable_functions(self,self.binding_map):
317 execute_and_update_function = self.execute_and_update(function)
318 (key,description) = self.binding_map[function.__name__]
319 key_and_menu_bindings.append((get_key(key),key,description,execute_and_update_function))
320 return key_and_menu_bindings
322 def entry_selected(self):
323 self.current_widget().change()
325 def execute_and_update(self,function):
326 return lambda: (function(),self.refresh(),self.index_changed())
328 def notify(self,item,attribute,new=None,old=None):
331 #class DisplayableFunction:
332 # def __init__(self,display_name,function):
333 # self.display_name = display_name
334 # self.function = function
335 # def list_repr(self):
336 # return self.display_name
341 __all__= ('EditableListView','show_config')