summaryrefslogtreecommitdiff
path: root/alot
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2012-07-07 11:59:31 +0100
committerPatrick Totzke <patricktotzke@gmail.com>2012-07-07 11:59:31 +0100
commit7bd9489ed8988eb66a40eaff6b60fb6d051bd88c (patch)
treecfbc458d7c4ba04697fd60514d95e410fc248fe7 /alot
parentc0d59d6c0ac9d1f65a9a9becbcbf8af8f1baf790 (diff)
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
Diffstat (limited to 'alot')
-rw-r--r--alot/widgets.py221
1 files changed, 130 insertions, 91 deletions
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):