From 7bd9489ed8988eb66a40eaff6b60fb6d051bd88c Mon Sep 17 00:00:00 2001 From: Patrick Totzke Date: Sat, 7 Jul 2012 11:59:31 +0100 Subject: rewrite Threadline widget This makes threadline build its parts according to a "threadline theming structure" it reads of a Theme object. This structure determines which subwidgets in which order are used and for each of them provides normal/focussed attributes, align and width --- alot/widgets.py | 221 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 130 insertions(+), 91 deletions(-) (limited to 'alot') diff --git a/alot/widgets.py b/alot/widgets.py index e98fbf7b..5986c49a 100644 --- a/alot/widgets.py +++ b/alot/widgets.py @@ -92,75 +92,85 @@ class ThreadlineWidget(urwid.AttrMap): def __init__(self, tid, dbman): self.dbman = dbman - #logging.debug('tid: %s' % tid) self.thread = dbman.get_thread(tid) - #logging.debug('tid: %s' % self.thread) self.tag_widgets = [] self.display_content = settings.get('display_content_in_threadline') + self.structure = None self.rebuild() - normal = settings.get_theming_attribute('search', 'thread') - focussed = settings.get_theming_attribute('search', 'thread_focus') + normal = self.structure['normal'] + focussed = self.structure['focus'] urwid.AttrMap.__init__(self, self.columns, normal, focussed) - def rebuild(self): - cols = [] - if self.thread: - newest = self.thread.get_newest_date() - else: + def _build_part(self, name, struct, minw, maxw, align): + def pad(string, shorten=None): + if maxw: + if len(string) > maxw: + if shorten: + string = shorten(string, maxw) + else: + string = string[:maxw] + if minw: + if len(string) < minw: + if align == 'left': + string = string.ljust(minw) + elif align == 'center': + string = string.center(minw) + else: + string = string.rjust(minw) + return string + + part = None + width = None + if name == 'date': newest = None - if newest == None: datestring = '' - else: - datestring = settings.represent_datetime(newest) - datestring = datestring.rjust(self.pretty_datetime_len) - self.date_w = urwid.AttrMap(urwid.Text(datestring), - self._get_theme('date')) - cols.append(('fixed', len(datestring), self.date_w)) - - if self.thread: - mailcountstring = "(%d)" % self.thread.get_total_messages() - else: - mailcountstring = "(?)" - self.mailcount_w = urwid.AttrMap(urwid.Text(mailcountstring), - self._get_theme('mailcount')) - cols.append(('fixed', len(mailcountstring), self.mailcount_w)) - - if self.thread: - self.tag_widgets = [TagWidget(t) - for t in self.thread.get_tags()] - else: - self.tag_widgets = [] - self.tag_widgets.sort(tag_cmp, - lambda tag_widget: tag_widget.translated) - for tag_widget in self.tag_widgets: - if not tag_widget.hidden: - cols.append(('fixed', tag_widget.width(), tag_widget)) - - if self.thread: - authors = self.thread.get_authors_string() or '(None)' - else: - authors = '(None)' - maxlength = settings.get('authors_maxlength') - authorsstring = shorten_author_string(authors, maxlength) - self.authors_w = urwid.AttrMap(urwid.Text(authorsstring), - self._get_theme('authors')) - cols.append(('fixed', len(authorsstring), self.authors_w)) - - if self.thread: - subjectstring = self.thread.get_subject() or '' - else: - subjectstring = '' - # sanitize subject string: - subjectstring = subjectstring.replace('\n', ' ') - subjectstring = subjectstring.replace('\r', '') - subjectstring = subjectstring.strip() - - self.subject_w = urwid.AttrMap(urwid.Text(subjectstring, wrap='clip'), - self._get_theme('subject')) - if subjectstring: - cols.append(('weight', 2, self.subject_w)) - - if self.display_content: + if self.thread: + newest = self.thread.get_newest_date() + datestring = settings.represent_datetime(newest) + datestring = datestring.rjust(self.pretty_datetime_len) + datestring = pad(datestring) + width = len(datestring) + part = AttrFlipWidget(urwid.Text(datestring), struct['date']) + + elif name == 'mailcount': + if self.thread: + mailcountstring = "(%d)" % self.thread.get_total_messages() + else: + mailcountstring = "(?)" + datestring = pad(mailcountstring) + width = len(mailcountstring) + mailcount_w = AttrFlipWidget(urwid.Text(mailcountstring), + struct['mailcount']) + part = mailcount_w + elif name == 'authors': + if self.thread: + authors = self.thread.get_authors_string() or '(None)' + else: + authors = '(None)' + maxlength = settings.get('authors_maxlength') #TODO + authorsstring = pad(authors, shorten_author_string) + authors_w = AttrFlipWidget(urwid.Text(authorsstring), + struct['authors']) + width = len(authorsstring) + part = authors_w + + elif name == 'subject': + if self.thread: + subjectstring = self.thread.get_subject() or '' + else: + subjectstring = '' + # sanitize subject string: + subjectstring = subjectstring.replace('\n', ' ') + subjectstring = subjectstring.replace('\r', '') + subjectstring = pad(subjectstring.strip()) + + subject_w = AttrFlipWidget(urwid.Text(subjectstring, wrap='clip'), + struct['subject']) + if subjectstring: + width = len(subjectstring) + part = subject_w + + elif name == 'content': if self.thread: msgs = self.thread.get_messages().keys() else: @@ -168,39 +178,66 @@ class ThreadlineWidget(urwid.AttrMap): # sort the most recent messages first msgs.sort(key=lambda msg: msg.get_date(), reverse=True) lastcontent = ' '.join([m.get_text_content() for m in msgs]) - contentstring = lastcontent.replace('\n', ' ').strip() - self.content_w = urwid.AttrMap(urwid.Text( + contentstring = pad(lastcontent.replace('\n', ' ').strip()) + content_w = AttrFlipWidget(urwid.Text( contentstring, wrap='clip'), - self._get_theme('content')) - cols.append(self.content_w) + struct['content']) + width = len(contentstring) + part = content_w + elif name == 'tags': + if self.thread: + tag_widgets = [TagWidget(t) + for t in self.thread.get_tags()] + tag_widgets.sort(tag_cmp, + lambda tag_widget: tag_widget.translated) + else: + tag_widgets = [] + cols = [] + length = -1 + for tag_widget in tag_widgets: + if not tag_widget.hidden: + wrapped_tagwidget = AttrFlipWidget(tag_widget, struct['tags']) + tag_width = tag_widget.width() + cols.append(('fixed', tag_width, wrapped_tagwidget)) + length += tag_width +1 + if cols: + part = urwid.Columns(cols, dividechars=1) + width = length + return width, part - self.columns = urwid.Columns(cols, dividechars=1) + def rebuild(self): + self.widgets = [] + columns = [] + self.structure = settings.get_threadline_theming(self.thread) + for partname in self.structure['order']: + minw = maxw = None + width_tuple = self.structure[partname]['width'] + if width_tuple is not None: + if width_tuple[0] == 'fit': + minw, maxw = width_tuple[1:] + align_mode = self.structure[partname]['alignment'] + width, part = self._build_part(partname, self.structure, + minw, maxw, align_mode) + if part is not None: + if isinstance(part, urwid.Columns): + for w in part.widget_list: + self.widgets.append(w) + else: + self.widgets.append(part) + + # compute width and align + if width_tuple[0] == 'weight': + columnentry = width_tuple + (part,) + else: + columnentry = ('fixed', width, part) + columns.append(columnentry) + self.columns = urwid.Columns(columns, dividechars=1) self.original_widget = self.columns def render(self, size, focus=False): - if focus: - self.date_w.set_attr_map({None: self._get_theme('date', focus)}) - self.mailcount_w.set_attr_map({None: - self._get_theme('mailcount', focus)}) - for tw in self.tag_widgets: - tw.set_focussed() - self.authors_w.set_attr_map({None: self._get_theme('authors', - focus)}) - self.subject_w.set_attr_map({None: self._get_theme('subject', - focus)}) - if self.display_content: - self.content_w.set_attr_map( - {None: self._get_theme('content', focus=True)}) - else: - self.date_w.set_attr_map({None: self._get_theme('date')}) - self.mailcount_w.set_attr_map({None: self._get_theme('mailcount')}) - for tw in self.tag_widgets: - tw.set_unfocussed() - self.authors_w.set_attr_map({None: self._get_theme('authors')}) - self.subject_w.set_attr_map({None: self._get_theme('subject')}) - if self.display_content: - self.content_w.set_attr_map({None: self._get_theme('content')}) + for w in self.widgets: + w.set_map('focus' if focus else 'normal') return urwid.AttrMap.render(self, size, focus) def selectable(self): @@ -213,10 +250,12 @@ class ThreadlineWidget(urwid.AttrMap): return self.thread def _get_theme(self, component, focus=False): - attr_key = 'thread_{0}'.format(component) + path = ['search', 'threadline', component] if focus: - attr_key += '_focus' - return settings.get_theming_attribute('search', attr_key) + path.append('focus') + else: + path.append('normal') + return settings.get_theming_attribute(path) class BufferlineWidget(urwid.Text): -- cgit v1.2.3