summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDon Sanders <sanders@trolltech.com>2009-03-13 17:20:04 +1000
committerDon Sanders <sanders@trolltech.com>2009-03-13 17:20:04 +1000
commitfd2ac942bf2713574827cdcdd4a1bf364ac556e7 (patch)
tree9c4b4949e882a8661fb10d14c16f03c6e16e790c
parent7f8aa529038e825f35938c879dc050ba00850204 (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.cpp18
-rw-r--r--src/plugins/messageservices/imap/imapservice.cpp30
-rw-r--r--src/plugins/messageservices/imap/imapstrategy.cpp91
-rw-r--r--src/plugins/messageservices/imap/imapstrategy.h13
-rw-r--r--src/plugins/viewers/generic/browser.cpp4
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)"));