Mercurial > getan > getan
view getan/controller.py @ 199:3fa4ab9146dd
Implement three phase user input handling
First the state is able to filter keys. Afterwards the MainLoop widget is
allowed to act on keypress. At last the state is allowed to react on keys.
author | Björn Ricks <bjoern.ricks@intevation.de> |
---|---|
date | Fri, 05 Apr 2013 19:29:33 +0200 |
parents | 9f85ffa0a2f6 |
children | 2987c6991005 |
line wrap: on
line source
# -*- coding: utf-8 -*- # # (c) 2010 by Ingo Weinzierl <ingo.weinzierl@intevation.de> # (c) 2011 by Björn Ricks <bjoern.ricks@intevation.de> # # A python worklog-alike to log what you have 'getan' (done). # # 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 urwid from datetime import datetime from getan.view import GetanView from getan.states import PausedProjectsState from getan.utils import format_time from getan.config import Config logger = logging.getLogger() class GetanController(object): def __init__(self, backend, pv_class, ev_class): self.ev_class = ev_class self.pv_class = pv_class self.config = Config() self.backend = backend projects, entries = self.load_projects() self.projects = projects self.running = [] self.project_view = pv_class(self, self.projects) self.entries_view = ev_class(entries) self.view = GetanView(self, self.project_view, self.entries_view) self.state = PausedProjectsState(self, self.project_view) def main(self): self.loop = urwid.MainLoop(self.view.get_frame(), self.view.get_palette(), screen=urwid.raw_display.Screen(), input_filter=self.input_filter) self.loop.run() def input_filter(self, input, raw_input): if 'window resize' in input: self.view.loop.screen_size = None self.view.loop.draw_screen() else: input = self.state.input_filter(input, raw_input) self.loop.process_input(input) self.state.handle_input(input) def load_projects(self): projects = self.backend.load_projects() if projects: entries = self.backend.load_entries(projects[0].id) else: entries = [] return (projects, entries) def update_entries(self, project): logger.debug("GetanController: update entries.") if project: entries = self.backend.load_entries(project.id) else: entries = [] self.entries_view.set_rows(entries) self.view.update_view() def move_selected_entries(self, project): old_project = None entries = [] try: while self.entries_view.selection: node = self.entries_view.selection.pop() if node.selected: node.select() entries.append(node.item) logger.info("GetanController: move entry '%s' (id = %d, "\ "project id = %d) to project '%s'" % (node.item.desc, node.item.id, node.item.project_id, project.desc)) if not old_project: old_project = self.project_by_id(node.item.project_id) finally: self.backend.move_entries(entries, project.id) if not old_project: return project.entries = self.backend.load_entries(project.id) old_project.entries = self.backend.load_entries(old_project.id) self.update_entries(old_project) self.project_view.update_all() def delete_entries(self, entry_nodes): if not entry_nodes: return proj = self.project_by_id(entry_nodes[0].project_id) entries = entry_nodes self.backend.delete_entries(entries) proj.entries = self.backend.load_entries(proj.id) self.update_entries(proj) self.project_view.update() def update_project_list(self): self.project_view.update() self.view.update_view() def project_by_key(self, key): for proj in self.projects: if proj.key == key: return proj return None def project_by_id(self, id): for proj in self.projects: if proj.id == id: return proj return None def find_projects_by_key(self, key): projects = [] for proj in self.projects: if proj.key.startswith(key): projects.append(proj) return projects def start_project(self, project): if not project: return self.running.append(project) project.start = datetime.now() logger.info("Start project '%s' at %s." % (project.desc, format_time(datetime.now()))) self.view.set_footer_text(" Running on '%s'" % project.desc, 'running') logger.debug('All running projects: %r' % self.running) def stop_project(self, desc='-no description-', display=True): if not self.running: return project = self.running.pop() if not project: return logger.info("Stop project '%s' at %s." % (project.desc, format_time(datetime.now()))) project.stop = datetime.now() self.backend.insert_project_entry(project, datetime.now(), desc) if display: self.update_entries(project) self.update_project_list() logger.debug('Still running projects: %r' % self.running) def add_project(self, key, description): if not key or not description: return self.backend.insert_project(key, description) self.update_projects() self.update_project_list() def update_entry(self, entry): self.backend.update_entry(entry) def shutdown(self): for project in self.running: self.stop_project(display=False) def update_project(self, project): self.backend.update_project(project) self.update_projects() self.update_project_list() def update_projects(self): projects, entries = self.load_projects() self.projects = projects self.project_view.load_rows(projects) def get_config(self): return self.config def exit(self): logger.info("GetanController: exit.") raise urwid.ExitMainLoop()