From ec0a3a8406cb34103eb0610c4c8aa3dc330f3c3c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 May 2021 16:27:34 +0200 Subject: buffers/thread: do not construct the message widgets until they are needed --- alot/buffers/thread.py | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/alot/buffers/thread.py b/alot/buffers/thread.py index d47faa31..33405be4 100644 --- a/alot/buffers/thread.py +++ b/alot/buffers/thread.py @@ -5,6 +5,7 @@ import asyncio import enum +from functools import cached_property import logging import urwid @@ -18,6 +19,16 @@ class _ThreadBufFocus(enum.Enum): TREE = enum.auto() MESSAGE = enum.auto() +class _LazyMessageWidget: + msg = None + + def __init__(self, msg): + self.msg = msg + + @cached_property + def wgt(self): + return MessageWidget(self.msg) + class ThreadBuffer(Buffer): """displays a thread as a tree of messages.""" @@ -28,7 +39,7 @@ class ThreadBuffer(Buffer): # list of the widgets containing the message body # indexed by its depth-first position in the thread tree - _msg_widgets = None + _messages = None # widget showing the thread tree _msgtree_widget = None # decorations around the msgtree widget @@ -87,9 +98,9 @@ class ThreadBuffer(Buffer): def _update_cur_msg(self): pos = self._msgtree_widget.body.focus - if pos is not None and pos < len(self._msg_widgets): + if pos is not None and pos < len(self._messages): logging.debug('displaying message %s ', pos) - self._cur_msg_holder.original_widget = self._msg_widgets[pos] + self._cur_msg_holder.original_widget = self._messages[pos].wgt def translated_tags_str(self, intersection=False): tags = self.thread.get_tags(intersection=intersection) @@ -108,7 +119,7 @@ class ThreadBuffer(Buffer): return info def rebuild(self): - self._msg_widgets = [] + self._messages = [] self._msgtree_widget.body.clear() self._cur_msg_holder.original_widget = urwid.SolidFill() @@ -119,11 +130,8 @@ class ThreadBuffer(Buffer): list_walker = self._msgtree_widget.body for pos, msg in enumerate(self.thread.message_list): - msg_wgt = MessageWidget(msg) - wgt = ThreadNode(msg, self.thread, pos, self._indent_width) - - self._msg_widgets.append(msg_wgt) - list_walker.append(wgt) + self._messages.append(_LazyMessageWidget(msg)) + list_walker.append(ThreadNode(msg, self.thread, pos, self._indent_width)) # approximate weight for one terminal line # substract 3 for decoration and panels @@ -133,11 +141,11 @@ class ThreadBuffer(Buffer): # the number of messages in it plus 2 (for surrounding decoration) - # scaled to approximately one line per message - up to maximum weight of # half the screen - tree_weight = min(line_weight * (len(self._msg_widgets) + 2), 0.5) + tree_weight = min(line_weight * (len(self._messages) + 2), 0.5) self.msgtree_weight = tree_weight - if len(self._msg_widgets) > 0: - self._cur_msg_holder.original_widget = self._msg_widgets[0] + if len(self._messages) > 0: + self._cur_msg_holder.original_widget = self._messages[0].wgt @property def msgtree_weight(self): @@ -155,7 +163,7 @@ class ThreadBuffer(Buffer): def get_selected_message_widget(self): """Return currently focused :class:`MessageWidget`.""" pos = self.get_selected_message_position() - return self._msg_widgets[pos] + return self._messages[pos].wgt def get_selected_message(self): """Return focussed :class:`~alot.db.message.Message`.""" @@ -176,8 +184,8 @@ class ThreadBuffer(Buffer): """ Iterate over all the message widgets in this buffer """ - for w in self._msg_widgets: - yield w + for m in self._messages: + yield m.wgt def set_focus(self, pos): "Set the focus in the underlying body widget." @@ -267,7 +275,7 @@ class ThreadBuffer(Buffer): raise ValueError('Invalid focus_propery direction: ' + str(direction)) for pos in walk: - if prop(self._msg_widgets[pos]): + if prop(self._messages[pos].wgt): self.set_focus(pos) break -- cgit v1.2.3