File indexing completed on 2024-05-12 05:11:10

0001 /*
0002     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>
0003     SPDX-FileCopyrightText: 2010 Andras Mantia <andras@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include "emptytrashcommand.h"
0009 #include "imapsettings.h"
0010 #include "specialmailcollections.h"
0011 #include "util_p.h"
0012 
0013 #include "akonadi_mime_debug.h"
0014 #include <KLocalizedString>
0015 #include <KMessageBox>
0016 
0017 #include <Akonadi/AgentManager>
0018 #include <Akonadi/EntityTreeModel>
0019 #include <Akonadi/ItemDeleteJob>
0020 #include <Akonadi/ItemFetchJob>
0021 #include <KMime/KMimeMessage>
0022 using namespace Akonadi;
0023 EmptyTrashCommand::EmptyTrashCommand(const QAbstractItemModel *model, QObject *parent)
0024     : CommandBase(parent)
0025     , mModel(model)
0026     , the_trashCollectionFolder(-1)
0027 {
0028 }
0029 
0030 EmptyTrashCommand::EmptyTrashCommand(const Akonadi::Collection &folder, QObject *parent)
0031     : CommandBase(parent)
0032     , mModel(nullptr)
0033     , the_trashCollectionFolder(-1)
0034     , mFolder(folder)
0035 {
0036 }
0037 
0038 void EmptyTrashCommand::execute()
0039 {
0040     if (!mFolder.isValid() && !mModel) {
0041         emitResult(Failed);
0042         return;
0043     }
0044 
0045     if (!mFolder.isValid()) { // expunge all
0046         const QString title = i18n("Empty Trash");
0047         const QString text = i18n("Are you sure you want to empty the trash folders of all accounts?");
0048         if (KMessageBox::warningContinueCancel(nullptr,
0049                                                text,
0050                                                title,
0051                                                KStandardGuiItem::cont(),
0052                                                KStandardGuiItem::cancel(),
0053                                                QStringLiteral("confirm_empty_trash"))
0054             != KMessageBox::Continue) {
0055             emitResult(OK);
0056             return;
0057         }
0058         Akonadi::Collection trash = trashCollectionFolder();
0059         QList<Akonadi::Collection> trashFolder;
0060         trashFolder << trash;
0061 
0062         const Akonadi::AgentInstance::List lst = agentInstances();
0063         for (const Akonadi::AgentInstance &type : lst) {
0064             if (type.identifier().contains(IMAP_RESOURCE_IDENTIFIER)) {
0065                 if (type.status() == Akonadi::AgentInstance::Broken) {
0066                     continue;
0067                 }
0068                 QScopedPointer<OrgKdeAkonadiImapSettingsInterface> iface{Util::createImapSettingsInterface(type.identifier())};
0069                 if (iface->isValid()) {
0070                     const int trashImap = iface->trashCollection();
0071                     if (trashImap != trash.id()) {
0072                         trashFolder << Akonadi::Collection(trashImap);
0073                     }
0074                 }
0075             }
0076         }
0077         mNumberOfTrashToEmpty = trashFolder.count();
0078         for (int i = 0; i < mNumberOfTrashToEmpty; ++i) {
0079             expunge(trashFolder.at(i));
0080         }
0081     } else {
0082         if (folderIsTrash(mFolder)) {
0083             mNumberOfTrashToEmpty++;
0084             expunge(mFolder);
0085         } else {
0086             emitResult(OK);
0087         }
0088     }
0089 }
0090 
0091 void EmptyTrashCommand::expunge(const Akonadi::Collection &col)
0092 {
0093     if (col.isValid()) {
0094         auto jobDelete = new Akonadi::ItemDeleteJob(col, this);
0095         connect(jobDelete, &Akonadi::ItemDeleteJob::result, this, [this, jobDelete]() {
0096             if (jobDelete->error()) {
0097                 Util::showJobError(jobDelete);
0098                 emitResult(Failed);
0099             }
0100             emitResult(OK);
0101         });
0102     } else {
0103         qCWarning(AKONADIMIME_LOG) << " Try to expunge an invalid collection :" << col;
0104         emitResult(Failed);
0105     }
0106 }
0107 
0108 Akonadi::AgentInstance::List EmptyTrashCommand::agentInstances()
0109 {
0110     Akonadi::AgentInstance::List relevantInstances;
0111     const auto instances = Akonadi::AgentManager::self()->instances();
0112     for (const Akonadi::AgentInstance &instance : instances) {
0113         if (instance.type().mimeTypes().contains(KMime::Message::mimeType()) && instance.type().capabilities().contains(QLatin1StringView("Resource"))
0114             && !instance.type().capabilities().contains(QLatin1StringView("Virtual"))) {
0115             relevantInstances << instance;
0116         }
0117     }
0118     return relevantInstances;
0119 }
0120 
0121 Akonadi::Collection EmptyTrashCommand::collectionFromId(Collection::Id id) const
0122 {
0123     const QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(mModel, Akonadi::Collection(id));
0124     return idx.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
0125 }
0126 
0127 Akonadi::Collection EmptyTrashCommand::trashCollectionFolder()
0128 {
0129     if (the_trashCollectionFolder < 0) {
0130         the_trashCollectionFolder = Akonadi::SpecialMailCollections::self()->defaultCollection(Akonadi::SpecialMailCollections::Trash).id();
0131     }
0132     return collectionFromId(the_trashCollectionFolder);
0133 }
0134 
0135 bool EmptyTrashCommand::folderIsTrash(const Akonadi::Collection &col)
0136 {
0137     if (col == Akonadi::SpecialMailCollections::self()->defaultCollection(Akonadi::SpecialMailCollections::Trash)) {
0138         return true;
0139     }
0140     const Akonadi::AgentInstance::List lst = agentInstances();
0141     for (const Akonadi::AgentInstance &type : lst) {
0142         if (type.status() == Akonadi::AgentInstance::Broken) {
0143             continue;
0144         }
0145         if (type.identifier().contains(IMAP_RESOURCE_IDENTIFIER)) {
0146             QScopedPointer<OrgKdeAkonadiImapSettingsInterface> iface{Util::createImapSettingsInterface(type.identifier())};
0147             if (iface->isValid()) {
0148                 if (iface->trashCollection() == col.id()) {
0149                     return true;
0150                 }
0151             }
0152         }
0153     }
0154     return false;
0155 }
0156 
0157 void EmptyTrashCommand::emitResult(Result value)
0158 {
0159     Q_EMIT result(value);
0160     mNumberOfTrashToEmpty--;
0161     if (mNumberOfTrashToEmpty <= 0) {
0162         deleteLater();
0163     }
0164 }
0165 
0166 #include "moc_emptytrashcommand.cpp"