diff options
author | Patrick Totzke <patricktotzke@gmail.com> | 2012-08-05 12:28:34 +0100 |
---|---|---|
committer | Patrick Totzke <patricktotzke@gmail.com> | 2012-08-10 13:03:39 +0100 |
commit | 14178c4e59850d4340e116ce29764cbd469c33be (patch) | |
tree | 3e0e47d32c88aeabf17b3250ef2aa5fe7c54fbbe /alot/widgets/globals.py | |
parent | 6c80ee5ecd23ec54604eab3ada0e2573e1757d89 (diff) |
cleanup: split widgets.py and pep8/pyflakes fixes
Diffstat (limited to 'alot/widgets/globals.py')
-rw-r--r-- | alot/widgets/globals.py | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/alot/widgets/globals.py b/alot/widgets/globals.py new file mode 100644 index 00000000..96fec312 --- /dev/null +++ b/alot/widgets/globals.py @@ -0,0 +1,203 @@ +# Copyright (C) 2011-2012 Patrick Totzke <patricktotzke@gmail.com> +# This file is released under the GNU GPL, version 3 or a later revision. +# For further details see the COPYING file + +""" +This contains alot-specific :ref:`urwid.Widgets` used in more than one mode. +""" +import urwid + +from alot.helper import string_decode +from alot.settings import settings +from alot.db.attachment import Attachment + + +class AttachmentWidget(urwid.WidgetWrap): + """ + one-line summary of an :class:`~alot.db.attachment.Attachment`. + """ + def __init__(self, attachment, selectable=True): + self._selectable = selectable + self.attachment = attachment + if not isinstance(attachment, Attachment): + self.attachment = Attachment(self.attachment) + att = settings.get_theming_attribute('thread', 'attachment') + focus_att = settings.get_theming_attribute('thread', + 'attachment_focus') + widget = urwid.AttrMap(urwid.Text(self.attachment.__str__()), + att, focus_att) + urwid.WidgetWrap.__init__(self, widget) + + def get_attachment(self): + return self.attachment + + def selectable(self): + return self._selectable + + def keypress(self, size, key): + return key + + +class ChoiceWidget(urwid.Text): + def __init__(self, choices, callback, cancel=None, select=None): + self.choices = choices + self.callback = callback + self.cancel = cancel + self.select = select + + items = [] + for k, v in choices.items(): + if v == select and select is not None: + items.append('[%s]:%s' % (k, v)) + else: + items.append('(%s):%s' % (k, v)) + urwid.Text.__init__(self, ' '.join(items)) + + def selectable(self): + return True + + def keypress(self, size, key): + if key == 'select' and self.select is not None: + self.callback(self.select) + elif key == 'cancel' and self.cancel is not None: + self.callback(self.cancel) + elif key in self.choices: + self.callback(self.choices[key]) + else: + return key + + +class CompleteEdit(urwid.Edit): + def __init__(self, completer, on_exit, edit_text=u'', + history=None, **kwargs): + self.completer = completer + self.on_exit = on_exit + self.history = list(history) # we temporarily add stuff here + self.historypos = None + + if not isinstance(edit_text, unicode): + edit_text = string_decode(edit_text) + self.start_completion_pos = len(edit_text) + self.completions = None + urwid.Edit.__init__(self, edit_text=edit_text, **kwargs) + + def keypress(self, size, key): + # if we tabcomplete + if key in ['tab', 'shift tab'] and self.completer: + # if not already in completion mode + if not self.completions: + self.completions = [(self.edit_text, self.edit_pos)] + \ + self.completer.complete(self.edit_text, self.edit_pos) + self.focus_in_clist = 1 + else: # otherwise tab through results + if key == 'tab': + self.focus_in_clist += 1 + else: + self.focus_in_clist -= 1 + if len(self.completions) > 1: + ctext, cpos = self.completions[self.focus_in_clist % + len(self.completions)] + self.set_edit_text(ctext) + self.set_edit_pos(cpos) + else: + self.edit_pos += 1 + if self.edit_pos >= len(self.edit_text): + self.edit_text += ' ' + self.completions = None + elif key in ['up', 'down']: + if self.history: + if self.historypos is None: + self.history.append(self.edit_text) + self.historypos = len(self.history) - 1 + if key == 'cursor up': + self.historypos = (self.historypos + 1) % len(self.history) + else: + self.historypos = (self.historypos - 1) % len(self.history) + self.set_edit_text(self.history[self.historypos]) + elif key == 'select': + self.on_exit(self.edit_text) + elif key == 'cancel': + self.on_exit(None) + elif key == 'ctrl a': + self.set_edit_pos(0) + elif key == 'ctrl e': + self.set_edit_pos(len(self.edit_text)) + else: + result = urwid.Edit.keypress(self, size, key) + self.completions = None + return result + + +class HeadersList(urwid.WidgetWrap): + """ renders a pile of header values as key/value list """ + def __init__(self, headerslist, key_attr, value_attr): + self.headers = headerslist + self.key_attr = key_attr + self.value_attr = value_attr + pile = urwid.Pile(self._build_lines(headerslist)) + att = settings.get_theming_attribute('thread', 'header') + pile = urwid.AttrMap(pile, att) + urwid.WidgetWrap.__init__(self, pile) + + def __str__(self): + return str(self.headers) + + def _build_lines(self, lines): + max_key_len = 1 + headerlines = [] + #calc max length of key-string + for key, value in lines: + if len(key) > max_key_len: + max_key_len = len(key) + for key, value in lines: + ##todo : even/odd + keyw = ('fixed', max_key_len + 1, + urwid.Text((self.key_attr, key))) + valuew = urwid.Text((self.value_attr, value)) + line = urwid.Columns([keyw, valuew]) + headerlines.append(line) + return headerlines + + +class TagWidget(urwid.AttrMap): + """ + text widget that renders a tagstring. + + It looks up the string it displays in the `tags` section + of the config as well as custom theme settings for its tag. + """ + def __init__(self, tag, fallback_normal=None, fallback_focus=None): + self.tag = tag + representation = settings.get_tagstring_representation(tag, + fallback_normal, + fallback_focus) + self.translated = representation['translated'] + self.hidden = self.translated == '' + self.txt = urwid.Text(self.translated, wrap='clip') + normal_att = representation['normal'] + focus_att = representation['focussed'] + self.attmaps = {'normal': normal_att, 'focus': focus_att} + urwid.AttrMap.__init__(self, self.txt, normal_att, focus_att) + + def set_map(self, attrstring): + self.set_attr_map({None: self.attmaps[attrstring]}) + + def width(self): + # evil voodoo hotfix for double width chars that may + # lead e.g. to strings with length 1 that need width 2 + return self.txt.pack()[0] + + def selectable(self): + return True + + def keypress(self, size, key): + return key + + def get_tag(self): + return self.tag + + def set_focussed(self): + self.set_attr_map(self.attmap['focus']) + + def set_unfocussed(self): + self.set_attr_map(self.attmap['normal']) |