summaryrefslogtreecommitdiff
path: root/alot/buffers
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-04-19 18:59:28 +0200
committerAnton Khirnov <anton@khirnov.net>2020-04-19 18:59:28 +0200
commit7b3bd19a2a2f2a9ebbd6ac4f3b90ca7206461980 (patch)
tree53e6eca7c378fe2d02ae0e182103027ef151e007 /alot/buffers
parent5e240f760d61dca12bfc8f4bc903af9fa33cb402 (diff)
buffers/search: rewrite PipeWalker
Convert it to the v2 API and avoid constructing widgets until they are needed.
Diffstat (limited to 'alot/buffers')
-rw-r--r--alot/buffers/search.py101
1 files changed, 56 insertions, 45 deletions
diff --git a/alot/buffers/search.py b/alot/buffers/search.py
index ef05c667..15e9f41f 100644
--- a/alot/buffers/search.py
+++ b/alot/buffers/search.py
@@ -14,62 +14,74 @@ class PipeWalker(urwid.ListWalker):
urwid.ListWalker that reads next items from a pipe and wraps them in
ThreadlineWidget widgets for displaying
"""
+
+ _pipe = None
+ _dbman = None
+
+ _pipe_eof = False
+
+ # list of the thread IDs
+ _tids = None
+ # a dictionary of threadline widgets, indexed by position
+ _wgts = None
+
+ _focus = None
+
def __init__(self, pipe, dbman):
- self.pipe = pipe
+ self._pipe = pipe
self._dbman = dbman
- self.lines = []
- self.focus = 0
- self.empty = False
+
+ self._tids = []
+ self._wgts = {}
+
+ self._focus = 0
+
+ super().__init__()
def __len__(self):
- while not self.empty:
+ while not self._pipe_eof:
self._get_next_item()
- return len(self.lines)
+ return len(self._tids)
- def get_focus(self):
- return self._get_at_pos(self.focus)
+ def __getitem__(self, pos):
+ self._check_pos(pos)
+ if not pos in self._wgts:
+ self._wgts[pos] = ThreadlineWidget(self._tids[pos], self._dbman)
+ return self._wgts[pos]
- def set_focus(self, focus):
- self.focus = focus
- self._modified()
+ def _check_pos(self, pos):
+ if pos < 0:
+ raise IndexError
+
+ while not self._pipe_eof and pos >= len(self._tids):
+ self._get_next_item()
+
+ if pos >= len(self._tids):
+ raise IndexError
- def get_next(self, start_from):
- return self._get_at_pos(start_from + 1)
-
- def get_prev(self, start_from):
- return self._get_at_pos(start_from - 1)
-
- def _get_at_pos(self, pos):
- if pos < 0: # pos too low
- return (None, None)
- elif pos > len(self.lines): # pos too high
- return (None, None)
- elif len(self.lines) > pos: # pos already cached
- return (self.lines[pos], pos)
- else: # pos not cached yet, look at next item from iterator
- if self.empty: # iterator is empty
- return (None, None)
- else:
- widget = self._get_next_item()
- if widget:
- return (widget, pos)
- else:
- return (None, None)
+ return pos
+ def next_position(self, pos):
+ return self._check_pos(pos + 1)
+ def prev_position(self, pos):
+ return self._check_pos(pos - 1)
+
+ @property
+ def focus(self):
+ return self._focus
+
+ def set_focus(self, pos):
+ self._check_pos(pos)
+ self._focus = pos
+ self._modified()
def _get_next_item(self):
- if self.empty:
+ if self._pipe_eof:
return None
+
try:
- # the next line blocks until it can read from the pipe or
- # EOFError is raised. No races here.
- next_obj = self.pipe.recv()
- next_widget = ThreadlineWidget(next_obj, self._dbman)
- self.lines.append(next_widget)
+ self._tids.append(self._pipe.recv())
except EOFError:
- logging.debug('EMPTY PIPE')
- next_widget = None
- self.empty = True
- return next_widget
+ self._pipe_eof = True
class SearchBuffer(Buffer):
"""shows a result list of threads for a query"""
@@ -145,8 +157,7 @@ class SearchBuffer(Buffer):
returns curently focussed :class:`alot.widgets.ThreadlineWidget`
from the result list.
"""
- threadlinewidget, _ = self.threadlist.get_focus()
- return threadlinewidget
+ return self.threadlist[self.threadlist.focus]
def get_selected_thread(self):
"""returns currently selected :class:`~alot.db.Thread`"""