File indexing completed on 2024-06-23 05:21:16
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 "UpdateFlagsTask.h" 0025 #include "Imap/Model/ItemRoles.h" 0026 #include "Imap/Model/MailboxTree.h" 0027 #include "Imap/Model/Model.h" 0028 #include "CopyMoveMessagesTask.h" 0029 #include "KeepMailboxOpenTask.h" 0030 0031 namespace Imap 0032 { 0033 namespace Mailbox 0034 { 0035 0036 UpdateFlagsTask::UpdateFlagsTask(Model *model, const QModelIndexList &messages_, const FlagsOperation flagOperation, const QString &flags): 0037 ImapTask(model), copyMove(0), flagOperation(flagOperation), flags(flags) 0038 { 0039 if (messages_.isEmpty()) { 0040 throw CantHappen("UpdateFlagsTask called with empty message set"); 0041 } 0042 Q_FOREACH(const QModelIndex& index, messages_) { 0043 messages << index; 0044 } 0045 QModelIndex mailboxIndex = model->findMailboxForItems(messages_); 0046 conn = model->findTaskResponsibleFor(mailboxIndex); 0047 conn->addDependentTask(this); 0048 } 0049 0050 UpdateFlagsTask::UpdateFlagsTask(Model *model, CopyMoveMessagesTask *copyTask, const QList<QPersistentModelIndex> &messages, 0051 const FlagsOperation flagOperation, const QString &flags): 0052 ImapTask(model), conn(0), copyMove(copyTask), messages(messages), flagOperation(flagOperation), flags(flags) 0053 { 0054 copyTask->addDependentTask(this); 0055 } 0056 0057 void UpdateFlagsTask::perform() 0058 { 0059 Q_ASSERT(conn || copyMove); 0060 if (conn) 0061 parser = conn->parser; 0062 else if (copyMove) 0063 parser = copyMove->parser; 0064 markAsActiveTask(); 0065 0066 IMAP_TASK_CHECK_ABORT_DIE; 0067 0068 Sequence seq; 0069 bool first = true; 0070 0071 Q_FOREACH(const QPersistentModelIndex& index, messages) { 0072 if (!index.isValid()) { 0073 log(QStringLiteral("Some message got removed before we could update its flags"), Common::LOG_MESSAGES); 0074 } else { 0075 TreeItem *item = static_cast<TreeItem *>(index.internalPointer()); 0076 Q_ASSERT(item); 0077 TreeItemMessage *message = dynamic_cast<TreeItemMessage *>(item); 0078 Q_ASSERT(message); 0079 if (first) { 0080 seq = Sequence(message->uid()); 0081 first = false; 0082 } else { 0083 seq.add(message->uid()); 0084 } 0085 switch (flagOperation) { 0086 case FLAG_ADD: 0087 case FLAG_REMOVE: 0088 case FLAG_USE_THESE: 0089 // we aren't supposed to update them ourselves; the IMAP server will tell us 0090 break; 0091 case FLAG_REMOVE_SILENT: 0092 { 0093 TreeItemMsgList *list = dynamic_cast<TreeItemMsgList*>(message->parent()); 0094 Q_ASSERT(list); 0095 QStringList newFlags = message->m_flags; 0096 newFlags.removeOne(flags); 0097 message->setFlags(list, newFlags); 0098 // we don't have to either re-sort or call Model::normalizeFlags again from this context; 0099 // this will change when the model starts de-duplicating whole lists 0100 model->cache()->setMsgFlags(static_cast<TreeItemMailbox*>(list->parent())->mailbox(), message->uid(), newFlags); 0101 break; 0102 } 0103 case FLAG_ADD_SILENT: 0104 { 0105 TreeItemMsgList *list = dynamic_cast<TreeItemMsgList*>(message->parent()); 0106 Q_ASSERT(list); 0107 QStringList newFlags = message->m_flags; 0108 if (!newFlags.contains(flags)) { 0109 newFlags << flags; 0110 message->setFlags(list, model->normalizeFlags(newFlags)); 0111 model->cache()->setMsgFlags(static_cast<TreeItemMailbox*>(list->parent())->mailbox(), message->uid(), newFlags); 0112 } 0113 break; 0114 } 0115 } 0116 } 0117 } 0118 0119 if (first) { 0120 // No valid messages 0121 _failed(tr("All messages got removed before we could've updated their flags")); 0122 return; 0123 } 0124 tag = parser->uidStore(seq, toImapString(flagOperation), flags); 0125 } 0126 0127 bool UpdateFlagsTask::handleStateHelper(const Imap::Responses::State *const resp) 0128 { 0129 if (resp->tag.isEmpty()) 0130 return false; 0131 0132 if (resp->tag == tag) { 0133 0134 if (resp->kind == Responses::OK) { 0135 // nothing should be needed here 0136 _completed(); 0137 } else { 0138 _failed(tr("Failed to update FLAGS")); 0139 // FIXME: error handling 0140 } 0141 return true; 0142 } 0143 return false; 0144 } 0145 0146 QVariant UpdateFlagsTask::taskData(const int role) const 0147 { 0148 return role == RoleTaskCompactName ? QVariant(tr("Saving message state")) : QVariant(); 0149 } 0150 0151 0152 } 0153 }