File indexing completed on 2024-10-27 04:51:03
0001 /* 0002 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "folderarchivemanager.h" 0007 #include "folderarchiveaccountinfo.h" 0008 #include "folderarchiveagentjob.h" 0009 #include "folderarchivecache.h" 0010 #include "folderarchiveutil.h" 0011 0012 #include <Akonadi/AgentManager> 0013 #include <Akonadi/CollectionFetchJob> 0014 #include <Akonadi/ItemFetchJob> 0015 #include <Akonadi/ItemFetchScope> 0016 0017 #include "kmail_debug.h" 0018 #include <KLocalizedString> 0019 #include <KNotification> 0020 #include <KSharedConfig> 0021 0022 #include <QRegularExpression> 0023 0024 FolderArchiveManager::FolderArchiveManager(QObject *parent) 0025 : QObject(parent) 0026 , mFolderArchiveCache(new FolderArchiveCache(this)) 0027 { 0028 load(); 0029 } 0030 0031 FolderArchiveManager::~FolderArchiveManager() 0032 { 0033 qDeleteAll(mListAccountInfo); 0034 mListAccountInfo.clear(); 0035 qDeleteAll(mJobQueue); 0036 delete mCurrentJob; 0037 } 0038 0039 void FolderArchiveManager::slotCollectionRemoved(const Akonadi::Collection &collection) 0040 { 0041 KConfig config(FolderArchive::FolderArchiveUtil::configFileName()); 0042 mFolderArchiveCache->clearCacheWithContainsCollection(collection.id()); 0043 for (FolderArchiveAccountInfo *info : std::as_const(mListAccountInfo)) { 0044 if (info->archiveTopLevel() == collection.id()) { 0045 info->setArchiveTopLevel(-1); 0046 KConfigGroup group = config.group(FolderArchive::FolderArchiveUtil::groupConfigPattern() + info->instanceName()); 0047 info->writeConfig(group); 0048 } 0049 } 0050 load(); 0051 } 0052 0053 FolderArchiveAccountInfo *FolderArchiveManager::infoFromInstanceName(const QString &instanceName) const 0054 { 0055 for (FolderArchiveAccountInfo *info : std::as_const(mListAccountInfo)) { 0056 if (info->instanceName() == instanceName) { 0057 return info; 0058 } 0059 } 0060 return nullptr; 0061 } 0062 0063 void FolderArchiveManager::setArchiveItem(qlonglong itemId) 0064 { 0065 auto job = new Akonadi::ItemFetchJob(Akonadi::Item(itemId), this); 0066 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 0067 job->fetchScope().setFetchRemoteIdentification(true); 0068 connect(job, &Akonadi::ItemFetchJob::result, this, &FolderArchiveManager::slotFetchParentCollection); 0069 } 0070 0071 void FolderArchiveManager::slotFetchParentCollection(KJob *job) 0072 { 0073 if (job->error()) { 0074 moveFailed(i18n("Unable to fetch folder. Error reported: %1", job->errorString())); 0075 qCDebug(KMAIL_LOG) << "Unable to fetch folder:" << job->errorString(); 0076 return; 0077 } 0078 const Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob *>(job); 0079 const Akonadi::Item::List items = fetchJob->items(); 0080 if (items.isEmpty()) { 0081 moveFailed(i18n("No folder returned.")); 0082 qCDebug(KMAIL_LOG) << "Fetch list is empty"; 0083 } else { 0084 auto jobCol = new Akonadi::CollectionFetchJob(Akonadi::Collection(items.first().parentCollection().id()), Akonadi::CollectionFetchJob::Base, this); 0085 jobCol->setProperty("itemId", items.first().id()); 0086 connect(jobCol, &Akonadi::CollectionFetchJob::result, this, &FolderArchiveManager::slotFetchCollection); 0087 } 0088 } 0089 0090 void FolderArchiveManager::slotFetchCollection(KJob *job) 0091 { 0092 if (job->error()) { 0093 moveFailed(i18n("Unable to fetch parent folder. Error reported: %1", job->errorString())); 0094 qCDebug(KMAIL_LOG) << "cannot fetch collection " << job->errorString(); 0095 return; 0096 } 0097 auto jobCol = qobject_cast<Akonadi::CollectionFetchJob *>(job); 0098 if (jobCol->collections().isEmpty()) { 0099 moveFailed(i18n("Unable to return list of folders.")); 0100 qCDebug(KMAIL_LOG) << "List of folder is empty"; 0101 return; 0102 } 0103 0104 const Akonadi::Item::List itemIds = {Akonadi::Item(jobCol->property("itemId").toLongLong())}; 0105 setArchiveItems(itemIds, jobCol->collections().constFirst().resource()); 0106 } 0107 0108 void FolderArchiveManager::setArchiveItems(const Akonadi::Item::List &items, const QString &instanceName) 0109 { 0110 FolderArchiveAccountInfo *info = infoFromInstanceName(instanceName); 0111 if (info) { 0112 auto job = new FolderArchiveAgentJob(this, info, items); 0113 if (mCurrentJob) { 0114 mJobQueue.enqueue(job); 0115 } else { 0116 mCurrentJob = job; 0117 job->start(); 0118 } 0119 } 0120 } 0121 0122 void FolderArchiveManager::slotInstanceRemoved(const Akonadi::AgentInstance &instance) 0123 { 0124 const QString instanceName = instance.name(); 0125 for (FolderArchiveAccountInfo *info : std::as_const(mListAccountInfo)) { 0126 if (info->instanceName() == instanceName) { 0127 mListAccountInfo.removeAll(info); 0128 removeInfo(instanceName); 0129 break; 0130 } 0131 } 0132 } 0133 0134 void FolderArchiveManager::removeInfo(const QString &instanceName) 0135 { 0136 KConfig config(FolderArchive::FolderArchiveUtil::configFileName()); 0137 KConfigGroup group = config.group(FolderArchive::FolderArchiveUtil::groupConfigPattern() + instanceName); 0138 group.deleteGroup(QLatin1StringView()); 0139 config.sync(); 0140 } 0141 0142 void FolderArchiveManager::load() 0143 { 0144 qDeleteAll(mListAccountInfo); 0145 mListAccountInfo.clear(); 0146 // Be sure to clear cache. 0147 mFolderArchiveCache->clearCache(); 0148 0149 KConfig config(FolderArchive::FolderArchiveUtil::configFileName()); 0150 const QStringList accountList = config.groupList().filter(QRegularExpression(FolderArchive::FolderArchiveUtil::groupConfigPattern())); 0151 for (const QString &account : accountList) { 0152 KConfigGroup group = config.group(account); 0153 auto info = new FolderArchiveAccountInfo(group); 0154 if (info->enabled()) { 0155 mListAccountInfo.append(info); 0156 } else { 0157 delete info; 0158 } 0159 } 0160 } 0161 0162 void FolderArchiveManager::moveDone() 0163 { 0164 KNotification::event(QStringLiteral("folderarchivedone"), 0165 QString(), 0166 i18n("Messages archived"), 0167 QStringLiteral("kmail"), 0168 KNotification::CloseOnTimeout, 0169 QStringLiteral("kmail2")); 0170 nextJob(); 0171 } 0172 0173 void FolderArchiveManager::moveFailed(const QString &msg) 0174 { 0175 KNotification::event(QStringLiteral("folderarchiveerror"), 0176 QString(), 0177 msg, 0178 QStringLiteral("kmail"), 0179 KNotification::CloseOnTimeout, 0180 QStringLiteral("kmail2")); 0181 nextJob(); 0182 } 0183 0184 void FolderArchiveManager::nextJob() 0185 { 0186 mCurrentJob->deleteLater(); 0187 if (mJobQueue.isEmpty()) { 0188 mCurrentJob = nullptr; 0189 } else { 0190 mCurrentJob = mJobQueue.dequeue(); 0191 mCurrentJob->start(); 0192 } 0193 } 0194 0195 FolderArchiveCache *FolderArchiveManager::folderArchiveCache() const 0196 { 0197 return mFolderArchiveCache; 0198 } 0199 0200 void FolderArchiveManager::reloadConfig() 0201 { 0202 load(); 0203 } 0204 0205 #include "moc_folderarchivemanager.cpp"