File indexing completed on 2024-06-02 05:21:11
0001 /* 0002 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0003 SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "movecollectiontask.h" 0009 0010 #include <KLocalizedString> 0011 0012 #include <KIMAP/RenameJob> 0013 #include <KIMAP/SelectJob> 0014 #include <KIMAP/Session> 0015 #include <KIMAP/SubscribeJob> 0016 0017 #include <QUuid> 0018 0019 MoveCollectionTask::MoveCollectionTask(const ResourceStateInterface::Ptr &resource, QObject *parent) 0020 : ResourceTask(DeferIfNoSession, resource, parent) 0021 { 0022 } 0023 0024 MoveCollectionTask::~MoveCollectionTask() = default; 0025 0026 void MoveCollectionTask::doStart(KIMAP::Session *session) 0027 { 0028 if (collection().remoteId().isEmpty()) { 0029 emitError(i18n("Cannot move IMAP folder '%1', it does not exist on the server.", collection().name())); 0030 changeProcessed(); 0031 return; 0032 } 0033 0034 if (sourceCollection().remoteId().isEmpty()) { 0035 emitError(i18n("Cannot move IMAP folder '%1' out of '%2', '%2' does not exist on the server.", collection().name(), sourceCollection().name())); 0036 changeProcessed(); 0037 return; 0038 } 0039 0040 if (targetCollection().remoteId().isEmpty()) { 0041 emitError(i18n("Cannot move IMAP folder '%1' to '%2', '%2' does not exist on the server.", collection().name(), sourceCollection().name())); 0042 changeProcessed(); 0043 return; 0044 } 0045 0046 if (session->selectedMailBox() != mailBoxForCollection(collection())) { 0047 doRename(session); 0048 return; 0049 } 0050 0051 // Some IMAP servers don't allow moving an opened mailbox, so make sure 0052 // it's not opened (https://bugs.kde.org/show_bug.cgi?id=324932) by examining 0053 // a non-existent mailbox. We don't use CLOSE in order not to trigger EXPUNGE 0054 auto examine = new KIMAP::SelectJob(session); 0055 examine->setOpenReadOnly(true); // use EXAMINE instead of SELECT 0056 examine->setMailBox(QStringLiteral("IMAP Resource non existing folder %1").arg(QUuid::createUuid().toString())); 0057 connect(examine, &KIMAP::SelectJob::result, this, &MoveCollectionTask::onExamineDone); 0058 examine->start(); 0059 } 0060 0061 void MoveCollectionTask::onExamineDone(KJob *job) 0062 { 0063 // We deliberately ignore any error here, because the SelectJob will always fail 0064 // when examining a non-existent mailbox 0065 0066 auto examine = static_cast<KIMAP::SelectJob *>(job); 0067 doRename(examine->session()); 0068 } 0069 0070 QString MoveCollectionTask::mailBoxForCollections(const Akonadi::Collection &parent, const Akonadi::Collection &child) const 0071 { 0072 const QString parentMailbox = mailBoxForCollection(parent); 0073 if (parentMailbox.isEmpty()) { 0074 return child.remoteId().mid(1); // Strip separator on toplevel mailboxes 0075 } 0076 return parentMailbox + child.remoteId(); 0077 } 0078 0079 void MoveCollectionTask::doRename(KIMAP::Session *session) 0080 { 0081 // collection.remoteId() already includes the separator 0082 const QString oldMailBox = mailBoxForCollections(sourceCollection(), collection()); 0083 const QString newMailBox = mailBoxForCollections(targetCollection(), collection()); 0084 0085 if (oldMailBox != newMailBox) { 0086 auto job = new KIMAP::RenameJob(session); 0087 job->setSourceMailBox(oldMailBox); 0088 job->setDestinationMailBox(newMailBox); 0089 0090 connect(job, &KIMAP::RenameJob::result, this, &MoveCollectionTask::onRenameDone); 0091 0092 job->start(); 0093 } else { 0094 changeProcessed(); 0095 } 0096 } 0097 0098 void MoveCollectionTask::onRenameDone(KJob *job) 0099 { 0100 if (job->error()) { 0101 cancelTask(job->errorString()); 0102 } else { 0103 // Automatically subscribe to the new mailbox name 0104 auto rename = static_cast<KIMAP::RenameJob *>(job); 0105 0106 auto subscribe = new KIMAP::SubscribeJob(rename->session()); 0107 subscribe->setMailBox(rename->destinationMailBox()); 0108 0109 connect(subscribe, &KIMAP::SubscribeJob::result, this, &MoveCollectionTask::onSubscribeDone); 0110 0111 subscribe->start(); 0112 } 0113 } 0114 0115 void MoveCollectionTask::onSubscribeDone(KJob *job) 0116 { 0117 if (job->error()) { 0118 emitWarning( 0119 i18n("Failed to subscribe to the folder '%1' on the IMAP server. " 0120 "It will disappear on next sync. Use the subscription dialog to overcome that", 0121 collection().name())); 0122 } 0123 0124 changeCommitted(collection()); 0125 } 0126 0127 #include "moc_movecollectiontask.cpp"