File indexing completed on 2024-06-23 05:21:13

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 
0024 #include "CopyMoveMessagesTask.h"
0025 #include "Imap/Model/ItemRoles.h"
0026 #include "Imap/Model/Model.h"
0027 #include "Imap/Model/MailboxTree.h"
0028 #include "ExpungeMessagesTask.h"
0029 #include "KeepMailboxOpenTask.h"
0030 #include "UpdateFlagsTask.h"
0031 
0032 namespace Imap
0033 {
0034 namespace Mailbox
0035 {
0036 
0037 
0038 CopyMoveMessagesTask::CopyMoveMessagesTask(Model *model, const QModelIndexList &messages_, const QString &targetMailbox,
0039                                            const CopyMoveOperation op):
0040     ImapTask(model), targetMailbox(targetMailbox), shouldDelete(op == MOVE)
0041 {
0042     if (messages_.isEmpty()) {
0043         throw CantHappen("CopyMoveMessagesTask called with empty message set");
0044     }
0045     Q_FOREACH(const QModelIndex& index, messages_) {
0046         messages << index;
0047     }
0048     QModelIndex mailboxIndex = model->findMailboxForItems(messages_);
0049     conn = model->findTaskResponsibleFor(mailboxIndex);
0050     conn->addDependentTask(this);
0051 }
0052 
0053 void CopyMoveMessagesTask::perform()
0054 {
0055     parser = conn->parser;
0056     markAsActiveTask();
0057 
0058     IMAP_TASK_CHECK_ABORT_DIE;
0059 
0060     Sequence seq;
0061     bool first = true;
0062 
0063     Q_FOREACH(const QPersistentModelIndex& index, messages) {
0064         if (! index.isValid()) {
0065             // FIXME: add proper fix
0066             log(QStringLiteral("Some message got removed before we could copy them"));
0067         } else {
0068             TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
0069             Q_ASSERT(item);
0070             TreeItemMessage *message = dynamic_cast<TreeItemMessage *>(item);
0071             Q_ASSERT(message);
0072             if (first) {
0073                 seq = Sequence(message->uid());
0074                 first = false;
0075             } else {
0076                 seq.add(message->uid());
0077             }
0078         }
0079     }
0080 
0081     if (first) {
0082         // No valid messages
0083         _failed(tr("All messages disappeared before we could have copied them"));
0084         return;
0085     }
0086 
0087     if (shouldDelete && model->accessParser(parser).capabilities.contains(QStringLiteral("MOVE"))) {
0088         moveTag = parser->uidMove(seq, targetMailbox);
0089     } else {
0090         copyTag = parser->uidCopy(seq, targetMailbox);
0091     }
0092 }
0093 
0094 bool CopyMoveMessagesTask::handleStateHelper(const Imap::Responses::State *const resp)
0095 {
0096     if (resp->tag.isEmpty())
0097         return false;
0098 
0099     if (resp->tag == copyTag) {
0100         if (resp->kind == Responses::OK) {
0101             if (shouldDelete) {
0102                 if (_dead) {
0103                     // Yeah, that's bad -- the COPY has succeeded, yet we cannot update the flags :(
0104                     log(QStringLiteral("COPY succeeded, but cannot update flags due to received die()"));
0105                     _failed(tr("Asked to die"));
0106                     return true;
0107                 }
0108                 // We ignore the _aborted status here, though -- we just want to finish in an "atomic" manner
0109                 ImapTask *flagTask = new UpdateFlagsTask(model, this, messages, FLAG_ADD_SILENT, QStringLiteral("\\Deleted"));
0110                 if (model->accessParser(parser).capabilities.contains(QStringLiteral("UIDPLUS"))) {
0111                     new ExpungeMessagesTask(model, flagTask, messages);
0112                 }
0113             }
0114             _completed();
0115         } else {
0116             _failed(tr("The COPY operation has failed: %1").arg(resp->message));
0117         }
0118         return true;
0119     } else if (resp->tag == moveTag) {
0120         if (resp->kind == Responses::OK) {
0121             _completed();
0122         } else {
0123             _failed(tr("The UID MOVE operation has failed: %1").arg(resp->message));
0124         }
0125         return true;
0126     } else {
0127         return false;
0128     }
0129 }
0130 
0131 QVariant CopyMoveMessagesTask::taskData(const int role) const
0132 {
0133     return role == RoleTaskCompactName ? QVariant(tr("Copying messages")) : QVariant();
0134 }
0135 
0136 }
0137 }