diff options
author | Anton Khirnov <anton@khirnov.net> | 2020-04-19 18:59:28 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2020-04-19 18:59:28 +0200 |
commit | 7b3bd19a2a2f2a9ebbd6ac4f3b90ca7206461980 (patch) | |
tree | 53e6eca7c378fe2d02ae0e182103027ef151e007 /alot/buffers | |
parent | 5e240f760d61dca12bfc8f4bc903af9fa33cb402 (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.py | 101 |
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`""" |