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 }