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

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 "movetotrashcommand.h"
0009 #include "imapsettings.h"
0010 #include "movecommand.h"
0011 #include "specialmailcollections.h"
0012 #include "util_p.h"
0013 
0014 #include <Akonadi/EntityTreeModel>
0015 #include <Akonadi/ItemFetchJob>
0016 #include <Akonadi/ItemFetchScope>
0017 using namespace Akonadi;
0018 MoveToTrashCommand::MoveToTrashCommand(const QAbstractItemModel *model, const Akonadi::Collection::List &folders, QObject *parent)
0019     : CommandBase(parent)
0020     , mFolders(folders)
0021     , the_trashCollectionFolder(-1)
0022     , mModel(model)
0023     , mFolderListJobCount(mFolders.size())
0024 {
0025 }
0026 
0027 MoveToTrashCommand::MoveToTrashCommand(const QAbstractItemModel *model, const Akonadi::Item::List &msgList, QObject *parent)
0028     : CommandBase(parent)
0029     , mMessages(msgList)
0030     , the_trashCollectionFolder(-1)
0031     , mModel(model)
0032     , mFolderListJobCount(0)
0033 {
0034 }
0035 
0036 void MoveToTrashCommand::slotFetchDone(KJob *job)
0037 {
0038     mFolderListJobCount--;
0039 
0040     if (job->error()) {
0041         // handle errors
0042         Util::showJobError(job);
0043         emitResult(Failed);
0044         return;
0045     }
0046 
0047     auto fjob = static_cast<Akonadi::ItemFetchJob *>(job);
0048 
0049     mMessages = fjob->items();
0050     moveMessages();
0051 
0052     if (mFolderListJobCount > 0) {
0053         auto fetchJob = new Akonadi::ItemFetchJob(mFolders[mFolderListJobCount - 1], parent());
0054         fetchJob->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent);
0055         connect(fetchJob, &Akonadi::ItemFetchJob::result, this, &MoveToTrashCommand::slotFetchDone);
0056     }
0057 }
0058 
0059 void MoveToTrashCommand::execute()
0060 {
0061     if (!mFolders.isEmpty()) {
0062         auto job = new Akonadi::ItemFetchJob(mFolders[mFolderListJobCount - 1], parent());
0063         job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent);
0064         connect(job, &Akonadi::ItemFetchJob::result, this, &MoveToTrashCommand::slotFetchDone);
0065     } else if (!mMessages.isEmpty()) {
0066         mFolders << mMessages.first().parentCollection();
0067         moveMessages();
0068     } else {
0069         emitResult(OK);
0070     }
0071 }
0072 
0073 void MoveToTrashCommand::moveMessages()
0074 {
0075     const Akonadi::Collection folder = mFolders.at(mFolderListJobCount);
0076     if (folder.isValid()) {
0077         auto moveCommand = new MoveCommand(findTrashFolder(folder), mMessages, this);
0078         connect(moveCommand, &MoveCommand::result, this, &MoveToTrashCommand::slotMoveDone);
0079         moveCommand->execute();
0080     } else {
0081         emitResult(Failed);
0082     }
0083 }
0084 
0085 void MoveToTrashCommand::slotMoveDone(Result result)
0086 {
0087     if (result == Failed) {
0088         emitResult(Failed);
0089     }
0090     if (mFolderListJobCount == 0 && result == OK) {
0091         emitResult(OK);
0092     }
0093 }
0094 
0095 Akonadi::Collection MoveToTrashCommand::collectionFromId(Akonadi::Collection::Id id) const
0096 {
0097     const QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(mModel, Akonadi::Collection(id));
0098     return idx.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
0099 }
0100 
0101 Akonadi::Collection MoveToTrashCommand::trashCollectionFromResource(const Akonadi::Collection &col)
0102 {
0103     // NOTE(Andras): from kmail/kmkernel.cpp
0104     Akonadi::Collection trashCol;
0105     if (col.isValid()) {
0106         if (col.resource().contains(IMAP_RESOURCE_IDENTIFIER)) {
0107             // TODO: we really need some standard interface to query for special collections,
0108             // instead of relying on a resource's settings interface
0109             OrgKdeAkonadiImapSettingsInterface *iface = Util::createImapSettingsInterface(col.resource());
0110             if (iface->isValid()) {
0111                 trashCol = Akonadi::Collection(iface->trashCollection());
0112                 delete iface;
0113                 return trashCol;
0114             }
0115             delete iface;
0116         }
0117     }
0118     return trashCol;
0119 }
0120 
0121 Akonadi::Collection MoveToTrashCommand::trashCollectionFolder()
0122 {
0123     if (the_trashCollectionFolder < 0) {
0124         the_trashCollectionFolder = Akonadi::SpecialMailCollections::self()->defaultCollection(Akonadi::SpecialMailCollections::Trash).id();
0125     }
0126     return collectionFromId(the_trashCollectionFolder);
0127 }
0128 
0129 Akonadi::Collection MoveToTrashCommand::findTrashFolder(const Akonadi::Collection &folder)
0130 {
0131     Akonadi::Collection col = trashCollectionFromResource(folder);
0132     if (!col.isValid()) {
0133         col = trashCollectionFolder();
0134     }
0135     if (folder != col) {
0136         return col;
0137     }
0138     return {};
0139 }
0140 
0141 #include "moc_movetotrashcommand.cpp"