Mercurial > getan > getan
view getan/states.py @ 137:5a4946fd9e6d
Update whitespace
author | Björn Ricks <bjoern.ricks@intevation.de> |
---|---|
date | Wed, 31 Oct 2012 14:22:43 +0100 |
parents | ce707fbb9666 |
children | bb6ddef4f88f |
line wrap: on
line source
#!/usr/bin/env python # -*- coding: utf-8 -*- # # (c) 2010 by Ingo Weinzierl <ingo.weinzierl@intevation.de> # (c) 2011 by Björn Ricks <bjoern.ricks@intevation.de> # # This is Free Software licensed under the terms of GPLv3 or later. # For details see LICENSE coming with the source of 'getan'. # import logging import signal from datetime import datetime, timedelta from getan.resources import gettext as _ from getan.utils import human_time, safe_int logger = logging.getLogger() class State(object): messages = { } def __init__(self, controller, view): self.controller = controller self.view = view def msg(self, key): return self.messages[key] class ProjectState(State): def keypress(self, key): logger.debug("ProjectState: handle key '%r'" % key) if 'f1' in key: self.view.switch_time_mode() return self if 'tab' in key: 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 'up' in key: return self.up() if '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 class PausedProjectsState(ProjectState): messages = { 'choose_proj': _('Choose a project: '), } def keypress(self, key): logger.debug("PausedProjectsState: handle key '%r'" % key) ret = super(PausedProjectsState, self).keypress(key) if ret: return ret if 'enter' in key: return self.select() if 'insert' in key: return AddProjectNameState(self.controller, self.view) if 'esc' in key: return ExitState(self.controller, self.view) else: if len(key) > 0 and len(key[0]) == 1: select_proj = SelectProjectState(self.controller, self.view, key[0]) return select_proj.check_key() return self def select(self): proj = self.view.item_in_focus() self.controller.start_project(proj) return RunningProjectsState(self.controller, self.view, proj) class SelectProjectState(State): def __init__(self, controller, view, key): super(SelectProjectState, self).__init__(controller, view) self.proj_keys = key self.set_footer_text() def reset(self): self.view.set_footer_text("", "entry_footer") def set_footer_text(self): self.view.set_footer_text("Selecting project from key: %s" % self.proj_keys, "running") def check_key(self): proj = self.controller.project_by_key(self.proj_keys) if proj: self.reset() self.view.select_project(proj) 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 def keypress(self, key): if 'esc' in key: self.reset() return PausedProjectsState(self.controller, self.view) else: if len(key) > 0 and len(key[0]) == 1: self.proj_keys += key[0] self.set_footer_text() return self.check_key() return self class ExitState(ProjectState): messages = { 'quit' : _(" Really quit? (y/n)"), 'choose': _(" Choose a project:") } def __init__(self, controller, view): super(ExitState, self).__init__(controller, view) self.controller.view.set_footer_text(self.msg('quit'), 'question') def keypress(self, key): logger.debug("ExitState: handle key '%r'" % key) ret = super(ExitState, self).keypress(key) if ret: return ret if 'y' in key or 'Y' in key: self.controller.exit() if 'n' in key or 'N' in key: self.controller.view.set_footer_text(self.msg('choose'), 'question') return PausedProjectsState(self.controller, self.view) return self class RunningProjectsState(ProjectState): messages = { 'description': _("Enter a description: "), 'add_time' : _("Enter time to add [min]: "), 'min_time' : _("Enter time to subtract [min]: "), 'continue' : _("Press 'Space' to continue."), 'running' : _("Running ( %s ) on '%s'."), 'paused' : _(" Break ( %s )%s."), } sec = 0 break_start = None def __init__(self, controller, view, project): super(RunningProjectsState, self).__init__(controller, view) self.project = project signal.signal(signal.SIGALRM, self.handle_signal) signal.alarm(1) def handle_signal(self, signum, frame): proj = self.project if not proj: return if not self.break_start: self.controller.view.set_footer_text(self.msg('running') % (human_time(self.sec), proj.desc), 'running') self.controller.view.loop.draw_screen() self.sec = self.sec + 1 else: self.view.set_footer_text( self.msg('paused') % (human_time((datetime.now()-self.break_start).seconds), self.msg('continue')), 'paused_running') self.controller.view.loop.draw_screen() signal.signal(signal.SIGALRM, self.handle_signal) signal.alarm(1) def keypress(self, key): logger.debug("RunningProjectsState: handle key '%r'" % key) ret = super(RunningProjectsState, self).keypress(key) if ret: return ret if 'enter' in key: return self.stop() if '+' in key: self.view.set_footer_text(self.msg('add_time'), 'question', 1) self.view.frame.set_focus('footer') return AddTimeState(self.controller, self.view, self) if '-' 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) if ' ' in key and not self.break_start: self.break_start = datetime.now() return self if ' ' in key and self.break_start: self.view._total_time() proj = self.project if proj: proj.start += datetime.now() - self.break_start self.break_start = None signal.signal(signal.SIGALRM, self.handle_signal) signal.alarm(1) return self def stop(self): signal.alarm(0) self.view.select() if self.break_start: proj = self.project 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()) class HandleUserInputState(State): def __init__(self, controller, view, state, footer): self.controller = controller self.view = view self.state = state self.footer = footer def keypress(self, key): logger.debug("HandleUserInputState: handle key '%r'" % key) pos = self.footer.edit_pos if 'esc' in key: return self.exit() elif 'enter' in key: return self.enter() elif 'left' in key: self.footer.set_edit_pos(pos-1) elif 'right' in key: self.footer.set_edit_pos(pos+1) 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) 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) elif len(key) >= 1 and len(key[0]) == 1: return self.insert(key) return self def enter(self): raise Exception("Not implemented") def exit(self): return self.state def insert(self, key): logger.debug("Enter key: %r" % key) self.footer.insert_text(key[0]) return self class BaseTimeState(HandleUserInputState): def __init__(self, controller, view, running_state): super(BaseTimeState, self).__init__(controller, view, running_state, view.frame.get_footer()) self.project = running_state.project def exit(self): self.view._total_time() return self.state def insert(self, key): if key[0] in ['0','1','2','3','4','5','6','7','8','9']: self.footer.insert_text(key[0]) else: logger.debug("BaseTimeState: invalid character for "\ "adding/subtracting time: '%r'" % key) return self class AddTimeState(BaseTimeState): def enter(self): minutes = safe_int(self.view.frame.get_footer().get_edit_text()) project = self.project project.start -= timedelta(minutes=minutes) self.state.sec += minutes * 60 logger.info("AddTimeState: add %d minutes to project '%s'" % (minutes, project.desc)) self.view._total_time() return self.state class SubtractTimeState(BaseTimeState): def enter(self): minutes = safe_int(self.view.frame.get_footer().get_edit_text()) sec = minutes * 60 if sec > self.state.sec: self.view._total_time() return self.state project = self.project project.start += timedelta(minutes=minutes) self.state.sec -= sec logger.info("SubtractTimeState: subtract %d minutes from project '%s'" % (minutes, project.desc)) self.view._total_time() return self.state class DescriptionProjectsState(HandleUserInputState): messages = { 'choose_proj': _(" Choose a project."), } def enter(self): text = self.footer.get_edit_text() if text == '': return self self.controller.stop_project(text) self.controller.view.set_footer_text(self.msg('choose_proj'), 'question') return PausedProjectsState(self.controller, self.view) def exit(self): project = self.view.item_in_focus() if project: time = (datetime.now() - project.start).seconds self.state.sec = time signal.signal(signal.SIGALRM, self.state.handle_signal) signal.alarm(1) return self.state class EntryListState(State): def __init__(self, state, controller, view): self.projectlist_state = state self.controller = controller self.view = view def keypress(self, key): logger.debug("EntryListState: pressed key '%r'" % key) if 'tab' in key: self.view.clear() return self.projectlist_state if 'up' in key: return self.up() if 'down' in key: return self.down() if 'enter' in key: return self.select() return None def up(self): self.view.up() return self def down(self): self.view.down() return self def select(self): self.view.select() return self def renew_focus(self): e_len = self.view.row_count() f = self.view.focused if f >= e_len: f = e_len - 1 self.view.focused = f self.view.update_focus(f) class DefaultEntryListState(EntryListState): def keypress(self, key): ret = super(DefaultEntryListState, self).keypress(key) if ret: return ret if 'esc' in key: self.view.clear() return self.projectlist_state if 'd' in key: if self.view.selection: return 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]) if 'm' in key: if self.view.selection: return MoveEntryState(self.projectlist_state, self.controller, self.view) if 'e' in key: entry = self.view.item_in_focus() if entry: return EditEntryState(self.projectlist_state, self.controller, self.view, entry) return self class DeleteEntryState(EntryListState): messages = { 'delete' : _("Really delete this entry? (y/n)"), } def __init__(self, state, controller, view, entries=None): super(DeleteEntryState, self).__init__(state, controller, view) self.view.set_footer_text(self.msg('delete'), 'question') self.entries = entries if not self.entries: self.entries = [x.item for x in self.view.selection] def keypress(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) if 'n' in key: self.view.set_footer_text("", 'entry_footer') return DefaultEntryListState(self.projectlist_state, self.controller, self.view) return self class MoveEntryState(EntryListState): messages = { 'project': _(" Into which project do you want to move these entries?"), 'really': _(" Are you sure? (y/n)"), } proj = None def __init__(self, state, controller, view): super(MoveEntryState, self).__init__(state, controller, view) self.view.set_footer_text(self.msg('project'), 'question') self.proj_keys = "" self.project_view = controller.project_view def set_project_footer(self): self.project_view.set_footer_text("Selecting project from " \ "key: %s" % self.proj_keys, "running") def reset_project_footer(self): self.project_view.reset_footer() def keypress(self, key): if 'y' in key and self.proj: logger.debug("MoveEntryState: move selected entries.") self.controller.move_selected_entries(self.proj) self.renew_focus() self.view.set_footer_text('', 'entry_footer') self.proj = None return DefaultEntryListState(self.projectlist_state, self.controller, self.view) 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) if 'esc' in key: self.view.set_footer_text('', 'entry_footer') self.reset_project_footer() return DefaultEntryListState(self.projectlist_state, self.controller, self.view) if 'backspace' in key: if len(self.proj_keys) > 0: self.proj_keys = self.proj_keys[:-1] self.set_project_footer() return self if len(key) > 0 and len(key[0]) == 1 and self.proj is None: self.proj_keys += key[0] self.set_project_footer() self.proj = self.controller.project_by_key(self.proj_keys) if self.proj: self.reset_project_footer() logger.debug("MoveEntryState: prepared entries to be moved to "\ "project '%s'" % self.proj.desc) self.view.set_footer_text(self.msg('really'), 'question') return self class CreateProjectState(HandleUserInputState): messages = { 'choose_proj': _(' Choose a project.'), } def __init__(self, controller, view): super(CreateProjectState, self).__init__(controller, view, None, controller.view.view.get_footer()) def exit(self): self.controller.view.set_footer_text(self.msg('choose_proj'), 'question') return PausedProjectsState(self.controller, self.view) class AddProjectNameState(CreateProjectState): messages = { 'choose_proj': _(' Choose a project.'), 'proj_name': _('Insert new project name: '), } def __init__(self, controller, view): controller.view.set_footer_text(self.msg('proj_name'), 'question', 1) super(AddProjectNameState, self).__init__(controller, view) self.view.frame.set_focus('footer') def enter(self): project = self.footer.get_edit_text() if project == '': return self return AddProjectKeyState(self.controller, self.view, project) class AddProjectKeyState(CreateProjectState): messages = { 'proj_name': _('Insert new project name: '), 'proj_key': _('Insert key for new project: '), } def __init__(self, controller, view, project): controller.view.set_footer_text(self.msg('proj_key'), 'question', 1) super(AddProjectKeyState, self).__init__(controller, view) self.view.frame.set_focus('footer') self.project = project def enter(self): key = self.footer.get_edit_text() if key == '': return self return AddProjectDescriptionState(self.controller, self.view, self.project, key) class AddProjectDescriptionState(CreateProjectState): messages = { 'proj_description': _('Insert a description for project: '), 'choose_proj': _(" Choose a project.") } def __init__(self, controller, view, project, key): controller.view.set_footer_text(self.msg('proj_description'), 'question', 1) super(AddProjectDescriptionState, self).__init__(controller, view) self.view.frame.set_focus('footer') self.project = project self.key = key def enter(self): description = self.footer.get_edit_text() if description == '': 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) class EditEntryState(HandleUserInputState): messages = { 'edit_entry': _('Edit entry text: '), } def __init__(self, state, controller, view, entry): view.set_footer_text(self.msg('edit_entry'), 'question', True) super(EditEntryState, self).__init__(controller, view, None, view.footer) self.footer.set_edit_text(entry.desc) self.footer.set_edit_pos(len(self.footer.edit_text)) self.view.frame.set_focus('footer') self.entry = entry self.state = state logger.debug("EditEntryState: Entry %s" % entry) def enter(self): entry_desc = self.footer.get_edit_text() if entry_desc == '': return self entry = self.entry entry.desc = entry_desc self.controller.update_entry(entry) self.view.node_in_focus().update() return self.exit() def exit(self): self.view.set_footer_text("", 'entry_footer', False) return DefaultEntryListState(self.state, self.controller, self.view)