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"