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()
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)