1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "FetchMsgPartTask.h"
25 #include "Imap/Model/ItemRoles.h"
26 #include "Imap/Model/Model.h"
27 #include "Imap/Model/MailboxTree.h"
28 #include "KeepMailboxOpenTask.h"
35 FetchMsgPartTask::FetchMsgPartTask(Model
*model
, const QModelIndex
&mailbox
, const Uids
&uids
, const QList
<QByteArray
> &parts
):
36 ImapTask(model
), uids(uids
), parts(parts
), mailboxIndex(mailbox
)
38 Q_ASSERT(!uids
.isEmpty());
39 conn
= model
->findTaskResponsibleFor(mailboxIndex
);
40 conn
->addDependentTask(this);
41 connect(this, &ImapTask::failed
, this, &FetchMsgPartTask::markPendingItemsUnavailable
);
44 void FetchMsgPartTask::perform()
46 parser
= conn
->parser
;
49 IMAP_TASK_CHECK_ABORT_DIE
;
51 Sequence seq
= Sequence::fromVector(uids
);
52 tag
= parser
->uidFetch(seq
, parts
);
55 bool FetchMsgPartTask::handleFetch(const Imap::Responses::Fetch
*const resp
)
57 if (!mailboxIndex
.isValid()) {
58 _failed(tr("Mailbox disappeared"));
62 TreeItemMailbox
*mailbox
= dynamic_cast<TreeItemMailbox
*>(static_cast<TreeItem
*>(mailboxIndex
.internalPointer()));
64 model
->genericHandleFetch(mailbox
, resp
);
68 bool FetchMsgPartTask::handleStateHelper(const Imap::Responses::State
*const resp
)
70 if (resp
->tag
.isEmpty())
73 if (!mailboxIndex
.isValid()) {
74 _failed(tr("Mailbox disappeared"));
78 if (resp
->tag
== tag
) {
79 markPendingItemsUnavailable();
80 if (resp
->kind
== Responses::OK
) {
81 log(QStringLiteral("Fetched parts"), Common::LOG_MESSAGES
);
82 model
->changeConnectionState(parser
, CONN_STATE_SELECTED
);
85 _failed(tr("Part fetch failed"));
93 QString
FetchMsgPartTask::debugIdentification() const
95 if (!mailboxIndex
.isValid())
96 return QStringLiteral("[invalid mailbox]");
98 Q_ASSERT(!uids
.isEmpty());
100 Q_FOREACH(const QByteArray
&item
, parts
) {
101 buf
<< QString::fromUtf8(item
);
103 return QStringLiteral("%1: parts %2 for UIDs %3")
104 .arg(mailboxIndex
.data(RoleMailboxName
).toString(), buf
.join(QStringLiteral(", ")),
105 QString::fromUtf8(Sequence::fromVector(uids
).toByteArray()));
108 QVariant
FetchMsgPartTask::taskData(const int role
) const
110 return role
== RoleTaskCompactName
? QVariant(tr("Downloading messages")) : QVariant();
113 /** @short We're dead, the data which hasn't arrived so far won't arrive in future unless a reset happens */
114 void FetchMsgPartTask::markPendingItemsUnavailable()
116 if (!mailboxIndex
.isValid())
119 TreeItemMailbox
*mailbox
= dynamic_cast<TreeItemMailbox
*>(static_cast<TreeItem
*>(mailboxIndex
.internalPointer()));
121 QList
<TreeItemMessage
*> messages
= model
->findMessagesByUids(mailbox
, uids
);
122 Q_FOREACH(TreeItemMessage
*message
, messages
) {
123 Q_FOREACH(const QByteArray
&partId
, parts
) {
124 if (finalizeFetchPart(mailbox
, message
->row() + 1, partId
)) {
125 log(QLatin1String("Fetched part ") + QString::fromUtf8(partId
), Common::LOG_MESSAGES
);
127 log(QLatin1String("Received no data for part ") + QString::fromUtf8(partId
), Common::LOG_MESSAGES
);
133 /** @short Retrieval of a message part has completed */
134 bool FetchMsgPartTask::finalizeFetchPart(TreeItemMailbox
*const mailbox
, const uint sequenceNo
, const QByteArray
&partId
)
137 // At first, verify that the message itself is marked as loaded.
138 // If it isn't, it's probably because of Model::releaseMessageData().
139 TreeItem
*item
= mailbox
->m_children
[0]; // TreeItemMsgList
140 item
= item
->child(sequenceNo
- 1, model
); // TreeItemMessage
141 Q_ASSERT(item
); // FIXME: or rather throw an exception?
142 if (item
->accessFetchStatus() == TreeItem::NONE
) {
143 // ...and it indeed got released, so let's just return and don't try to check anything
147 TreeItemPart
*part
= mailbox
->partIdToPtr(model
, static_cast<TreeItemMessage
*>(item
), partId
);
149 log(QStringLiteral("Can't verify part fetching status: part is not here!"), Common::LOG_MESSAGES
);
152 if (part
->loading()) {
153 part
->setFetchStatus(TreeItem::UNAVAILABLE
);
154 QModelIndex idx
= part
->toIndex(model
);
155 emit model
->dataChanged(idx
, idx
);