File indexing completed on 2024-11-24 04:44:02
0001 /* 0002 SPDX-FileCopyrightText: 2013 Daniel Vrátil <dvratil@redhat.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "changeitemsflagstask.h" 0008 0009 #include "imapresource_debug.h" 0010 #include <KIMAP/SelectJob> 0011 #include <KIMAP/Session> 0012 #include <KIMAP/StoreJob> 0013 0014 ChangeItemsFlagsTask::ChangeItemsFlagsTask(const ResourceStateInterface::Ptr &resource, QObject *parent) 0015 : ResourceTask(ResourceTask::DeferIfNoSession, resource, parent) 0016 { 0017 } 0018 0019 ChangeItemsFlagsTask::~ChangeItemsFlagsTask() = default; 0020 0021 void ChangeItemsFlagsTask::doStart(KIMAP::Session *session) 0022 { 0023 const QString mailBox = mailBoxForCollection(items().at(0).parentCollection()); 0024 qCDebug(IMAPRESOURCE_LOG) << mailBox; 0025 0026 if (session->selectedMailBox() != mailBox) { 0027 auto select = new KIMAP::SelectJob(session); 0028 select->setMailBox(mailBox); 0029 0030 connect(select, &KJob::result, this, &ChangeItemsFlagsTask::onSelectDone); 0031 0032 select->start(); 0033 } else { 0034 if (!addedFlags().isEmpty()) { 0035 triggerAppendFlagsJob(session); 0036 } else if (!removedFlags().isEmpty()) { 0037 triggerRemoveFlagsJob(session); 0038 } else { 0039 qCDebug(IMAPRESOURCE_LOG) << "nothing to do"; 0040 changeProcessed(); 0041 } 0042 } 0043 } 0044 0045 void ChangeItemsFlagsTask::onSelectDone(KJob *job) 0046 { 0047 if (job->error()) { 0048 qCWarning(IMAPRESOURCE_LOG) << "Select failed: " << job->errorString(); 0049 cancelTask(job->errorString()); 0050 } else { 0051 auto select = static_cast<KIMAP::SelectJob *>(job); 0052 qCDebug(IMAPRESOURCE_LOG) << addedFlags(); 0053 if (!addedFlags().isEmpty()) { 0054 triggerAppendFlagsJob(select->session()); 0055 } else if (!removedFlags().isEmpty()) { 0056 triggerRemoveFlagsJob(select->session()); 0057 } else { 0058 qCDebug(IMAPRESOURCE_LOG) << "nothing to do"; 0059 changeProcessed(); 0060 } 0061 } 0062 } 0063 0064 KIMAP::StoreJob *ChangeItemsFlagsTask::prepareJob(KIMAP::Session *session) 0065 { 0066 KIMAP::ImapSet set; 0067 const Akonadi::Item::List &allItems = items(); 0068 // Split the request to multiple smaller requests of 2000 UIDs each - various IMAP 0069 // servers have various limits on maximum size of a request 0070 // 2000 is a random number that sounds like a good compromise between performance 0071 // and functionality (i.e. 2000 UIDs should be supported by any server out there) 0072 for (int i = 0, count = qMin(2000, allItems.count() - m_processedItems); i < count; ++i) { 0073 set.add(allItems[m_processedItems].remoteId().toLong()); 0074 ++m_processedItems; 0075 } 0076 0077 auto store = new KIMAP::StoreJob(session); 0078 store->setUidBased(true); 0079 store->setSequenceSet(set); 0080 0081 return store; 0082 } 0083 0084 void ChangeItemsFlagsTask::triggerAppendFlagsJob(KIMAP::Session *session) 0085 { 0086 const auto supportedFlags = fromAkonadiToSupportedImapFlags(addedFlags().values(), items().at(0).parentCollection()); 0087 if (supportedFlags.isEmpty()) { 0088 if (!removedFlags().isEmpty()) { 0089 m_processedItems = 0; 0090 triggerRemoveFlagsJob(session); 0091 } else { 0092 changeProcessed(); 0093 } 0094 } else { 0095 KIMAP::StoreJob *store = prepareJob(session); 0096 store->setFlags(supportedFlags); 0097 store->setMode(KIMAP::StoreJob::AppendFlags); 0098 connect(store, &KIMAP::StoreJob::result, this, &ChangeItemsFlagsTask::onAppendFlagsDone); 0099 store->start(); 0100 } 0101 } 0102 0103 void ChangeItemsFlagsTask::triggerRemoveFlagsJob(KIMAP::Session *session) 0104 { 0105 const auto supportedFlags = fromAkonadiToSupportedImapFlags(removedFlags().values(), items().at(0).parentCollection()); 0106 if (supportedFlags.isEmpty()) { 0107 changeProcessed(); 0108 } else { 0109 KIMAP::StoreJob *store = prepareJob(session); 0110 store->setFlags(supportedFlags); 0111 store->setMode(KIMAP::StoreJob::RemoveFlags); 0112 connect(store, &KIMAP::StoreJob::result, this, &ChangeItemsFlagsTask::onRemoveFlagsDone); 0113 store->start(); 0114 } 0115 } 0116 0117 void ChangeItemsFlagsTask::onAppendFlagsDone(KJob *job) 0118 { 0119 if (job->error()) { 0120 qCWarning(IMAPRESOURCE_LOG) << "Flag append failed: " << job->errorString(); 0121 cancelTask(job->errorString()); 0122 } else { 0123 KIMAP::Session *session = qobject_cast<KIMAP::Job *>(job)->session(); 0124 if (m_processedItems < items().count()) { 0125 triggerAppendFlagsJob(session); 0126 } else if (removedFlags().isEmpty()) { 0127 changeProcessed(); 0128 } else { 0129 qCDebug(IMAPRESOURCE_LOG) << removedFlags(); 0130 m_processedItems = 0; 0131 triggerRemoveFlagsJob(session); 0132 } 0133 } 0134 } 0135 0136 void ChangeItemsFlagsTask::onRemoveFlagsDone(KJob *job) 0137 { 0138 if (job->error()) { 0139 qCWarning(IMAPRESOURCE_LOG) << "Flag remove failed: " << job->errorString(); 0140 cancelTask(job->errorString()); 0141 } else { 0142 if (m_processedItems < items().count()) { 0143 triggerRemoveFlagsJob(qobject_cast<KIMAP::Job *>(job)->session()); 0144 } else { 0145 changeProcessed(); 0146 } 0147 } 0148 } 0149 0150 #include "moc_changeitemsflagstask.cpp"