Fix keybindings.
[matthijs/upstream/mobilegtd.git] / src / gui / gui.py
index f7ee31e78f89eed14e89f3b80b6d973dc4aa9f8a..16fa606231e83a71551335f45b6546c3933a2ea3 100644 (file)
@@ -137,7 +137,6 @@ class View(object):
         appuifw.app.body=self.view
         appuifw.app.exit_key_handler=self.exit
         try:
         appuifw.app.body=self.view
         appuifw.app.exit_key_handler=self.exit
         try:
-            self.lock.wait()
             while not self.exit_flag:
                 self.refresh()
                 self.lock.wait()
             while not self.exit_flag:
                 self.refresh()
                 self.lock.wait()
@@ -164,7 +163,7 @@ class View(object):
         Called when the current view must be updated. Never call
         directly. Subclasses should extend this method, not update.
         """
         Called when the current view must be updated. Never call
         directly. Subclasses should extend this method, not update.
         """
-        pass
+        self.refresh_menu()
 
     def refresh_menu(self):
         """
 
     def refresh_menu(self):
         """
@@ -174,7 +173,10 @@ class View(object):
         # Two helper functions
         def shortcut_prefix(key_name):
             short = key_shortname(key_name)
         # Two helper functions
         def shortcut_prefix(key_name):
             short = key_shortname(key_name)
-            return '[%s]' % short if short else '   '
+            if short:
+                return '[%s]' % short
+            else:
+                return '   '
 
         def do_entry((text, callback, key_name)):
             key = get_key(key_name)
 
         def do_entry((text, callback, key_name)):
             key = get_key(key_name)
@@ -205,7 +207,8 @@ class ListView(View):
     def __init__(self):
         super(ListView, self).__init__()
         self.current_index = None
     def __init__(self):
         super(ListView, self).__init__()
         self.current_index = None
-        self.set_view(appuifw.Listbox(self.items(),self.entry_selected))
+        self.items_cache = self.items()
+        self.set_view(appuifw.Listbox(self.items_cache, self.entry_selected))
         self.view.bind(EKeyUpArrow,lambda: self.arrow_key_pressed(-1))
         self.view.bind(EKeyDownArrow,lambda: self.arrow_key_pressed(1))
 
         self.view.bind(EKeyUpArrow,lambda: self.arrow_key_pressed(-1))
         self.view.bind(EKeyDownArrow,lambda: self.arrow_key_pressed(1))
 
@@ -223,6 +226,27 @@ class ListView(View):
         self.index_changed()
         self.current_index = None
 
         self.index_changed()
         self.current_index = None
 
+    def refresh(self):
+        self.refresh_list()
+        super(ListView, self).refresh()
+    
+    def refresh_list(self):
+        """ Reload the list items. Calls items() again. """
+        # Remember which item was selected
+        selected = self.selected_item()
+        # Refresh the list
+        self.items_cache = self.items()
+        try:
+            # Try to find the selected item in the new list (based on
+            # the display text).
+            selected_index = self.items_cache.index(selected)
+        except ValueError:
+            # If the selected item is no longer present, just keep the
+            # index the same (but be careful not to fall off the end).
+            selected_index = self.clip_index(self.selected_index())
+        # Update the items in the view
+        self.view.set_list(self.items_cache, selected_index)
+
     def run(self):
         self.index_changed()
         super(ListView, self).run()
     def run(self):
         self.index_changed()
         super(ListView, self).run()
@@ -249,7 +273,14 @@ class ListView(View):
 
     def set_index(self,index):
         """ Changes the currently selected item to index. """
 
     def set_index(self,index):
         """ Changes the currently selected item to index. """
-        self.view.set_list(self.items(),index % len(self.items()))
+        self.view.set_list(self.items_cache, self.clip_index(index))
+
+    def selected_item(self):
+        """ Returns the (title of the) currently selected list item. """
+        if not self.items_cache:
+            return None # No items, so none is selected.
+        return self.items_cache[self.selected_index()]
+
 
     def selected_index(self):
         """ Returns the currently selected index. """
 
     def selected_index(self):
         """ Returns the currently selected index. """
@@ -296,16 +327,19 @@ class WidgetBasedListView(ListView):
         self.refresh()
 
     def refresh(self):
         self.refresh()
 
     def refresh(self):
-        self.widgets = self.generate_widgets()
-        self.redisplay_widgets()
+        self.refresh_widgets()
         super(WidgetBasedListView,self).refresh()
         super(WidgetBasedListView,self).refresh()
+    
+    def refresh_widgets(self):
+        """ Refresh the widget list. Calls generate_widgets(). """
+        self.widgets = self.generate_widgets()
 
     def redisplay_widgets(self):
         """
         Redisplay the widgets. Should be called if the widgets
         themselves have changed, does not call generate_widgets again.
         """
 
     def redisplay_widgets(self):
         """
         Redisplay the widgets. Should be called if the widgets
         themselves have changed, does not call generate_widgets again.
         """
-        self.set_index(self.selected_index())
+        self.refresh_list()
 
     def items(self):
         # Let ListView show each widget's text.
 
     def items(self):
         # Let ListView show each widget's text.
@@ -330,13 +364,19 @@ class WidgetBasedListView(ListView):
         # Determine the current menu based on the methods available on
         # the selected widget and on ourselves.
         menu_items = []
         # Determine the current menu based on the methods available on
         # the selected widget and on ourselves.
         menu_items = []
+        def make_callback(f):
+            # This is rather complicated, but loops don't have their own
+            # scope, so putting do_callback inside the loop would not
+            # capture the value of function, but only a reference to the
+            # loop variable (always evaluating to the final value...)
+            def do_callback():
+                f()
+                self.update()
+            return do_callback
         for function in applicable_functions(self.current_widget(),self.binding_map)+\
             applicable_functions(self,self.binding_map):
             (key,description) = self.binding_map[function.__name__]
         for function in applicable_functions(self.current_widget(),self.binding_map)+\
             applicable_functions(self,self.binding_map):
             (key,description) = self.binding_map[function.__name__]
-            def do_callback():
-                function()
-                self.update()
-            menu_items.append((description, do_callback, key))
+            menu_items.append((description, make_callback(function), key))
         menu_items += super(WidgetBasedListView, self).menu_items()
         return menu_items
 
         menu_items += super(WidgetBasedListView, self).menu_items()
         return menu_items