Don't use if expression, python 2.4 doesn't support that.
[matthijs/upstream/mobilegtd.git] / src / gui / gui.py
index 94ade0689c9a09b1a4a212d9f38a61660a579c4b..5c4d0b8ee7e221ad26b087909f27ff64091dd20e 100644 (file)
@@ -137,12 +137,13 @@ 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()
         except:
             while not self.exit_flag:
                 self.refresh()
                 self.lock.wait()
         except:
-            pass
+            # TODO: Find out which exceptions to catch here. Catching
+            # and silencing all exceptions is not a good idea.
+            raise
         restore_gui(self)
 
     def exit(self):
         restore_gui(self)
 
     def exit(self):
@@ -162,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):
         """
@@ -172,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)
@@ -203,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.set_view(appuifw.Listbox([], 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))
 
@@ -217,10 +222,31 @@ class ListView(View):
         we'll have to adjust the index with the direction of the
         keypress (-1 for up, +1 for down).
         """
         we'll have to adjust the index with the direction of the
         keypress (-1 for up, +1 for down).
         """
-        self.current_index = (self.selected_index() + dir) % len(self.items())
+        self.current_index = self.wrap_index(self.selected_index() + dir)
         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()
@@ -247,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. """
@@ -258,6 +291,24 @@ class ListView(View):
         else:
             return self.view.current()
 
         else:
             return self.view.current()
 
+    def clip_index(self, index):
+        """
+        Make sure the given index fits within the bounds of this
+        list. If it doesn't, clip it off at the ends of the list (e.g,
+        -1 becomes 0).
+        """
+        max_index = len(self.items_cache) - 1
+        return max (0, min(max_index, index))
+
+    def wrap_index(self, index):
+        """
+        Make sure the given index fits within the bounds of this
+        list. If it doesn't, wrap it around (e.g., -1 becomes 5 in a
+        6-element list).
+        """
+        count = len(self.items_cache)
+        return index % count
+    
 class WidgetBasedListView(ListView):
     def __init__(self):
         self.binding_map = {}
 class WidgetBasedListView(ListView):
     def __init__(self):
         self.binding_map = {}
@@ -276,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.