changeset 205:a1b00ffea269

Use handle_input instead of keypress to act on user input in States
author Björn Ricks <bjoern.ricks@intevation.de>
date Fri, 05 Apr 2013 19:44:59 +0200 (2013-04-05)
parents 921e98f9aa87
children 9f1c45a2126e
files getan/states.py
diffstat 1 files changed, 152 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/getan/states.py	Fri Apr 05 19:34:23 2013 +0200
+++ b/getan/states.py	Fri Apr 05 19:44:59 2013 +0200
@@ -66,80 +66,76 @@
 
 
 class ProjectState(State):
-    def keypress(self, key):
+
+    def handle_input(self, input):
         keys = self.config.get_keybinding()
-        logger.debug("ProjectState: handle key '%r'" % key)
-        if keys.get_switch_time_mode() in key:
+        logger.debug("ProjectState: handle input '%r'" % input)
+        if keys.get_switch_time_mode() in input:
             self.view.switch_time_mode()
-            return self
+            return True
 
-        if keys.get_switch_project_order() in key:
+        if keys.get_switch_project_order() in input:
             self.view.switch_project_order()
-            return self
+            return True
 
-        if keys.get_switch_lists() in key:
+        if keys.get_switch_lists() in input:
             if not self.controller.entries_view.rows:
-                return self
-            self.controller.entries_view.focused = 0
-            self.controller.entries_view.update_focus(0)
-            return DefaultEntryListState(self, self.controller,
-                                  self.controller.entries_view)
-
-        if keys.get_entry_up() in key:
-            return self.up()
-
-        if keys.get_entry_down() in key:
-            return self.down()
-
-    def up(self):
-        self.view.up()
-        self.controller.update_entries(self.view.item_in_focus())
-        return self
-
-    def down(self):
-        self.view.down()
-        self.controller.update_entries(self.view.item_in_focus())
-        return self
+                return True
+            new_state = DefaultEntryListState(self, self.controller,
+                    self.controller.entries_view)
+            self.set_next_state(new_state)
+            self.controller.view.set_focus(1)
+            self.controller.entries_view.set_focus(0)
+            return True
 
 
 class PausedProjectsState(ProjectState):
+
     messages = {
         'choose_proj': _('Choose a project: '),
     }
 
-    def keypress(self, key):
+    def handle_input(self, key):
         logger.debug("PausedProjectsState: handle key '%r'" % key)
         keys = self.config.get_keybinding()
-        ret = super(PausedProjectsState, self).keypress(key)
+        ret = super(PausedProjectsState, self).handle_input(key)
         if ret:
-            return ret
+            return True
 
         if keys.get_enter() in key:
             return self.select()
 
         if keys.get_insert() in key:
-            return AddProjectKeyState(self.controller, self.view)
+            state = AddProjectKeyState(self.controller, self.view)
+            self.set_next_state(state)
+            return True
 
         if keys.get_escape() in key:
-            return ExitState(self.controller, self.view)
+            state = ExitState(self.controller, self.view)
+            self.set_next_state(state)
+            return True
 
         if keys.get_project_edit() in key:
             proj = self.view.item_in_focus()
             if not proj:
-                return self
-            return ProjectEditKeyState(self.controller, self.view, proj)
+                return True
+            state = ProjectEditKeyState(self.controller, self.view, proj)
+            self.set_next_state(state)
+            return True
 
         else:
             if len(key) > 0 and len(key[0]) == 1:
-                select_proj = SelectProjectState(self.controller, self.view)
-                return select_proj.keypress(key)
-        return self
-
+                state = SelectProjectState(self.controller, self.view)
+                self.set_next_state(state)
+                return state.handle_input(key)
+        return False
 
     def select(self):
         proj = self.view.item_in_focus()
         self.controller.start_project(proj)
-        return RunningProjectsState(self.controller, self.view, proj)
+        state = RunningProjectsState(self.controller, self.view, proj)
+        self.set_next_state(state)
+        return True
 
 
 class SelectProjectState(State):
