diff options
| author | Don Sanders <sanders@trolltech.com> | 2009-03-13 17:20:04 +1000 |
|---|---|---|
| committer | Don Sanders <sanders@trolltech.com> | 2009-03-13 17:20:04 +1000 |
| commit | fd2ac942bf2713574827cdcdd4a1bf364ac556e7 (patch) | |
| tree | 9c4b4949e882a8661fb10d14c16f03c6e16e790c | |
| parent | 7f8aa529038e825f35938c879dc050ba00850204 (diff) | |
Description: Smarter completion logic for mails that are not completely downloaded. For these mails get as many inline parts as possible without going over the download limit set for the account.2009W11
This is useful so that for mails with attachments that have some inline text, we can just download the text and leave the other parts on the server.
Rather than getting just inline parts, maybe should get all non-attachment parts, as e.g. I think signatures have dispostion type none (rather than inline or attachment).
| -rw-r--r-- | src/plugins/messageservices/imap/imapprotocol.cpp | 18 | ||||
| -rw-r--r-- | src/plugins/messageservices/imap/imapservice.cpp | 30 | ||||
| -rw-r--r-- | src/plugins/messageservices/imap/imapstrategy.cpp | 91 | ||||
| -rw-r--r-- | src/plugins/messageservices/imap/imapstrategy.h | 13 | ||||
| -rw-r--r-- | src/plugins/viewers/generic/browser.cpp | 4 |
5 files changed, 88 insertions, 68 deletions
diff --git a/src/plugins/messageservices/imap/imapprotocol.cpp b/src/plugins/messageservices/imap/imapprotocol.cpp index 7dafc4a5..3b5a6273 100644 --- a/src/plugins/messageservices/imap/imapprotocol.cpp +++ b/src/plugins/messageservices/imap/imapprotocol.cpp @@ -1991,20 +1991,6 @@ bool hasAttachments(const QMailMessagePartContainer &partContainer) return false; } -bool hasOnlyInlineAndAttachmentParts(const QMailMessagePartContainer &partContainer) -{ - for (uint i = 0; i < partContainer.partCount(); ++i) { - const QMailMessagePart &part(partContainer.partAt(i)); - - QMailMessageContentDisposition disposition(part.contentDisposition()); - if (disposition.isNull() || (disposition.type() == QMailMessageContentDisposition::None)) { - return false; - } - } - - return true; -} - } void ImapProtocol::createMail(const QString &uid, const QDateTime &timeStamp, int size, uint flags, const QString &detachedFile, const QStringList& structure, bool partialMessage) @@ -2014,9 +2000,7 @@ void ImapProtocol::createMail(const QString &uid, const QDateTime &timeStamp, in setMessageContentFromStructure( structure, &mail ); if (mail.multipartType() != QMailMessage::MultipartNone) { - if (hasOnlyInlineAndAttachmentParts(mail)) { - mail.setStatus( QMailMessage::ContentAvailable, true ); - } + mail.setStatus( QMailMessage::ContentAvailable, true ); // See if any of the parts are attachments if (hasAttachments(mail)) { diff --git a/src/plugins/messageservices/imap/imapservice.cpp b/src/plugins/messageservices/imap/imapservice.cpp index f76d7c58..a5ab0063 100644 --- a/src/plugins/messageservices/imap/imapservice.cpp +++ b/src/plugins/messageservices/imap/imapservice.cpp @@ -123,12 +123,14 @@ bool ImapService::Source::retrieveMessages(const QMailMessageIdList &messageIds, } if (spec == QMailRetrievalAction::Flags) { - _service->_client.strategyContext()->updateMessagesFlagsStrategy.setSelectedMails(messageIds); + _service->_client.strategyContext()->updateMessagesFlagsStrategy.clearSelection(); + _service->_client.strategyContext()->updateMessagesFlagsStrategy.selectedMailsAppend(messageIds); return setStrategy(&_service->_client.strategyContext()->updateMessagesFlagsStrategy); } _service->_client.strategyContext()->selectedStrategy.setOperation(spec); - _service->_client.strategyContext()->selectedStrategy.setSelectedMails(messageIds); + _service->_client.strategyContext()->selectedStrategy.clearSelection(); + _service->_client.strategyContext()->selectedStrategy.selectedMailsAppend(messageIds); return setStrategy(&_service->_client.strategyContext()->selectedStrategy); } @@ -148,7 +150,8 @@ bool ImapService::Source::retrieveMessagePart(const QMailMessagePart::Location & } _service->_client.strategyContext()->selectedStrategy.setOperation(QMailRetrievalAction::Content); - _service->_client.strategyContext()->selectedStrategy.setSelectedSection(partLocation); + _service->_client.strategyContext()->selectedStrategy.clearSelection(); + _service->_client.strategyContext()->selectedStrategy.selectedSectionsAppend(partLocation); return setStrategy(&_service->_client.strategyContext()->selectedStrategy); } @@ -172,7 +175,8 @@ bool ImapService::Source::retrieveMessageRange(const QMailMessageId &messageId, location.setContainingMessageId(messageId); _service->_client.strategyContext()->selectedStrategy.setOperation(QMailRetrievalAction::Content); - _service->_client.strategyContext()->selectedStrategy.setSelectedSection(location, minimum); + _service->_client.strategyContext()->selectedStrategy.clearSelection(); + _service->_client.strategyContext()->selectedStrategy.selectedSectionsAppend(location, minimum); return setStrategy(&_service->_client.strategyContext()->selectedStrategy); } @@ -196,7 +200,8 @@ bool ImapService::Source::retrieveMessagePartRange(const QMailMessagePart::Locat } _service->_client.strategyContext()->selectedStrategy.setOperation(QMailRetrievalAction::Content); - _service->_client.strategyContext()->selectedStrategy.setSelectedSection(partLocation, minimum); + _service->_client.strategyContext()->selectedStrategy.clearSelection(); + _service->_client.strategyContext()->selectedStrategy.selectedSectionsAppend(partLocation, minimum); return setStrategy(&_service->_client.strategyContext()->selectedStrategy); } @@ -221,7 +226,8 @@ bool ImapService::Source::exportUpdates(const QMailAccountId &accountId) } _service->_client.strategyContext()->exportUpdatesStrategy.setOperation(QMailRetrievalAction::Content); - _service->_client.strategyContext()->exportUpdatesStrategy.setSelectedMails(QMailMessageIdList()); + _service->_client.strategyContext()->exportUpdatesStrategy.clearSelection(); + _service->_client.strategyContext()->exportUpdatesStrategy.selectedMailsAppend(QMailMessageIdList()); return setStrategy(&_service->_client.strategyContext()->exportUpdatesStrategy); } @@ -250,7 +256,8 @@ bool ImapService::Source::deleteMessages(const QMailMessageIdList &messageIds) if (imapCfg.canDeleteMail()) { // Delete the messages from the server _service->_client.strategyContext()->deleteMessagesStrategy.setLocalMessageRemoval(true); - _service->_client.strategyContext()->deleteMessagesStrategy.setSelectedMails(messageIds); + _service->_client.strategyContext()->deleteMessagesStrategy.clearSelection(); + _service->_client.strategyContext()->deleteMessagesStrategy.selectedMailsAppend(messageIds); return setStrategy(&_service->_client.strategyContext()->deleteMessagesStrategy, &ImapService::Source::messagesDeleted); } @@ -271,7 +278,8 @@ bool ImapService::Source::copyMessages(const QMailMessageIdList &messageIds, con QMailFolder destination(destinationId); if (destination.parentAccountId() == _service->accountId()) { - _service->_client.strategyContext()->copyMessagesStrategy.setSelectedMails(messageIds); + _service->_client.strategyContext()->copyMessagesStrategy.clearSelection(); + _service->_client.strategyContext()->copyMessagesStrategy.selectedMailsAppend(messageIds); _service->_client.strategyContext()->copyMessagesStrategy.setDestination(destinationId); return setStrategy(&_service->_client.strategyContext()->copyMessagesStrategy, &ImapService::Source::messagesCopied); } @@ -293,7 +301,8 @@ bool ImapService::Source::moveMessages(const QMailMessageIdList &messageIds, con QMailFolder destination(destinationId); if (destination.parentAccountId() == _service->accountId()) { - _service->_client.strategyContext()->moveMessagesStrategy.setSelectedMails(messageIds); + _service->_client.strategyContext()->moveMessagesStrategy.clearSelection(); + _service->_client.strategyContext()->moveMessagesStrategy.selectedMailsAppend(messageIds); _service->_client.strategyContext()->moveMessagesStrategy.setDestination(destinationId); return setStrategy(&_service->_client.strategyContext()->moveMessagesStrategy, &ImapService::Source::messagesMoved); } @@ -310,7 +319,8 @@ bool ImapService::Source::moveMessages(const QMailMessageIdList &messageIds, con if (!serverMessages.isEmpty()) { // Delete the messages from the server _service->_client.strategyContext()->deleteMessagesStrategy.setLocalMessageRemoval(false); - _service->_client.strategyContext()->deleteMessagesStrategy.setSelectedMails(serverMessages); + _service->_client.strategyContext()->deleteMessagesStrategy.clearSelection(); + _service->_client.strategyContext()->deleteMessagesStrategy.selectedMailsAppend(serverMessages); setStrategy(&_service->_client.strategyContext()->deleteMessagesStrategy); } } diff --git a/src/plugins/messageservices/imap/imapstrategy.cpp b/src/plugins/messageservices/imap/imapstrategy.cpp index d404b6c4..3d5ac9f3 100644 --- a/src/plugins/messageservices/imap/imapstrategy.cpp +++ b/src/plugins/messageservices/imap/imapstrategy.cpp @@ -188,9 +188,13 @@ void ImapStrategy::downloadSize(ImapStrategyContextBase *context, const QString Also implements logic to determine which messages or message part to operate on next. */ -void ImapMessageListStrategy::setSelectedMails(const QMailMessageIdList& ids) +void ImapMessageListStrategy::clearSelection() { _selectionMap.clear(); +} + +void ImapMessageListStrategy::selectedMailsAppend(const QMailMessageIdList& ids) +{ if (ids.count() == 0) return; @@ -207,10 +211,8 @@ void ImapMessageListStrategy::setSelectedMails(const QMailMessageIdList& ids) _selectionItr = _folderItr.value().begin(); } -void ImapMessageListStrategy::setSelectedSection(const QMailMessagePart::Location &location) +void ImapMessageListStrategy::selectedSectionsAppend(const QMailMessagePart::Location &location) { - _selectionMap.clear(); - QMailMessageMetaData metaData(location.containingMessageId()); if (metaData.id().isValid()) { SectionProperties sectionProperties(metaData.id(), location); @@ -328,7 +330,11 @@ bool ImapMessageListStrategy::selectNextMessageSequence(ImapStrategyContextBase return false; } - while ((_selectionItr != selectionEnd) && (uidList.count() < maximum)) { + //TODO Leave parts to last to reduce roundtrips. Get all parts in one message in one roundtrip. + while ((_selectionItr != selectionEnd) + && (uidList.count() < maximum) + && (!location.isValid()) + && (minimum == SectionProperties::All)) { uidList.append(_selectionItr.key()); location = _selectionItr.value()._location; minimum = _selectionItr.value()._minimum; @@ -385,6 +391,14 @@ void ImapMessageListStrategy::completedAction(ImapStrategyContextBase *context) or message parts to retrieve, and logic to retrieve those messages or message parts and emit progress notifications. */ +void ImapFetchSelectedMessagesStrategy::clearSelection() +{ + ImapMessageListStrategy::clearSelection(); + _totalRetrievalSize = 0; + _listSize = 0; + _retrievalSize.clear(); +} + void ImapFetchSelectedMessagesStrategy::setOperation(QMailRetrievalAction::RetrievalSpecification spec) { if (spec == QMailRetrievalAction::MetaData) { @@ -394,19 +408,9 @@ void ImapFetchSelectedMessagesStrategy::setOperation(QMailRetrievalAction::Retri } } -void ImapFetchSelectedMessagesStrategy::setSelectedMails(const QMailMessageIdList& ids) +void ImapFetchSelectedMessagesStrategy::selectedMailsAppend(const QMailMessageIdList& ids) { - // We shouldn't have anything left in our retrieval list... - if (!_retrievalSize.isEmpty()) { - foreach (const QString& uid, _retrievalSize.keys()) - qMailLog(IMAP) << "Message" << uid << "still in retrieve map..."; - - _retrievalSize.clear(); - } - - _totalRetrievalSize = 0; - _selectionMap.clear(); - _listSize = ids.count(); + _listSize += ids.count(); if (_listSize == 0) return; @@ -432,18 +436,9 @@ void ImapFetchSelectedMessagesStrategy::setSelectedMails(const QMailMessageIdLis _progressRetrievalSize = 0; } -void ImapFetchSelectedMessagesStrategy::setSelectedSection(const QMailMessagePart::Location &location, int minimum) +void ImapFetchSelectedMessagesStrategy::selectedSectionsAppend(const QMailMessagePart::Location &location, int minimum) { - // We shouldn't have anything left in our retrieval list... - if (!_retrievalSize.isEmpty()) { - foreach (const QString& uid, _retrievalSize.keys()) - qMailLog(IMAP) << "Message" << uid << "still in retrieve map..."; - - _retrievalSize.clear(); - } - - _totalRetrievalSize = 0; - _selectionMap.clear(); + _listSize += 1; QMailMessageMetaData metaData(location.containingMessageId()); if (metaData.id().isValid()) { @@ -461,8 +456,6 @@ void ImapFetchSelectedMessagesStrategy::setSelectedSection(const QMailMessagePar _folderItr = _selectionMap.begin(); _selectionItr = _folderItr.value().begin(); - - _listSize = 1; } void ImapFetchSelectedMessagesStrategy::newConnection(ImapStrategyContextBase *context) @@ -777,6 +770,7 @@ void ImapSynchronizeBaseStrategy::transition(ImapStrategyContextBase *context, I void ImapSynchronizeBaseStrategy::handleLogin(ImapStrategyContextBase *context) { _completionList.clear(); + _completionSectionList.clear(); ImapFolderListStrategy::handleLogin(context); } @@ -864,9 +858,13 @@ void ImapSynchronizeBaseStrategy::fetchNextMailPreview(ImapStrategyContextBase * _newUids = _newUids.mid(uidList.count()); } else if (!selectNextMailbox(context)) { if ((_transferState == Preview) || (_retrieveUids.isEmpty())) { - if (!_completionList.isEmpty()) { + if (!_completionList.isEmpty() || !_completionSectionList.isEmpty()) { // Fetch the messages that need completion - setSelectedMails(_completionList); + clearSelection(); + selectedMailsAppend(_completionList); + foreach(QMailMessagePart::Location location, _completionSectionList) { + selectedSectionsAppend(location); + } messageAction(context); } else { context->operationCompleted(); @@ -896,8 +894,32 @@ void ImapSynchronizeBaseStrategy::messageFetched(ImapStrategyContextBase *contex if (_transferState == Preview) { context->progressChanged(_progress++, _total); - if (((message.status() & QMailMessage::ContentAvailable) == 0) && (message.size() < _headerLimit)) { + if (message.size() < _headerLimit) { _completionList.append(message.id()); + } else { + int bytesLeft = _headerLimit; + if (QMailMessage(message.id()).partCount() != message.partCount()) { + QMailMessage message2(message.id()); + qWarning() << "messageFetched: partCount mismatch" << message2.partCount() << message.partCount(); + qWarning() << "message1 subject" << message.subject() << "serverUid" << message.serverUid(); + qWarning() << "message2 subject" << message2.subject() << "serverUid" << message2.serverUid(); + return; + } + + for (uint i = 0; i < message.partCount(); ++i) { + QMailMessageContentDisposition disposition(message.partAt(i).contentDisposition()); + + if (message.partAt(i).partialContentAvailable()) { + break; + } else if (disposition.size() <= 0) { + continue; + } else if (disposition.type() != QMailMessageContentDisposition::Inline) { + continue; + } else if (bytesLeft >= disposition.size()) { + _completionSectionList.append(message.partAt(i).location()); + bytesLeft -= disposition.size(); + } + } } } } @@ -1234,7 +1256,7 @@ static QStringList stripFolderPrefix(const QStringList &list) That is to detect changes to flags (unseen->seen) and to detect deleted mails. */ -void ImapUpdateMessagesFlagsStrategy::setSelectedMails(const QMailMessageIdList &messageIds) +void ImapUpdateMessagesFlagsStrategy::selectedMailsAppend(const QMailMessageIdList &messageIds) { _messageIds = messageIds; } @@ -1392,6 +1414,7 @@ void ImapRetrieveMessageListStrategy::handleLogin(ImapStrategyContextBase *conte _transferState = List; _fillingGap = false; _completionList.clear(); + _completionSectionList.clear(); if (_folderId.isValid()) { if (_folderId == context->mailbox().id) { diff --git a/src/plugins/messageservices/imap/imapstrategy.h b/src/plugins/messageservices/imap/imapstrategy.h index eb636390..6692a4f0 100644 --- a/src/plugins/messageservices/imap/imapstrategy.h +++ b/src/plugins/messageservices/imap/imapstrategy.h @@ -100,8 +100,9 @@ public: ImapMessageListStrategy() {} virtual ~ImapMessageListStrategy() {} - virtual void setSelectedMails(const QMailMessageIdList &ids); - virtual void setSelectedSection(const QMailMessagePart::Location &location); + virtual void clearSelection(); + virtual void selectedMailsAppend(const QMailMessageIdList &ids); + virtual void selectedSectionsAppend(const QMailMessagePart::Location &location); virtual void newConnection(ImapStrategyContextBase *context); virtual void transition(ImapStrategyContextBase*, const ImapCommand, const OperationStatus); @@ -136,8 +137,9 @@ public: virtual ~ImapFetchSelectedMessagesStrategy() {} virtual void setOperation(QMailRetrievalAction::RetrievalSpecification spec); - virtual void setSelectedMails(const QMailMessageIdList &ids); - virtual void setSelectedSection(const QMailMessagePart::Location &, int = -1); + virtual void clearSelection(); + virtual void selectedMailsAppend(const QMailMessageIdList &ids); + virtual void selectedSectionsAppend(const QMailMessagePart::Location &, int = -1); virtual void newConnection(ImapStrategyContextBase *context); virtual void transition(ImapStrategyContextBase*, const ImapCommand, const OperationStatus); @@ -235,6 +237,7 @@ protected: QStringList _newUids; QList<QPair<QMailFolderId, QStringList> > _retrieveUids; QMailMessageIdList _completionList; + QList<QMailMessagePart::Location> _completionSectionList; private: uint _progress; @@ -305,7 +308,7 @@ public: ImapUpdateMessagesFlagsStrategy() {} virtual ~ImapUpdateMessagesFlagsStrategy() {} - virtual void setSelectedMails(const QMailMessageIdList &messageIds); + virtual void selectedMailsAppend(const QMailMessageIdList &messageIds); protected: virtual void handleLogin(ImapStrategyContextBase *context); diff --git a/src/plugins/viewers/generic/browser.cpp b/src/plugins/viewers/generic/browser.cpp index a0fa5a6e..8293f17f 100644 --- a/src/plugins/viewers/generic/browser.cpp +++ b/src/plugins/viewers/generic/browser.cpp @@ -245,7 +245,7 @@ void Browser::displayPlainText(const QMailMessage* mail) else { // According to RFC 2046, any unrecognised type should be treated as 'mixed' if (mail->multipartType() != QMailMessagePartContainer::MultipartMixed) - qWarning() << "Unimplemented multipart type:" << mail->contentType().toString(); + qWarning() << "Generic viewer: Unimplemented multipart type:" << mail->contentType().toString(); // Render each succesive part to text, where possible for ( uint i = 0; i < mail->partCount(); i++ ) { @@ -357,7 +357,7 @@ QString Browser::renderAttachment(const QMailMessagePart& part) "<hr><b>ATTACHMENT_TEXT</b>: <a href=\"attachment;ATTACHMENT_ACTION;ATTACHMENT_NUMBER\">NAME_TEXT</a>DISPOSITION<br>"; attachmentTemplate = replaceLast(attachmentTemplate, "ATTACHMENT_TEXT", tr("Attachment")); - attachmentTemplate = replaceLast(attachmentTemplate, "ATTACHMENT_ACTION", part.hasBody() ? "view" : "retrieve"); + attachmentTemplate = replaceLast(attachmentTemplate, "ATTACHMENT_ACTION", part.contentAvailable() ? "view" : "retrieve"); attachmentTemplate = replaceLast(attachmentTemplate, "ATTACHMENT_NUMBER", QString::number(part.partNumber())); attachmentTemplate = replaceLast(attachmentTemplate, "NAME_TEXT", partId); return replaceLast(attachmentTemplate, "DISPOSITION", part.hasBody() ? "" : tr(" (on server)")); |
