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

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 "ListChildMailboxesTask.h"
0025 #include "Imap/Model/ItemRoles.h"
0026 #include "Imap/Model/MailboxTree.h"
0027 #include "Imap/Model/Model.h"
0028 #include "GetAnyConnectionTask.h"
0029 #include "NumberOfMessagesTask.h"
0030 
0031 namespace Imap
0032 {
0033 namespace Mailbox
0034 {
0035 
0036 
0037 ListChildMailboxesTask::ListChildMailboxesTask(Model *model, const QModelIndex &mailbox):
0038     ImapTask(model), mailboxIndex(mailbox), mailboxIsRootMailbox(!mailbox.isValid())
0039 {
0040     Q_ASSERT(!mailbox.isValid() || dynamic_cast<TreeItemMailbox *>(static_cast<TreeItem *>(mailbox.internalPointer())));
0041     conn = model->m_taskFactory->createGetAnyConnectionTask(model);
0042     conn->addDependentTask(this);
0043 }
0044 
0045 ListChildMailboxesTask::~ListChildMailboxesTask()
0046 {
0047     qDeleteAll(m_pendingStatusResponses);
0048 }
0049 
0050 void ListChildMailboxesTask::perform()
0051 {
0052     parser = conn->parser;
0053     markAsActiveTask();
0054 
0055     IMAP_TASK_CHECK_ABORT_DIE;
0056 
0057     if (!mailboxIsRootMailbox && !mailboxIndex.isValid()) {
0058         // FIXME: add proper fix
0059         _failed(tr("Mailbox vanished before we could ask for its children"));
0060         return;
0061     }
0062     TreeItemMailbox *mailbox = dynamic_cast<TreeItemMailbox *>(static_cast<TreeItem *>(model->translatePtr(mailboxIndex)));
0063     Q_ASSERT(mailbox);
0064 
0065     QString mailboxName = mailbox->mailbox();
0066     if (mailboxName.isNull())
0067         mailboxName = QStringLiteral("%");
0068     else
0069         mailboxName += mailbox->separator() + QLatin1Char('%');
0070 
0071     QStringList returnOptions;
0072     if (model->accessParser(parser).capabilitiesFresh) {
0073         if (model->accessParser(parser).capabilities.contains(QStringLiteral("LIST-EXTENDED"))) {
0074             returnOptions << QStringLiteral("SUBSCRIBED") << QStringLiteral("CHILDREN");
0075         }
0076         if (model->accessParser(parser).capabilities.contains(QStringLiteral("LIST-STATUS"))) {
0077             returnOptions << QStringLiteral("STATUS (%1)").arg(NumberOfMessagesTask::requestedStatusOptions().join(QStringLiteral(" ")));
0078         }
0079     }
0080     // empty string, not a null string
0081     tag = parser->list(QLatin1String(""), mailboxName, returnOptions);
0082 }
0083 
0084 bool ListChildMailboxesTask::handleStateHelper(const Imap::Responses::State *const resp)
0085 {
0086     if (resp->tag.isEmpty())
0087         return false;
0088 
0089     if (resp->tag == tag) {
0090 
0091         if (mailboxIndex.isValid() || mailboxIsRootMailbox) {
0092             TreeItemMailbox *mailbox = dynamic_cast<TreeItemMailbox *>(static_cast<TreeItem *>(model->translatePtr(mailboxIndex)));
0093             Q_ASSERT(mailbox);
0094 
0095             if (resp->kind == Responses::OK) {
0096                 model->finalizeList(parser, mailbox);
0097                 applyCachedStatus();
0098                 _completed();
0099             } else {
0100                 applyCachedStatus();
0101                 _failed(tr("LIST failed"));
0102             }
0103         } else {
0104             applyCachedStatus();
0105             _failed(tr("Mailbox no longer available -- weird timing?"));
0106         }
0107         return true;
0108     } else {
0109         return false;
0110     }
0111 }
0112 
0113 /** @short Defer processing of the STATUS responses until after all of the LISTs are processed */
0114 bool ListChildMailboxesTask::handleStatus(const Imap::Responses::Status *const resp)
0115 {
0116     if (!mailboxIndex.isValid() && !mailboxIsRootMailbox)
0117         return false;
0118 
0119     if (!resp->mailbox.startsWith(mailboxIndex.data(RoleMailboxName).toString())) {
0120         // not our data
0121         return false;
0122     }
0123 
0124     // Got to cache these responses until we can apply them
0125     m_pendingStatusResponses << new Imap::Responses::Status(*resp);
0126     return true;
0127 }
0128 
0129 /** @short Send the cached STATUS responses to the Model */
0130 void ListChildMailboxesTask::applyCachedStatus()
0131 {
0132     Q_FOREACH(Imap::Responses::Status *resp, m_pendingStatusResponses) {
0133         resp->plug(parser, model);
0134         delete resp;
0135     }
0136     m_pendingStatusResponses.clear();
0137 }
0138 
0139 QString ListChildMailboxesTask::debugIdentification() const
0140 {
0141     if (!mailboxIndex.isValid() && !mailboxIsRootMailbox)
0142         return QStringLiteral("[invalid mailboxIndex]");
0143 
0144     TreeItemMailbox *mailbox = dynamic_cast<TreeItemMailbox *>(static_cast<TreeItem *>(model->translatePtr(mailboxIndex)));
0145     Q_ASSERT(mailbox);
0146     return QStringLiteral("Listing stuff below mailbox %1").arg(mailbox->mailbox());
0147 }
0148 
0149 QVariant ListChildMailboxesTask::taskData(const int role) const
0150 {
0151     return role == RoleTaskCompactName ? QVariant(tr("Listing mailboxes")) : QVariant();
0152 }
0153 
0154 void ListChildMailboxesTask::_failed(const QString &errorMessage)
0155 {
0156     if (mailboxIsRootMailbox || mailboxIndex.isValid()) {
0157         TreeItemMailbox *mailbox = dynamic_cast<TreeItemMailbox *>(static_cast<TreeItem *>(model->translatePtr(mailboxIndex)));
0158         mailbox->setFetchStatus(TreeItem::UNAVAILABLE);
0159         QModelIndex index = mailbox->toIndex(model);
0160         emit model->dataChanged(index, index);
0161     }
0162     ImapTask::_failed(errorMessage);
0163 }
0164 
0165 
0166 }
0167 }