@@ -166,20 +162,22 @@
             self.controller.start_project(self.view.item_in_focus())
             self.controller.update_entries(
                     self.view.item_in_focus())
-            return RunningProjectsState(self.controller, self.view, proj)
-        return self
+            self.set_next_state(RunningProjectsState(self.controller, self.view,
+                proj))
+        return True
 
-    def keypress(self, key):
+    def handle_input(self, key):
         keys = self.config.get_keybinding()
         if keys.get_escape() in key:
             self.reset()
-            return PausedProjectsState(self.controller, self.view)
+            self.set_next_state(PausedProjectsState(self.controller, self.view))
+            return True
 
         if 'backspace' in key:
             if len(self.proj_keys) > 0:
                 self.proj_keys = self.proj_keys[:-1]
                 self.set_footer_text()
-            return self
+            return True
 
         if keys.get_enter() in key:
             return self.select_project()
@@ -194,10 +192,11 @@
                     if num == 1:
                         # run project directly
                         return self.select_project()
-        return self
+        return False
 
 
 class ExitState(ProjectState):
+
     messages = {
         'quit'  : _(" Really quit? (y/n)"),
         'choose': _(" Choose a project:")
@@ -207,23 +206,26 @@
         super(ExitState, self).__init__(controller, view)
         self.controller.view.set_footer_text(self.msg('quit'), 'question')
 
-    def keypress(self, key):
+    def handle_input(self, key):
         logger.debug("ExitState: handle key '%r'" % key)
-        ret = super(ExitState, self).keypress(key)
+        ret = super(ExitState, self).handle_input(key)
         if ret:
             return ret
 
         if 'y' in key or 'Y' in key:
             self.controller.exit()
+            return True
 
         if 'n' in key or 'N' in key:
             self.controller.view.set_footer_text(self.msg('choose'), 'question')
-            return PausedProjectsState(self.controller, self.view)
+            self.set_next_state(PausedProjectsState(self.controller, self.view))
+            return True
 
-        return self
+        return False
 
 
 class RunningProjectsState(ProjectState):
+
     messages = {
         'description': _("Enter a description: "),
         'add_time'   : _("Enter time to add [min]: "),
@@ -245,8 +247,10 @@
     def handle_signal(self, signum, frame):
         proj = self.project
         keys = self.config.get_keybinding()
+
         if not proj:
             return
+
         if not self.break_start:
             self.controller.view.set_footer_text(self.msg('running') %
                                                  (human_time(self.sec),
@@ -265,10 +269,10 @@
         signal.signal(signal.SIGALRM, self.handle_signal)
         signal.alarm(1)
 
-    def keypress(self, key):
+    def handle_input(self, key):
         logger.debug("RunningProjectsState: handle key '%r'" % key)
         keys = self.config.get_keybinding()
-        ret = super(RunningProjectsState, self).keypress(key)
+        ret = super(RunningProjectsState, self).handle_input(key)
         if ret:
             return ret
 
@@ -278,17 +282,20 @@
             self.view.set_footer_text(self.msg('add_time'),
                                                'question', 1)
             self.view.frame.set_focus('footer')
-            return AddTimeState(self.controller, self.view, self)
+            self.set_next_state(AddTimeState(self.controller, self.view, self))
+            return True
+
         if keys.get_subtract_time() in key:
             self.view.set_footer_text(self.msg('min_time'),
                                                  'question', 1)
             self.view.frame.set_focus('footer')
-            return SubtractTimeState(self.controller, self.view, self)
+            self.set_next_state(SubtractTimeState(self.controller, self.view,
+                self))
+            return True
 
         if keys.get_project_pause() in key:
             if not self.break_start:
                 self.break_start = datetime.now()
-                return self
             else:
                 self.view._total_time()
                 proj = self.project
@@ -297,7 +304,8 @@
                     self.break_start = None
                     signal.signal(signal.SIGALRM, self.handle_signal)
                     signal.alarm(1)
-        return self
+            return True
+        return False
 
     def stop(self):
         signal.alarm(0)
@@ -307,9 +315,9 @@
             if proj: proj.start += datetime.now() - self.break_start
         self.controller.view.set_footer_text(self.msg('description'),'question',1)
         self.controller.view.get_frame().set_focus('footer')
-        return DescriptionProjectsState(
-            self.controller, self.view, self,
-            self.controller.view.get_frame().get_footer())
+        self.set_next_state(DescriptionProjectsState(self.controller, self.view,
+            self, self.controller.view.get_frame().get_footer()))
+        return True
 
 
 class HandleUserInputState(State):
@@ -318,7 +326,7 @@
         self.state      = state
         self.footer     = footer
 
-    def keypress(self, key):
+    def handle_input(self, key):
         logger.debug("HandleUserInputState: handle key '%r'" % key)
         pos = self.footer.edit_pos
         keys = self.config.get_keybinding()
@@ -329,27 +337,32 @@
             return self.enter()
         elif 'left' in key:
             self.footer.set_edit_pos(pos-1)
+            return True
         elif 'right' in key:
             self.footer.set_edit_pos(pos+1)
+            return True
         elif 'backspace' in key:
             text = self.footer.edit_text
             self.footer.set_edit_text(
                 '%s%s' % (text[0:pos-1], text[pos:len(text)]))
             self.footer.set_edit_pos(pos-1)
+            return True
         elif 'delete' in key:
             text = self.footer.edit_text
             self.footer.set_edit_text(
                 '%s%s' % (text[0:pos], text[pos+1:len(text)]))
             self.footer.set_edit_pos(pos)
+            return True
         elif len(key) >= 1 and len(key[0]) == 1:
             return self.insert(key)
-        return self
+        return False
 
     def enter(self):
         raise Exception("Not implemented")
 
     def exit(self):
-        return self.state
+        self.set_next_state(self.state)
+        return True
 
     def insert(self, key):
         logger.debug("Enter key: %r" % key)
@@ -360,7 +373,7 @@
         if not isinstance(text, unicode):
             text = unicode(text, locale.getpreferredencoding())
         self.footer.insert_text(text)
-        return self
+        return True
 
 
 class BaseTimeState(HandleUserInputState):
@@ -371,7 +384,7 @@
 
     def exit(self):
         self.view._total_time()
-        return self.state
+        return super(BaseTimeState, self).exit()
 
     def insert(self, key):
         if key[0] in ['0','1','2','3','4','5','6','7','8','9']:
@@ -379,7 +392,7 @@
         else:
             logger.debug("BaseTimeState: invalid character for "\
                          "adding/subtracting time: '%r'" % key)
-        return self
+        return True
 
 
 class AddTimeState(BaseTimeState):
@@ -391,7 +404,8 @@
         logger.info("AddTimeState: add %d minutes to project '%s'"
                     % (minutes, project.desc))
         self.view._total_time()
-        return self.state
+        self.set_next_state(self.state)
+        return True
 
 
 class SubtractTimeState(BaseTimeState):
@@ -407,7 +421,8 @@
         logger.info("SubtractTimeState: subtract %d minutes from project '%s'"
                     % (minutes, project.desc))
         self.view._total_time()
-        return self.state
+        self.set_next_state(self.state)
+        return True
 
 
 class DescriptionProjectsState(HandleUserInputState):
@@ -421,7 +436,8 @@
             return self
         self.controller.stop_project(text)
         self.controller.view.set_footer_text(self.msg('choose_proj'), 'question')
-        return PausedProjectsState(self.controller, self.view)
+        self.set_next_state(PausedProjectsState(self.controller, self.view))
+        return True
 
     def exit(self):
         project = self.view.item_in_focus()
@@ -430,7 +446,7 @@
             self.state.sec = time
             signal.signal(signal.SIGALRM, self.state.handle_signal)
             signal.alarm(1)
-        return self.state
+        return super(DescriptionProjectsState, self).exit()
 
 
 class EntryListState(State):
@@ -438,31 +454,22 @@
         super(EntryListState, self).__init__(controller, view)
         self.projectlist_state = state
 
-    def keypress(self, key):
+    def handle_input(self, key):
         logger.debug("EntryListState: pressed key '%r'" % key)
         keys = self.config.get_keybinding()
         if keys.get_switch_lists() in key:
             self.view.clear()
-            return self.projectlist_state
-        if keys.get_entry_up() in key:
-            return self.up()
-        if keys.get_entry_down() in key:
-            return self.down()
+            self.set_next_state(self.projectlist_state)
+            self.controller.view.set_focus(0)
+            return True
+
         if keys.get_enter() in key:
             return self.select()
-        return None
-
-    def up(self):
-        self.view.up()
-        return self
-
-    def down(self):
-        self.view.down()
-        return self
+        return False
 
     def select(self):
         self.view.select()
-        return self
+        return True
 
     def renew_focus(self):
         e_len = self.view.row_count()
@@ -474,34 +481,43 @@
 
 
 class DefaultEntryListState(EntryListState):
-    def keypress(self, key):
-        ret = super(DefaultEntryListState, self).keypress(key)
+
+    def handle_input(self, key):
+        logger.info("Handling DefaultEntryListState input")
+        ret = super(DefaultEntryListState, self).handle_input(key)
         if ret:
             return ret
 
         keys = self.config.get_keybinding()
         if keys.get_escape() in key:
             self.view.clear()
-            return self.projectlist_state
+            self.set_next_state(self.projectlist_state)
+            return True
 
         if keys.get_entry_delete() in key:
             if self.view.selection:
-                return DeleteEntryState(self.projectlist_state,
-                                        self.controller, self.view)
+                self.set_next_state(DeleteEntryState(self.projectlist_state,
+                    self.controller, self.view))
             else:
                 entry = self.view.item_in_focus()
-                return DeleteEntryState(self.projectlist_state,
-                                        self.controller, self.view, [entry])
+                self.set_next_state(DeleteEntryState(self.projectlist_state,
+                    self.controller, self.view, [entry]))
+            return True
+
         if keys.get_entry_move() in key:
             if self.view.selection:
-                return MoveEntryState(self.projectlist_state,
-                                      self.controller, self.view)
+                self.set_next_state(MoveEntryState(self.projectlist_state,
+                    self.controller, self.view))
+            return True
+
         if keys.get_entry_edit() in key:
             entry = self.view.item_in_focus()
             if entry:
-                return EditEntryState(self.projectlist_state,
-                                      self.controller, self.view, entry)
-        return self
+                self.set_next_state(EditEntryState(self.projectlist_state,
+                    self.controller, self.view, entry))
+            return True
+
+        return False
 
 
 class DeleteEntryState(EntryListState):
@@ -516,21 +532,23 @@
         if not self.entries:
             self.entries = [x.item for x in self.view.selection]
 
-    def keypress(self, key):
+    def handle_input(self, key):
         if 'y' in key:
             if self.entries:
                 self.controller.delete_entries(self.entries)
                 self.renew_focus()
             self.view.set_footer_text("", 'entry_footer')
-            return DefaultEntryListState(self.projectlist_state,
-                                         self.controller, self.view)
+            self.set_next_state(DefaultEntryListState(self.projectlist_state,
+                self.controller, self.view))
+            return True
 
         if 'n' in key:
             self.view.set_footer_text("", 'entry_footer')
-            return DefaultEntryListState(self.projectlist_state,
-                                         self.controller, self.view)
+            self.set_next_state(DefaultEntryListState(self.projectlist_state,
+                self.controller, self.view))
+            return True
 
-        return self
+        return False
 
 
 class MoveEntryState(EntryListState):
@@ -567,7 +585,7 @@
             self.view.set_footer_text(self.msg('really'), 'question')
 
 
-    def keypress(self, key):
+    def handle_input(self, key):
         keys = self.config.get_keybinding()
         if 'y' in key and self.proj:
             logger.debug("MoveEntryState: move selected entries.")
@@ -575,28 +593,32 @@
             self.renew_focus()
             self.view.set_footer_text('', 'entry_footer')
             self.proj = None
-            return DefaultEntryListState(self.projectlist_state,
-                                         self.controller, self.view)
+            self.set_next_state(DefaultEntryListState(self.projectlist_state,
+                self.controller, self.view))
+            return True
 
         if 'n' in key and self.proj:
             self.view.set_footer_text('', 'entry_footer')
             self.reset_project_footer()
-            return DefaultEntryListState(self.projectlist_state,
-                                         self.controller, self.view)
+            self.set_next_state(DefaultEntryListState(self.projectlist_state,
+                self.controller, self.view))
+            return True
 
         if keys.get_escape() in key:
             self.view.set_footer_text('', 'entry_footer')
             self.reset_project_footer()
-            return DefaultEntryListState(self.projectlist_state,
-                                         self.controller, self.view)
+            self.set_next_state(DefaultEntryListState(self.projectlist_state,
+                self.controller, self.view))
+            return True
         if 'backspace' in key:
             if len(self.proj_keys) > 0:
                 self.proj_keys = self.proj_keys[:-1]
                 self.set_project_footer()
-            return self
+            return True
 
         if keys.get_enter() in key and self.proj is None:
             self.select_project()
+            return True
 
         if len(key) > 0 and len(key[0]) == 1 and self.proj is None:
             proj_key = self.proj_keys + key[0]
@@ -606,8 +628,9 @@
                 self.set_project_footer()
                 if num == 1:
                     self.select_project()
+            return True
 
-        return self
+        return False
 
 
 class AlterProjectState(HandleUserInputState):
@@ -622,7 +645,8 @@
 
     def exit(self):
         self.controller.view.set_footer_text(self.msg('choose_proj'), 'question')
-        return PausedProjectsState(self.controller, self.view)
+        self.set_next_state(PausedProjectsState(self.controller, self.view))
+        return True
 
 
 class AddProjectKeyState(AlterProjectState):
@@ -641,8 +665,10 @@
     def enter(self):
         key = self.footer.get_edit_text()
         if key == '':
-            return self
-        return AddProjectDescriptionState(self.controller, self.view, key)
+            return True
+        self.set_next_state(AddProjectDescriptionState(self.controller,
+            self.view, key))
+        return True
 
 
 class AddProjectDescriptionState(AlterProjectState):
@@ -664,7 +690,8 @@
             return self
         self.controller.add_project(self.key, description)
         self.controller.view.set_footer_text(self.msg('choose_proj'), 'question')
-        return PausedProjectsState(self.controller, self.view)
+        self.set_next_state(PausedProjectsState(self.controller, self.view))
+        return True
 
 
 class EditEntryState(HandleUserInputState):
@@ -696,7 +723,9 @@
 
     def exit(self):
         self.view.set_footer_text("", 'entry_footer', False)
-        return DefaultEntryListState(self.state, self.controller, self.view)
+        self.set_next_state(DefaultEntryListState(self.state, self.controller,
+            self.view))
+        return True
 
 
 class ProjectEditKeyState(AlterProjectState):
@@ -719,10 +748,11 @@
     def enter(self):
         key = self.footer.get_edit_text()
         if key == '':
-            return self
+            return True
         self.project.key = key
-        return ProjectEditDescriptionState(self.controller, self.view,
-                self.project)
+        self.set_next_state(ProjectEditDescriptionState(self.controller,
+            self.view, self.project))
+        return True
 
 
 class ProjectEditDescriptionState(AlterProjectState):
@@ -748,4 +778,5 @@
         self.project.desc = description
         self.controller.update_project(self.project)
         self.controller.view.set_footer_text(self.msg('choose_proj'), 'question')
-        return PausedProjectsState(self.controller, self.view)
+        self.set_next_state(PausedProjectsState(self.controller, self.view))
+        return True
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)