File indexing completed on 2024-11-17 04:44:46

0001 /*
0002     SPDX-FileCopyrightText: 2015-2016 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ewsfetchcalendardetailjob.h"
0008 
0009 #include <QTimeZone>
0010 
0011 #include <KCalendarCore/Event>
0012 #include <KCalendarCore/ICalFormat>
0013 #include <KCalendarCore/MemoryCalendar>
0014 
0015 #include "ewsgetitemrequest.h"
0016 #include "ewsitemshape.h"
0017 #include "ewsmailbox.h"
0018 #include "ewsoccurrence.h"
0019 #include "ewsresource_debug.h"
0020 
0021 using namespace Akonadi;
0022 
0023 EwsFetchCalendarDetailJob::EwsFetchCalendarDetailJob(EwsClient &client, QObject *parent, const Collection &collection)
0024     : EwsFetchItemDetailJob(client, parent, collection)
0025 {
0026     EwsItemShape shape(EwsShapeIdOnly);
0027     /*    shape << EwsPropertyField(QStringLiteral("calendar:UID"));
0028         shape << EwsPropertyField(QStringLiteral("item:Subject"));
0029         shape << EwsPropertyField(QStringLiteral("item:Body"));
0030         shape << EwsPropertyField(QStringLiteral("calendar:Organizer"));
0031         shape << EwsPropertyField(QStringLiteral("calendar:RequiredAttendees"));
0032         shape << EwsPropertyField(QStringLiteral("calendar:OptionalAttendees"));
0033         shape << EwsPropertyField(QStringLiteral("calendar:Resources"));
0034         shape << EwsPropertyField(QStringLiteral("calendar:Start"));
0035         shape << EwsPropertyField(QStringLiteral("calendar:End"));
0036         shape << EwsPropertyField(QStringLiteral("calendar:IsAllDayEvent"));
0037         shape << EwsPropertyField(QStringLiteral("calendar:LegacyFreeBusyStatus"));
0038         shape << EwsPropertyField(QStringLiteral("calendar:AppointmentSequenceNumber"));
0039         shape << EwsPropertyField(QStringLiteral("calendar:IsRecurring"));
0040         shape << EwsPropertyField(QStringLiteral("calendar:Recurrence"));
0041         shape << EwsPropertyField(QStringLiteral("calendar:FirstOccurrence"));
0042         shape << EwsPropertyField(QStringLiteral("calendar:LastOccurrence"));
0043         shape << EwsPropertyField(QStringLiteral("calendar:ModifiedOccurrences"));
0044         shape << EwsPropertyField(QStringLiteral("calendar:DeletedOccurrences"));
0045         shape << EwsPropertyField(QStringLiteral("calendar:StartTimeZone"));
0046         shape << EwsPropertyField(QStringLiteral("calendar:EndTimeZone"));
0047         shape << EwsPropertyField(QStringLiteral("calendar:MyResponseType"));
0048         shape << EwsPropertyField(QStringLiteral("item:HasAttachments"));
0049         shape << EwsPropertyField(QStringLiteral("item:Attachments"));*/
0050 
0051     //    shape << EwsPropertyField(QStringLiteral("item:Attachments"));
0052     shape << EwsPropertyField(QStringLiteral("calendar:ModifiedOccurrences"));
0053     shape << EwsPropertyField(QStringLiteral("calendar:DeletedOccurrences"));
0054     shape << EwsPropertyField(QStringLiteral("item:Body"));
0055     //    shape << EwsPropertyField(QStringLiteral("item:Culture"));
0056     shape << EwsPropertyField(QStringLiteral("item:MimeContent"));
0057     shape << EwsPropertyField(QStringLiteral("item:Subject"));
0058     //    shape << EwsPropertyField(QStringLiteral("calendar:TimeZone"));
0059     mRequest->setItemShape(shape);
0060 }
0061 
0062 EwsFetchCalendarDetailJob::~EwsFetchCalendarDetailJob() = default;
0063 
0064 void EwsFetchCalendarDetailJob::processItems(const EwsGetItemRequest::Response::List &responses)
0065 {
0066     Item::List::iterator it = mChangedItems.begin();
0067     KCalendarCore::ICalFormat format;
0068 
0069     EwsId::List addItems;
0070 
0071     for (const EwsGetItemRequest::Response &resp : responses) {
0072         Item &item = *it;
0073 
0074         if (!resp.isSuccess()) {
0075             qCWarningNC(EWSRES_LOG) << QStringLiteral("Failed to fetch item %1").arg(item.remoteId());
0076             continue;
0077         }
0078 
0079         const EwsItem &ewsItem = resp.item();
0080         QString mimeContent = ewsItem[EwsItemFieldMimeContent].toString();
0081         KCalendarCore::Calendar::Ptr memcal(new KCalendarCore::MemoryCalendar(QTimeZone::utc()));
0082         format.fromString(memcal, mimeContent);
0083         qCDebugNC(EWSRES_LOG) << QStringLiteral("Found %1 events").arg(memcal->events().count());
0084         KCalendarCore::Incidence::Ptr incidence;
0085         if (memcal->events().count() > 1) {
0086             const auto memcalEvents{memcal->events()};
0087             for (const KCalendarCore::Event::Ptr &event : memcalEvents) {
0088                 qCDebugNC(EWSRES_LOG) << QString::number(event->recurrence()->recurrenceType(), 16) << event->recurrenceId() << event->recurrenceId().isValid();
0089                 if (!event->recurrenceId().isValid()) {
0090                     incidence = event;
0091                 }
0092             }
0093             const auto excList = ewsItem[EwsItemFieldModifiedOccurrences].value<EwsOccurrence::List>();
0094             for (const EwsOccurrence &exc : excList) {
0095                 addItems.append(exc.itemId());
0096             }
0097         } else if (memcal->events().count() == 1) {
0098             incidence = memcal->events()[0];
0099         }
0100         // KCalendarCore::Incidence::Ptr incidence(format.fromString(mimeContent));
0101 
0102         if (incidence) {
0103             QDateTime dt(incidence->dtStart());
0104             if (dt.isValid()) {
0105                 incidence->setDtStart(dt);
0106             }
0107             if (incidence->type() == KCalendarCore::Incidence::TypeEvent) {
0108                 auto event = reinterpret_cast<KCalendarCore::Event *>(incidence.data());
0109                 dt = event->dtEnd();
0110                 if (dt.isValid()) {
0111                     event->setDtEnd(dt);
0112                 }
0113             }
0114             dt = incidence->recurrenceId();
0115             if (dt.isValid()) {
0116                 incidence->setRecurrenceId(dt);
0117             }
0118 
0119             item.setPayload<KCalendarCore::Incidence::Ptr>(incidence);
0120         }
0121 
0122         ++it;
0123     }
0124 
0125     if (addItems.isEmpty()) {
0126         emitResult();
0127     } else {
0128         auto req = new EwsGetItemRequest(mClient, this);
0129         EwsItemShape shape(EwsShapeIdOnly);
0130         //        shape << EwsPropertyField(QStringLiteral("item:Attachments"));
0131         shape << EwsPropertyField(QStringLiteral("item:Body"));
0132         shape << EwsPropertyField(QStringLiteral("item:MimeContent"));
0133         //        shape << EwsPropertyField(QStringLiteral("calendar:TimeZone"));
0134         //        shape << EwsPropertyField(QStringLiteral("item:Culture"));
0135         req->setItemShape(shape);
0136 
0137         req->setItemIds(addItems);
0138         connect(req, &KJob::result, this, &EwsFetchCalendarDetailJob::exceptionItemsFetched);
0139         req->start();
0140     }
0141 }
0142 
0143 void EwsFetchCalendarDetailJob::exceptionItemsFetched(KJob *job)
0144 {
0145     if (job->error()) {
0146         setError(job->error());
0147         setErrorText(job->errorText());
0148         emitResult();
0149         return;
0150     }
0151 
0152     auto req = qobject_cast<EwsGetItemRequest *>(job);
0153 
0154     if (!req) {
0155         setError(1);
0156         setErrorText(QStringLiteral("Job is not an instance of EwsGetItemRequest"));
0157         emitResult();
0158         return;
0159     }
0160 
0161     KCalendarCore::ICalFormat format;
0162     const auto responses{req->responses()};
0163     for (const EwsGetItemRequest::Response &resp : responses) {
0164         if (!resp.isSuccess()) {
0165             qCWarningNC(EWSRES_LOG) << QStringLiteral("Failed to fetch item.");
0166             continue;
0167         }
0168         const EwsItem &ewsItem = resp.item();
0169 
0170         Item item(KCalendarCore::Event::eventMimeType());
0171         item.setParentCollection(mCollection);
0172         auto id = ewsItem[EwsItemFieldItemId].value<EwsId>();
0173         item.setRemoteId(id.id());
0174         item.setRemoteRevision(id.changeKey());
0175 
0176         QString mimeContent = ewsItem[EwsItemFieldMimeContent].toString();
0177         KCalendarCore::Calendar::Ptr memcal(new KCalendarCore::MemoryCalendar(QTimeZone::utc()));
0178         format.fromString(memcal, mimeContent);
0179         KCalendarCore::Incidence::Ptr incidence(memcal->events().last());
0180         incidence->clearRecurrence();
0181 
0182         QDateTime dt(incidence->dtStart());
0183         if (dt.isValid()) {
0184             incidence->setDtStart(dt);
0185         }
0186         if (incidence->type() == KCalendarCore::Incidence::TypeEvent) {
0187             auto event = reinterpret_cast<KCalendarCore::Event *>(incidence.data());
0188             dt = event->dtEnd();
0189             if (dt.isValid()) {
0190                 event->setDtEnd(dt);
0191             }
0192         }
0193         dt = incidence->recurrenceId();
0194         if (dt.isValid()) {
0195             incidence->setRecurrenceId(dt);
0196         }
0197 
0198         item.setPayload<KCalendarCore::Incidence::Ptr>(incidence);
0199 
0200         mChangedItems.append(item);
0201     }
0202 
0203     emitResult();
0204 }
0205 
0206 #include "moc_ewsfetchcalendardetailjob.cpp"