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 }