bjoern@112: # -*- coding: utf-8 -*- bjoern@112: # bjoern@112: # (c) 2010 by Ingo Weinzierl bjoern@112: # (c) 2011 by Björn Ricks mschieder@488: # (c) 2017, 2018 Intevation GmbH mschieder@488: # Authors: mschieder@488: # * Magnus Schieder bjoern@112: # bjoern@112: # A python worklog-alike to log what you have 'getan' (done). bjoern@112: # bjoern@112: # This is Free Software licensed under the terms of GPLv3 or later. bjoern@112: # For details see LICENSE coming with the source of 'getan'. bjoern@112: # bjoern@112: bjoern@112: import logging bjoern@194: import urwid bjoern@194: bjoern@297: from datetime import datetime bjoern@112: bjoern@318: from getan.view import GetanView, ProjectList, EntryList bjoern@112: from getan.states import PausedProjectsState bjoern@112: from getan.utils import format_time bjoern@149: from getan.config import Config bjoern@112: bjoern@112: logger = logging.getLogger() bjoern@112: bjoern@297: bjoern@136: class GetanController(object): bjoern@136: bjoern@318: def __init__(self, backend): bjoern@149: self.config = Config() bjoern@149: bjoern@297: self.backend = backend bjoern@112: projects, entries = self.load_projects() mschieder@499: self.load_recover() bjoern@112: self.projects = projects bjoern@297: self.running = [] bjoern@112: mschieder@499: bjoern@203: self.view = None bjoern@318: self.entries_view = EntryList(entries) bjoern@318: self.project_view = ProjectList(self, self.projects) bjoern@112: bjoern@297: self.view = GetanView(self, self.project_view, self.entries_view) bjoern@112: self.state = PausedProjectsState(self, self.project_view) bjoern@112: bjoern@112: def main(self): bjoern@320: theme = self.config.get_theme() bjoern@229: self.loop = urwid.MainLoop(self.view, bjoern@320: theme.get_palette(), bjoern@194: screen=urwid.raw_display.Screen(), bjoern@194: input_filter=self.input_filter) bjoern@194: self.loop.run() bjoern@112: mschieder@479: def redraw(self): mschieder@479: self.loop.stop() mschieder@479: self.loop.start() mschieder@479: self.loop.screen_size = None mschieder@479: self.loop.draw_screen() mschieder@479: bjoern@112: def input_filter(self, input, raw_input): bjoern@112: if 'window resize' in input: bjoern@255: self.loop.screen_size = None bjoern@255: self.loop.draw_screen() bjoern@112: else: bjoern@199: self.loop.process_input(input) bjoern@199: self.state.handle_input(input) bjoern@112: bjoern@112: def load_projects(self): bjoern@112: projects = self.backend.load_projects() bjoern@112: if projects: bjoern@112: entries = self.backend.load_entries(projects[0].id) bjoern@112: else: bjoern@112: entries = [] bjoern@112: return (projects, entries) bjoern@112: mschieder@499: def load_recover(self): mschieder@499: self.backend.load_recover() mschieder@499: bjoern@112: def update_entries(self, project): bjoern@297: logger.debug("GetanController: update entries for project %s." % bjoern@297: project.id) bjoern@314: bjoern@362: project.load_entries() bjoern@314: bjoern@204: if self.view: bjoern@362: self.view.update_entries(project.entries) bjoern@112: bjoern@238: def move_entries(self, entries, project): bjoern@238: old_project = self.project_by_id(entries[0].project_id) bjoern@238: self.backend.move_entries(entries, project.id) bjoern@238: self.update_entries(old_project) mschieder@471: self.update_projects() bjoern@238: self.project_view.update_rows() mschieder@471: open_project = self.project_by_id(old_project.id) mschieder@471: open_project.open = True bjoern@238: bjoern@112: def delete_entries(self, entry_nodes): bjoern@112: if not entry_nodes: bjoern@112: return bjoern@314: proj_id = entry_nodes[0].project_id bjoern@314: proj = self.project_by_id(proj_id) bjoern@314: if proj: bjoern@314: entries = entry_nodes bjoern@314: self.backend.delete_entries(entries) bjoern@314: self.update_entries(proj) bjoern@112: bjoern@112: def project_by_key(self, key): bjoern@112: for proj in self.projects: bjoern@112: if proj.key == key: bjoern@112: return proj bjoern@112: return None bjoern@112: bjoern@112: def project_by_id(self, id): bjoern@112: for proj in self.projects: bjoern@112: if proj.id == id: bjoern@112: return proj bjoern@112: return None bjoern@112: bjoern@154: def find_projects_by_key(self, key): bjoern@154: projects = [] bjoern@154: for proj in self.projects: bjoern@154: if proj.key.startswith(key): bjoern@154: projects.append(proj) bjoern@154: return projects bjoern@154: bjoern@112: def start_project(self, project): bjoern@135: if not project: bjoern@135: return bjoern@112: self.running.append(project) bjoern@112: project.start = datetime.now() bjoern@112: logger.info("Start project '%s' at %s." bjoern@112: % (project.desc, format_time(datetime.now()))) bjoern@112: self.view.set_footer_text(" Running on '%s'" % project.desc, 'running') bjoern@112: logger.debug('All running projects: %r' % self.running) bjoern@112: bjoern@316: def stop_project(self, desc=None, display=True): bjoern@316: desc = desc or '-no description-' bjoern@135: if not self.running: bjoern@135: return bjoern@112: project = self.running.pop() bjoern@135: if not project: bjoern@135: return bjoern@112: logger.info("Stop project '%s' at %s." bjoern@112: % (project.desc, format_time(datetime.now()))) bjoern@112: project.stop = datetime.now() bjoern@112: self.backend.insert_project_entry(project, datetime.now(), desc) bjoern@112: if display: bjoern@112: self.update_entries(project) bjoern@112: logger.debug('Still running projects: %r' % self.running) bjoern@112: mschieder@499: def save_recovery_data(self): mschieder@499: desc = '-no description-' mschieder@499: if not self.running: mschieder@499: return mschieder@499: project = self.running[-1] mschieder@499: if not project: mschieder@499: return mschieder@499: project.stop = datetime.now() mschieder@499: self.backend.insert_recover(project, datetime.now(), desc) mschieder@499: bjoern@112: def add_project(self, key, description): bjoern@112: if not key or not description: bjoern@112: return bjoern@112: self.backend.insert_project(key, description) bjoern@112: self.update_projects() bjoern@112: bjoern@112: def update_entry(self, entry): bjoern@112: self.backend.update_entry(entry) bjoern@112: bjoern@112: def shutdown(self): bjoern@112: for project in self.running: bjoern@112: self.stop_project(display=False) bjoern@112: bjoern@175: def update_project(self, project): bjoern@175: self.backend.update_project(project) bjoern@175: self.update_projects() bjoern@175: bjoern@112: def update_projects(self): bjoern@112: projects, entries = self.load_projects() bjoern@112: self.projects = projects bjoern@112: self.project_view.load_rows(projects) bjoern@266: self.project_view.total_time() bjoern@149: bjoern@149: def get_config(self): bjoern@149: return self.config bjoern@194: bjoern@202: def set_state(self, state): bjoern@202: self.state = state bjoern@202: bjoern@194: def exit(self): bjoern@194: logger.info("GetanController: exit.") bjoern@194: raise urwid.ExitMainLoop()