Mercurial > getan > getan
view getan/states.py @ 100:8f433e3c2f21
Allow to pass entries to the DeleteEntryState
By default DeleteEntryState uses the selected entries if no entry is passes
to the constructor. This allows to reuse the state class for single entry
deletion
author | Björn Ricks <bjoern.ricks@intevation.de> |
---|---|
date | Mon, 12 Sep 2011 14:05:34 +0200 |
parents | 7c3f43bfc0a8 |
children | df98b84d22f9 |
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 'd' in key: if self.view.selection: return DeleteEntryState(self.projectlist_state, self.controller, self.view) 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): ret = super(DeleteEntryState, self).keypress(key) if ret: return ret 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? (> %s) (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') 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') return DefaultEntryListState(self.projectlist_state, self.controller, self.view) if 'esc' in key: self.view.set_footer_text('', 'entry_footer') return DefaultEntryListState(self.projectlist_state, self.controller, self.view) if len(key) > 0 and self.proj is None: self.proj = self.controller.project_by_key(key[0]) if self.proj: 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)