summaryrefslogtreecommitdiff
path: root/alot/db/thread.py
diff options
context:
space:
mode:
Diffstat (limited to 'alot/db/thread.py')
-rw-r--r--alot/db/thread.py100
1 files changed, 43 insertions, 57 deletions
diff --git a/alot/db/thread.py b/alot/db/thread.py
index bae48b1a..2792737c 100644
--- a/alot/db/thread.py
+++ b/alot/db/thread.py
@@ -36,6 +36,15 @@ class Thread:
"""Thread subject"""
subject = None
+ """A list of toplevel messages"""
+ toplevel_messages = None
+
+ """A list of ids of all messages in this thread in depth-first order"""
+ message_ids = None
+
+ """A dict mapping Message-Id strings to Message instances"""
+ messages = None
+
def __init__(self, dbman, thread):
"""
:param dbman: db manager that is used for further lookups
@@ -46,9 +55,12 @@ class Thread:
self._dbman = dbman
self._authors = None
self.id = thread.get_thread_id()
- self._messages = {}
self._tags = set()
+ self.toplevel_messages = []
+ self.message_ids = []
+ self.messages = {}
+
self.refresh(thread)
def refresh(self, thread=None):
@@ -84,8 +96,34 @@ class Thread:
self.newest_date = None
self._tags = {t for t in thread.get_tags()}
- self._messages = {} # this maps messages to its children
- self._toplevel_messages = []
+
+ self.messages, self.toplevel_messages, self.message_ids = self._gather_messages()
+
+ def _gather_messages(self):
+ query = self._dbman.query('thread:' + self.id)
+ nm_thread = next(query.search_threads())
+
+ msgs = {}
+ msg_tree = []
+ ids = []
+
+ def thread_tree_walk(nm_msg):
+ msg_id = nm_msg.get_message_id()
+ ids.append(msg_id)
+
+ replies = []
+ for m in nm_msg.get_replies():
+ replies.append(thread_tree_walk(m))
+ msg = Message(self._dbman, nm_msg, self, replies)
+
+ msgs[msg_id] = msg
+
+ return msg
+
+ for m in nm_thread.get_toplevel_messages():
+ msg_tree.append(thread_tree_walk(m))
+
+ return msgs, msg_tree, ids
def __str__(self):
return "thread:%s: %s" % (self.id, self.subject)
@@ -101,7 +139,7 @@ class Thread:
"""
tags = set(list(self._tags))
if intersection:
- for m in self.get_messages().keys():
+ for m in self.messages.values():
tags = tags.intersection(set(m.get_tags()))
return tags
@@ -172,7 +210,7 @@ class Thread:
if self._authors is None:
# Sort messages with date first (by date ascending), and those
# without a date last.
- msgs = sorted(self.get_messages().keys(),
+ msgs = sorted(self.messages.values(),
key=lambda m: m.date or datetime.max)
orderby = settings.get('thread_authors_order_by')
@@ -222,58 +260,6 @@ class Thread:
else:
return self._notmuch_authors_string
- def get_toplevel_messages(self):
- """
- returns all toplevel messages contained in this thread.
- This are all the messages without a parent message
- (identified by 'in-reply-to' or 'references' header.
-
- :rtype: list of :class:`~alot.db.message.Message`
- """
- if not self._messages:
- self.get_messages()
- return self._toplevel_messages
-
- def get_messages(self):
- """
- returns all messages in this thread as dict mapping all contained
- messages to their direct responses.
-
- :rtype: dict mapping :class:`~alot.db.message.Message` to a list of
- :class:`~alot.db.message.Message`.
- """
- if not self._messages: # if not already cached
- query = self._dbman.query('thread:' + self.id)
- thread = next(query.search_threads())
-
- def accumulate(acc, msg):
- M = Message(self._dbman, msg, thread=self)
- acc[M] = []
- r = msg.get_replies()
- if r is not None:
- for m in r:
- acc[M].append(accumulate(acc, m))
- return M
-
- self._messages = {}
- for m in thread.get_toplevel_messages():
- self._toplevel_messages.append(accumulate(self._messages, m))
- return self._messages
-
- def get_replies_to(self, msg):
- """
- returns all replies to the given message contained in this thread.
-
- :param msg: parent message to look up
- :type msg: :class:`~alot.db.message.Message`
- :returns: list of :class:`~alot.db.message.Message` or `None`
- """
- msg_hash = self.get_messages()
- for m in msg_hash.keys():
- if m.id == msg.id:
- return msg_hash[m]
- return None
-
def matches(self, query):
"""
Check if this thread matches the given notmuch query.