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"