File: movecollectiontask.cpp

package info (click to toggle)
kdepim-runtime 4%3A24.12.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 24,012 kB
  • sloc: cpp: 90,562; xml: 1,020; javascript: 60; sh: 58; makefile: 13
file content (127 lines) | stat: -rw-r--r-- 4,299 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
    SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
    SPDX-FileContributor: Kevin Ottens <kevin@kdab.com>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#include "movecollectiontask.h"

#include <KLocalizedString>

#include <KIMAP/RenameJob>
#include <KIMAP/SelectJob>
#include <KIMAP/Session>
#include <KIMAP/SubscribeJob>

#include <QUuid>

MoveCollectionTask::MoveCollectionTask(const ResourceStateInterface::Ptr &resource, QObject *parent)
    : ResourceTask(DeferIfNoSession, resource, parent)
{
}

MoveCollectionTask::~MoveCollectionTask() = default;

void MoveCollectionTask::doStart(KIMAP::Session *session)
{
    if (collection().remoteId().isEmpty()) {
        emitError(i18n("Cannot move IMAP folder '%1', it does not exist on the server.", collection().name()));
        changeProcessed();
        return;
    }

    if (sourceCollection().remoteId().isEmpty()) {
        emitError(i18n("Cannot move IMAP folder '%1' out of '%2', '%2' does not exist on the server.", collection().name(), sourceCollection().name()));
        changeProcessed();
        return;
    }

    if (targetCollection().remoteId().isEmpty()) {
        emitError(i18n("Cannot move IMAP folder '%1' to '%2', '%2' does not exist on the server.", collection().name(), sourceCollection().name()));
        changeProcessed();
        return;
    }

    if (session->selectedMailBox() != mailBoxForCollection(collection())) {
        doRename(session);
        return;
    }

    // Some IMAP servers don't allow moving an opened mailbox, so make sure
    // it's not opened (https://bugs.kde.org/show_bug.cgi?id=324932) by examining
    // a non-existent mailbox. We don't use CLOSE in order not to trigger EXPUNGE
    auto examine = new KIMAP::SelectJob(session);
    examine->setOpenReadOnly(true); // use EXAMINE instead of SELECT
    examine->setMailBox(QStringLiteral("IMAP Resource non existing folder %1").arg(QUuid::createUuid().toString()));
    connect(examine, &KIMAP::SelectJob::result, this, &MoveCollectionTask::onExamineDone);
    examine->start();
}

void MoveCollectionTask::onExamineDone(KJob *job)
{
    // We deliberately ignore any error here, because the SelectJob will always fail
    // when examining a non-existent mailbox

    auto examine = static_cast<KIMAP::SelectJob *>(job);
    doRename(examine->session());
}

QString MoveCollectionTask::mailBoxForCollections(const Akonadi::Collection &parent, const Akonadi::Collection &child) const
{
    const QString parentMailbox = mailBoxForCollection(parent);
    if (parentMailbox.isEmpty()) {
        return child.remoteId().mid(1); // Strip separator on toplevel mailboxes
    }
    return parentMailbox + child.remoteId();
}

void MoveCollectionTask::doRename(KIMAP::Session *session)
{
    // collection.remoteId() already includes the separator
    const QString oldMailBox = mailBoxForCollections(sourceCollection(), collection());
    const QString newMailBox = mailBoxForCollections(targetCollection(), collection());

    if (oldMailBox != newMailBox) {
        auto job = new KIMAP::RenameJob(session);
        job->setSourceMailBox(oldMailBox);
        job->setDestinationMailBox(newMailBox);

        connect(job, &KIMAP::RenameJob::result, this, &MoveCollectionTask::onRenameDone);

        job->start();
    } else {
        changeProcessed();
    }
}

void MoveCollectionTask::onRenameDone(KJob *job)
{
    if (job->error()) {
        cancelTask(job->errorString());
    } else {
        // Automatically subscribe to the new mailbox name
        auto rename = static_cast<KIMAP::RenameJob *>(job);

        auto subscribe = new KIMAP::SubscribeJob(rename->session());
        subscribe->setMailBox(rename->destinationMailBox());

        connect(subscribe, &KIMAP::SubscribeJob::result, this, &MoveCollectionTask::onSubscribeDone);

        subscribe->start();
    }
}

void MoveCollectionTask::onSubscribeDone(KJob *job)
{
    if (job->error()) {
        emitWarning(
            i18n("Failed to subscribe to the folder '%1' on the IMAP server. "
                 "It will disappear on next sync. Use the subscription dialog to overcome that",
                 collection().name()));
    }

    changeCommitted(collection());
}

#include "moc_movecollectiontask.cpp"