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 }