From 0dbf2be49db228e43fe4b196199f82ea281886bf Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 29 Jun 2015 11:57:20 -0400 Subject: [bug] allow mailbox to be notified of collection changes in a previous refactor, we decoupled the incoming mail service from the IMAP layer. However, this left the IMAPMailbox unable to react to changes in the underlying collection when a new message is inserted. in this commit, we add a Listener mechanism to the collection itself, so that IMAPMailbox (and any other object that uses it) can subscribe to changes on the number of messages of the collection. Resolves: #7191 Releases: 0.4.0 --- src/leap/mail/adaptors/soledad.py | 2 ++ src/leap/mail/imap/mailbox.py | 14 +++++++++++--- src/leap/mail/mail.py | 16 +++++++++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/leap/mail/adaptors/soledad.py b/src/leap/mail/adaptors/soledad.py index 4020bd0..2b1d2ff 100644 --- a/src/leap/mail/adaptors/soledad.py +++ b/src/leap/mail/adaptors/soledad.py @@ -505,6 +505,8 @@ class MessageWrapper(object): (key, get_doc_wrapper(doc, ContentDocWrapper)) for (key, doc) in cdocs.items()]) for doc_id, cdoc in zip(self.mdoc.cdocs, self.cdocs.values()): + if cdoc.raw == "": + log.msg("Empty raw field in cdoc %s" % doc_id) cdoc.set_future_doc_id(doc_id) def create(self, store, notify_just_mdoc=False, pending_inserts_dict={}): diff --git a/src/leap/mail/imap/mailbox.py b/src/leap/mail/imap/mailbox.py index 139ae66..0de4b40 100644 --- a/src/leap/mail/imap/mailbox.py +++ b/src/leap/mail/imap/mailbox.py @@ -91,6 +91,8 @@ class IMAPMailbox(object): imap4.IMailboxInfo, imap4.ISearchableMailbox, # XXX I think we do not need to implement CloseableMailbox, do we? + # We could remove ourselves from the collectionListener, although I + # think it simply will be garbage collected. # imap4.ICloseableMailbox imap4.IMessageCopier) @@ -116,6 +118,7 @@ class IMAPMailbox(object): self.rw = rw self._uidvalidity = None self.collection = collection + self.collection.addListener(self) @property def mbox_name(self): @@ -155,9 +158,10 @@ class IMAPMailbox(object): if not NOTIFY_NEW: return + listeners = self.listeners logger.debug('adding mailbox listener: %s. Total: %s' % ( - listener, len(self.listeners))) - self.listeners.add(listener) + listener, len(listeners))) + listeners.add(listener) def removeListener(self, listener): """ @@ -371,13 +375,16 @@ class IMAPMailbox(object): d = self.collection.add_msg(message, flags, date=date, notify_just_mdoc=notify_just_mdoc) - d.addCallback(self.notify_new) d.addErrback(lambda failure: log.err(failure)) return d def notify_new(self, *args): """ Notify of new messages to all the listeners. + This will be called indirectly by the underlying collection, that will + notify this IMAPMailbox whenever there are changes in the number of + messages in the collection, since we have added ourselves to the + collection listeners. :param args: ignored. """ @@ -392,6 +399,7 @@ class IMAPMailbox(object): d = self._get_notify_count() d.addCallback(cbNotifyNew) d.addCallback(self.collection.cb_signal_unread_to_ui) + d.addErrback(lambda failure: log.err(failure)) def _get_notify_count(self): """ diff --git a/src/leap/mail/mail.py b/src/leap/mail/mail.py index faaabf6..4a73186 100644 --- a/src/leap/mail/mail.py +++ b/src/leap/mail/mail.py @@ -378,6 +378,7 @@ class MessageCollection(object): # of by doc_id. See get_message_by_content_hash self.mbox_indexer = mbox_indexer self.mbox_wrapper = mbox_wrapper + self._listeners = set([]) def is_mailbox_collection(self): """ @@ -639,11 +640,24 @@ class MessageCollection(object): notify_just_mdoc=notify_just_mdoc, pending_inserts_dict=self._pending_inserts) d.addCallback(insert_mdoc_id, wrapper) - d.addErrback(lambda failure: log.err(failure)) d.addCallback(self.cb_signal_unread_to_ui) + d.addCallback(self.notify_new_to_listeners) + d.addErrback(lambda failure: log.err(failure)) return d + # Listeners + + def addListener(self, listener): + self._listeners.add(listener) + + def removeListener(self, listener): + self._listeners.remove(listener) + + def notify_new_to_listeners(self, *args): + for listener in self._listeners: + listener.notify_new() + def cb_signal_unread_to_ui(self, result): """ Sends an unread event to ui, passing *only* the number of unread -- cgit v1.2.3