Mercurial > getan > getan
view getan/view.py @ 24:c89721a3f0f8
Bugfix: switching the time mode in ProjectList will also update the displayed total time in the footer of ProjectList.
author | Ingo Weinzierl <ingo_weinzierl@web.de> |
---|---|
date | Sun, 29 Aug 2010 19:10:48 +0200 |
parents | 9c4e8ba3c4fa |
children | 155b23da504b |
line wrap: on
line source
#!/usr/bin/env python # -*- coding: utf-8 -*- # # (c) 2010 by Ingo Weinzierl <ingo.weinzierl@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 urwid import urwid.raw_display from getan.states import * from getan.utils import short_time, format_datetime, format_time APP_TITLE = u" .: getan next generation :." APP_REALLY_QUIT = u" Wollen Sie wirklich beenden? " APP_CHOOSE_PROJECT = u" Wählen Sie ein Projekt: " PROJECTS_TITLE = u" Liste registrierter Projekte" ENTRIES_TITLE = u" Liste der letzten Einträge" logger = logging.getLogger() class ListWidget(urwid.BoxWidget): def _update_view(self): logger.debug("ListWidget: update view now.") self.frame.set_body(self.body) self.frame.set_footer(self.footer) self.frame.set_header(self.header) def update_focus(self, focus, unfocus=-1): logger.debug("ListWidget: focus row (index = %d)" % focus) logger.debug("ListWidget: unfocus row (index = %d)" % unfocus) if focus >= 0 and focus <= len(self.rows)-1: self.rows[focus].focus = True self.rows[focus].update_w() if unfocus >= 0: self.rows[unfocus].focus = False self.rows[unfocus].update_w() def render(self, size, focus=False): maxcol, maxrow = size return self.frame.render((maxcol, maxrow), focus) def set_footer_text(self, text, attr, edit=False): if edit: logger.debug("ListWidget: set footer text (edit) = '%s'" % text) self.frame.set_footer(urwid.AttrWrap(urwid.Edit(text),attr)) else: logger.debug("ListWidget: set footer text = '%s'" % text) self.frame.set_footer(urwid.AttrWrap(urwid.Text(text),attr)) def row_count(self): if not self.rows: return 0 return len(self.rows) def item_in_focus(self): return self.rows[self.focused].get_item() def up(self): logger.debug("ListWidget: navigate to upper row.") if self.focused > 0: self.focused = self.focused - 1 self.update_focus(self.focused, self.focused+1) def down(self): logger.debug("ListWidget: navigate to lower row.") if self.focused < len(self.rows) - 1: self.focused = self.focused + 1 self.update_focus(self.focused, self.focused-1) def select(self): node = self.rows[self.focused] logger.debug("ListWidget: select row '%s'" % self.focused) node.select() if node.selected: self.selection.append(node) else: if node in self.selection: self.selection.pop() logger.debug("ListWidget: all selected rows: %r" % self.selection) return node def clear(self): logger.debug("EntryList: clear focus and selection of all entries.") for node in self.selection: if node.selected: node.select() self.update_focus(-1, self.focused) self.focused = False class ProjectNode(urwid.WidgetWrap): MODES = [ (0, 'Gesamt'), (1, 'Jahr'), (2, 'Monat'), (3, 'Woche'), (4, 'Tag') ] def __init__(self, proj, mode=3): self.selected = False self.focus = False self.mode = self.MODES[mode] self.item = proj w = self.update() self.__super.__init__(w) self.update_w() def update(self): logger.debug("Update ProjectNode '%s'" % self.item.desc) time_str = self._get_formatted_time() description = urwid.Text('%s %s' % (self.item.key, self.item.desc)) time = urwid.Text('%s (%s)' % (self.mode[1], time_str)) self.widget = urwid.AttrWrap(urwid.Columns([description, time]),None) self._w = self.widget self.update_w() return self._w def _get_formatted_time(self): return human_time(self._get_time()) def _get_time(self): if self.mode == self.MODES[0]: return self.item.total if self.mode == self.MODES[1]: return self.item.year() if self.mode == self.MODES[2]: return self.item.month() if self.mode == self.MODES[3]: return self.item.week() if self.mode == self.MODES[4]: return self.item.day() return self.item.week() def get_item(self): return self.item def switch_time_mode(self): tmp = self.mode[0] + 1 if tmp > 4: self.mode = self.MODES[0] else: self.mode = self.MODES[tmp] self.update() def update_w(self): if self.focus: if self.selected: self._w.focus_attr = 'selected focus' self._w.attr = 'selected focus' else: self._w.focus_attr = 'focus' self._w.attr = 'focus' else: if self.selected: self._w.focus_attr = 'selected' self._w.attr = 'selected' else: self._w.focus_attr = 'body' self._w.attr = 'body' def select(self): self.selected = not self.selected self.update_w() class ProjectList(ListWidget): def __init__(self, controller, rows): self.selection = [] self.focused = 0 self.controller = controller self.raw_projects = rows self.head = urwid.LineBox( urwid.AttrWrap(urwid.Text("\n%s\n" % PROJECTS_TITLE),'project_header')) self.foot = urwid.Edit() self.rows = [ProjectNode(x) for x in rows] self.listbox = urwid.ListBox(urwid.SimpleListWalker(self.rows)) self.body = urwid.LineBox(urwid.Padding(urwid.AttrWrap( self.listbox, 'entries'),('fixed left',1),('fixed right',1))) self.frame = urwid.Frame(self.body, header=self.head, footer=self.foot) self.update_focus(self.focused) self._total_time() def _total_time(self): logger.debug("ProjectList: update projects total time.") total = 0 for proj in self.rows: total += proj._get_time() self.frame.set_footer(urwid.AttrWrap( urwid.Text(' Alle Projekte: %s %s' % (proj.mode[1],human_time(total))), 'project_footer')) def update(self): logger.debug("ProjectList: update focused project row now.") self.rows[self.focused].update() self._total_time() self.controller.view.loop.draw_screen() def update_all(self): logger.debug("ProjectList: update all project rows now.") for proj in self.rows: proj.update() self._total_time() self.controller.view.loop.draw_screen() def switch_time_mode(self): logger.debug("ProjectList: switch time mode now.") for proj in self.rows: proj.switch_time_mode() self._total_time() self.controller.view.loop.draw_screen() def unhandled_keypress(self, key): logger.debug("ProjectList: unhandled keypress '%r'" % key) def select_project(self, project): for proj_node in self.rows: if proj_node.project.key == project.key: idx = self.rows.index(proj_node) self.update_focus(idx, self.focused) self.focused = idx self.select() break class EntryNode(urwid.WidgetWrap): def __init__(self, entry): self.selected = False self.focus = False self.item = entry w = self.update() self.__super.__init__(w) self.update_w() def update(self): logger.debug("EntryNode: update entry '%s'." % self.item.desc) row = urwid.Text(' %s [%s] %s' \ % (format_datetime(self.item.start), short_time(self.item.duration().seconds), self.item.desc), wrap='clip') self.widget = urwid.AttrWrap(row, None) self._w = self.widget self.update_w() return self._w def update_w(self): if self.focus: if self.selected: self._w.focus_attr = 'selected focus entry' self._w.attr = 'selected focus entry' else: self._w.focus_attr = 'focus entry' self._w.attr = 'focus entry' else: if self.selected: self._w.focus_attr = 'selected entry' self._w.attr = 'selected entry' else: self._w.focus_attr = 'entry body' self._w.attr = 'entry body' def select(self): logger.debug("EntryNode: update selection of entry '%s'" % self.item.desc) self.selected = not self.selected self.update_w() class EntryList(ListWidget): def __init__(self, rows): self.selection = [] self.focused = 0 self.rows = [EntryNode(x) for x in rows] listbox = urwid.ListBox(urwid.SimpleListWalker(self.rows)) self.body = urwid.LineBox(urwid.Padding(urwid.AttrWrap( listbox, 'entry_body'), ('fixed left', 1), ('fixed right', 1))) self.header = urwid.LineBox(urwid.AttrWrap(urwid.Text( "\n%s\n" % ENTRIES_TITLE),'entry_header')) self.footer = urwid.AttrWrap(urwid.Text(""), 'entry_footer') self.frame = urwid.Frame(self.body, header=self.header, footer=self.footer) def set_rows(self, rows): logger.debug("EntryList: set new entries.") self.rows = [EntryNode(x) for x in rows] listbox = urwid.LineBox(urwid.ListBox(urwid.SimpleListWalker( self.rows))) self.body = urwid.AttrWrap(listbox, 'entry_body') self._update_view() class GetanView: palette = [ ('header', 'white', 'dark blue'), ('project_header', 'white', 'dark cyan'), ('entry_header', 'white', 'dark cyan'), ('footer', 'yellow', 'dark blue'), ('entry_footer', 'white', 'dark blue'), ('project_footer', 'white', 'dark blue'), ('body', 'white', 'black'), ('entry body', 'white', 'dark blue'), ('entries', 'white', 'black'), ('entry_body', 'white', 'dark blue'), ('focused entry', 'white', 'dark cyan'), ('selected entry', 'yellow', 'light cyan'), ('selected focus entry', 'yellow', 'dark cyan'), ('info', 'white', 'dark red'), ('focus', 'white', 'dark blue'), ('selected', 'black', 'light green'), ('selected focus', 'yellow', 'dark cyan'), ('question', 'white', 'dark red'), ('running', 'yellow', 'dark green'), ('paused_running', 'white', 'dark red'), ] def __init__(self, controller, proj_list, entr_list): urwid.set_encoding("UTF-8") self.controller = controller self.proj_list = proj_list self.entr_list = entr_list self.columns = urwid.Columns([ urwid.Padding(self.proj_list, ('fixed left',0),('fixed right',1)), self.entr_list], 0) self.header = urwid.AttrWrap(urwid.Text('%s\n' % APP_TITLE), 'header') self.footer = urwid.AttrWrap(urwid.Text(APP_CHOOSE_PROJECT), 'question') self.col_list = self.columns.widget_list view = urwid.AttrWrap(self.columns, 'body') self.view = urwid.Frame(view, header=self.header,footer=self.footer) self.state = PausedProjectsState(controller, self.proj_list) def update_view(self): logger.debug("GetanView: update view now.") view = urwid.AttrWrap(self.columns, 'body') self.view.set_body(view) self.loop.draw_screen() def get_frame(self): return self.view def set_footer_text(self, text, attr, edit=False): if edit: logger.debug("GetanView: set footer text (edit): '%s'" % text) self.view.set_footer(urwid.AttrWrap(urwid.Edit(text),attr)) else: logger.debug("GetanView: set footer text: '%s'" % text) self.view.set_footer(urwid.AttrWrap(urwid.Text(text),attr)) def run(self): self.loop = urwid.MainLoop(self.view, self.palette, screen=urwid.raw_display.Screen(), unhandled_input=self.controller.unhandled_keypress, input_filter=self.controller.input_filter) self.loop.run() def unhandled_keypress(self, k): logger.warn("GetanView: unhandled keypress '%r'" % k) def exit(self): logger.info("GetanView: shutdown view.") raise urwid.ExitMainLoop()