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))
170 def entry_selected(self):
172 This function is called when the user selects an an entry (e.g.,
173 navigates to it and push the ok button).
177 def index_changed(self,adjustment=None):
179 index = self.selected_index() + adjustment
181 index = self.selected_index()
183 index = len(self.widgets) - 1
184 if index >= len(self.widgets):
186 self.set_bindings_for_selection(index)
188 def set_index(self,index):
189 if index > len(self.widgets):
190 index = len(self.widgets)
193 self.view.set_list(self.items(),index)
195 def selected_index(self):
196 return self.view.current()
198 class WidgetBasedListView(ListView):
200 self.widgets = self.generate_widgets()
201 super(WidgetBasedListView,self).__init__()
205 self.set_bindings_for_selection(0)
208 def notify(self,object,attribute,new=None,old=None):
211 self.widgets = self.generate_widgets()
212 self.redisplay_widgets()
213 super(WidgetBasedListView,self).refresh()
214 def redisplay_widgets(self):
215 self.set_index(self.selected_index())
217 return self.all_widget_texts()
218 def all_widget_texts(self):
219 return [entry.list_repr() for entry in self.widgets]
223 def current_widget(self):
224 return self.widgets[self.selected_index()]
227 class KeyBindingView(View):
230 self.binding_map = {}
231 super(KeyBindingView,self).__init__()
233 def set_keybindings(self, binding_map):
235 Set a new map of key bindings. This map maps method names to a
236 tuple of keyname and description.
238 The method name refers to a method on the selected item, or the
241 Example: { 'search_item' : ('0', 'Search item') }
244 self.binding_map = binding_map
246 def get_menu_entries(self):
248 for key,key_name,description,function in self.key_and_menu_bindings(self.selected_index()):
249 if description != '':
251 if key_name == 'Backspace': key_name='C'
252 description='[%s] '%key_name +description
254 description=' '+description
255 menu_entries.append((description,function))
256 menu_entries.append((u'Exit', self.exit))
257 return menu_entries + super(KeyBindingView, self).get_menu_entries()
259 def set_bindings_for_selection(self,selected_index):
260 self.remove_all_key_bindings()
262 for key,key_name,description,function in self.key_and_menu_bindings(selected_index):
264 self.view.bind(key,function)
265 self.view.bind(EKeyUpArrow,lambda: self.index_changed(-1))
266 self.view.bind(EKeyDownArrow,lambda: self.index_changed(1))
268 def remove_all_key_bindings(self):
269 for key in all_key_values():
270 self.view.bind(key,no_action)
272 class SearchableListView(WidgetBasedListView):
274 self.current_entry_filter_index = -1
275 self.entry_filters = []
276 self.filtered_list = lambda:[]
278 super(SearchableListView,self).__init__()
280 def set_filters(self, entry_filters):
282 Set the filters that could be applied to this list. Each filter
283 can be applied in turn by calling switch_entry_filter (for
284 example from a key binding).
286 The entry_filters argument should be a list of filters. The
287 active filter is stored into self.filtered_list and should be
288 processed by generate_widgets in the subclass.
290 self.current_entry_filter_index = 0
291 self.entry_filters = entry_filters
292 self.filtered_list = self.entry_filters[0]
294 def search_item(self):
295 selected_item = appuifw.selection_list(self.all_widget_texts(),search_field=1)
296 if selected_item == None or selected_item == -1:
297 selected_item = self.selected_index()
298 self.view.set_list(self.items(),selected_item)
299 self.set_bindings_for_selection(selected_item)
301 def switch_entry_filter(self):
302 self.current_entry_filter_index += 1
303 self.filtered_list = self.entry_filters[self.current_entry_filter_index % len(self.entry_filters)]
307 class EditableListView(SearchableListView,KeyBindingView):
309 super(EditableListView, self).__init__()
311 def key_and_menu_bindings(self,selected_index):
312 key_and_menu_bindings=[]
313 for function in applicable_functions(self.widgets[selected_index],self.binding_map)+\
314 applicable_functions(self,self.binding_map):
315 execute_and_update_function = self.execute_and_update(function)
316 (key,description) = self.binding_map[function.__name__]
317 key_and_menu_bindings.append((get_key(key),key,description,execute_and_update_function))
318 return key_and_menu_bindings
320 def entry_selected(self):
321 self.current_widget().change()
323 def execute_and_update(self,function):
324 return lambda: (function(),self.refresh(),self.index_changed())
326 def notify(self,item,attribute,new=None,old=None):
329 #class DisplayableFunction:
330 # def __init__(self,display_name,function):
331 # self.display_name = display_name
332 # self.function = function
333 # def list_repr(self):
334 # return self.display_name
339 __all__= ('EditableListView','show_config')