1 /* Copyright (C) 2013 Yasser Aziza <yasser.aziza@gmail.com>
2 
3    This file is part of the Trojita Qt IMAP e-mail client,
4    http://trojita.flaska.net/
5 
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.
13 
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.
18 
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/>.
21 */
22 
23 
24 #include "UpdateFlagsOfAllMessagesTask.h"
25 #include "Imap/Model/ItemRoles.h"
26 #include "Imap/Model/MailboxTree.h"
27 #include "Imap/Model/Model.h"
28 #include "KeepMailboxOpenTask.h"
29 
30 namespace Imap
31 {
32 namespace Mailbox
33 {
34 
UpdateFlagsOfAllMessagesTask(Model * model,const QModelIndex & mailboxIndex,const FlagsOperation flagOperation,const QString & flags)35 UpdateFlagsOfAllMessagesTask::UpdateFlagsOfAllMessagesTask(Model *model, const QModelIndex &mailboxIndex,
36                                                            const FlagsOperation flagOperation, const QString &flags):
37     ImapTask(model), flagOperation(flagOperation), flags(flags), mailboxIndex(mailboxIndex)
38 {
39     Q_ASSERT(mailboxIndex.isValid());
40     Q_ASSERT(flagOperation == Imap::Mailbox::FLAG_ADD || flagOperation == Imap::Mailbox::FLAG_ADD_SILENT);
41     conn = model->findTaskResponsibleFor(mailboxIndex);
42     conn->addDependentTask(this);
43 }
44 
perform()45 void UpdateFlagsOfAllMessagesTask::perform()
46 {
47     Q_ASSERT(conn);
48     parser = conn->parser;
49 
50     markAsActiveTask();
51     IMAP_TASK_CHECK_ABORT_DIE;
52 
53     Sequence seq = Sequence::startingAt(1);
54     tag = parser->store(seq, toImapString(flagOperation), flags);
55 }
56 
handleStateHelper(const Imap::Responses::State * const resp)57 bool UpdateFlagsOfAllMessagesTask::handleStateHelper(const Imap::Responses::State *const resp)
58 {
59     if (resp->tag.isEmpty())
60         return false;
61 
62     if (resp->tag == tag) {
63         if (resp->kind == Responses::OK) {
64             TreeItemMailbox *mailbox = model->mailboxForSomeItem(mailboxIndex);
65             if (!mailbox) {
66                 // There isn't much to be done here -- let's assume that the index has disappeared.
67                 // The flags will be resynced the next time we open that mailbox.
68                 _failed(QStringLiteral("Mailbox is gone"));
69                 return true;
70             }
71             Q_ASSERT(mailbox);
72             TreeItemMsgList *list = dynamic_cast<TreeItemMsgList*>(mailbox->m_children [0]);
73             Q_ASSERT(list);
74 
75             Q_FOREACH (TreeItem *item, list->m_children) {
76                 TreeItemMessage *message = dynamic_cast<TreeItemMessage *>(item);
77                 Q_ASSERT(message);
78 
79                 if (message->uid() == 0) {
80                     // UID not determined yet, so we cannot really modify its flags
81                     continue;
82                 }
83 
84                 Q_ASSERT(flagOperation == Imap::Mailbox::FLAG_ADD || flagOperation == Imap::Mailbox::FLAG_ADD_SILENT);
85                 QStringList newFlags = message->m_flags;
86                 if (!newFlags.contains(flags)) {
87                     newFlags << flags;
88                     message->setFlags(list, model->normalizeFlags(newFlags));
89                     model->cache()->setMsgFlags(mailbox->mailbox(), message->uid(), newFlags);
90                     QModelIndex messageIndex = model->createIndex(message->m_offset, 0, message);
91 
92                     // emitting dataChanged() separately for each message in the mailbox:
93                     // Trojita model assmues that dataChanged is emitted individually
94                     model->dataChanged(messageIndex, messageIndex);
95                 }
96             }
97             model->emitMessageCountChanged(mailbox);
98             list->fetchNumbers(model);
99             _completed();
100         } else {
101             _failed(tr("Failed to update Mailbox FLAGS"));
102         }
103         return true;
104     }
105     return false;
106 }
107 
taskData(const int role) const108 QVariant UpdateFlagsOfAllMessagesTask::taskData(const int role) const
109 {
110     return role == RoleTaskCompactName ? QVariant(tr("Saving mailbox state")) : QVariant();
111 }
112 
113 }
114 }
115