File indexing completed on 2024-11-24 04:44:29

0001 /*
0002     This file is part of oxaccess.
0003 
0004     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "incidenceutils.h"
0010 
0011 #include "davmanager.h"
0012 #include "davutils.h"
0013 #include "oxutils.h"
0014 #include "users.h"
0015 
0016 #include <KCalendarCore/Event>
0017 #include <KCalendarCore/Todo>
0018 
0019 #include <QDomElement>
0020 
0021 #include <QBitArray>
0022 #include <QDebug>
0023 #include <QRegularExpression>
0024 
0025 using namespace OXA;
0026 
0027 static void parseMembersAttribute(const QDomElement &element, const KCalendarCore::Incidence::Ptr &incidence)
0028 {
0029     incidence->clearAttendees();
0030 
0031     for (QDomElement child = element.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
0032         if (child.tagName() == QLatin1StringView("user")) {
0033             const QString uid = child.text();
0034 
0035             const User user = Users::self()->lookupUid(uid.toLongLong());
0036 
0037             QString name;
0038             QString email;
0039             KCalendarCore::Attendee attendee = incidence->attendeeByUid(uid);
0040             if (!user.isValid()) {
0041                 if (!attendee.isNull()) {
0042                     continue;
0043                 }
0044 
0045                 name = uid;
0046                 email = uid + QLatin1Char('@') + DavManager::self()->baseUrl().host();
0047             } else {
0048                 name = user.name();
0049                 email = user.email();
0050             }
0051 
0052             if (!attendee.isNull()) {
0053                 attendee.setName(name);
0054                 attendee.setEmail(email);
0055             } else {
0056                 attendee = KCalendarCore::Attendee(name, email);
0057                 attendee.setUid(uid);
0058                 incidence->addAttendee(attendee);
0059             }
0060 
0061             const QString status = child.attribute(QStringLiteral("confirm"));
0062             if (!status.isEmpty()) {
0063                 if (status == QLatin1StringView("accept")) {
0064                     attendee.setStatus(KCalendarCore::Attendee::Accepted);
0065                 } else if (status == QLatin1StringView("decline")) {
0066                     attendee.setStatus(KCalendarCore::Attendee::Declined);
0067                 } else {
0068                     attendee.setStatus(KCalendarCore::Attendee::NeedsAction);
0069                 }
0070             }
0071         }
0072     }
0073 }
0074 
0075 static void parseIncidenceAttribute(const QDomElement &element, const KCalendarCore::Incidence::Ptr &incidence)
0076 {
0077     const QString tagName = element.tagName();
0078     const QString text = OXUtils::readString(element.text());
0079 
0080     if (tagName == QLatin1StringView("title")) {
0081         incidence->setSummary(text);
0082     } else if (tagName == QLatin1StringView("note")) {
0083         incidence->setDescription(text);
0084     } else if (tagName == QLatin1StringView("alarm")) {
0085         const int minutes = OXUtils::readNumber(element.text());
0086         if (minutes != 0) {
0087             KCalendarCore::Alarm::List alarms = incidence->alarms();
0088             KCalendarCore::Alarm::Ptr alarm;
0089             if (alarms.isEmpty()) {
0090                 alarm = incidence->newAlarm();
0091             } else {
0092                 alarm = alarms.first();
0093             }
0094 
0095             if (alarm->type() == KCalendarCore::Alarm::Invalid) {
0096                 alarm->setType(KCalendarCore::Alarm::Display);
0097             }
0098 
0099             KCalendarCore::Duration duration(minutes * -60);
0100             alarm->setStartOffset(duration);
0101             alarm->setEnabled(true);
0102         } else {
0103             // 0 reminder -> disable alarm
0104             incidence->clearAlarms();
0105         }
0106     } else if (tagName == QLatin1StringView("created_by")) {
0107         const User user = Users::self()->lookupUid(OXUtils::readNumber(element.text()));
0108         incidence->setOrganizer(KCalendarCore::Person(user.name(), user.email()));
0109     } else if (tagName == QLatin1StringView("participants")) {
0110         parseMembersAttribute(element, incidence);
0111     } else if (tagName == QLatin1StringView("private_flag")) {
0112         if (OXUtils::readBoolean(element.text()) == true) {
0113             incidence->setSecrecy(KCalendarCore::Incidence::SecrecyPrivate);
0114         } else {
0115             incidence->setSecrecy(KCalendarCore::Incidence::SecrecyPublic);
0116         }
0117     } else if (tagName == QLatin1StringView("categories")) {
0118         incidence->setCategories(text.split(QRegularExpression(QStringLiteral(",\\s*"))));
0119     }
0120 }
0121 
0122 static void parseEventAttribute(const QDomElement &element, const KCalendarCore::Event::Ptr &event)
0123 {
0124     const QString tagName = element.tagName();
0125     const QString text = OXUtils::readString(element.text());
0126 
0127     if (tagName == QLatin1StringView("start_date")) {
0128         QDateTime dateTime = OXUtils::readDateTime(element.text());
0129         event->setDtStart(dateTime);
0130     } else if (tagName == QLatin1StringView("end_date")) {
0131         QDateTime dateTime = OXUtils::readDateTime(element.text());
0132         if (event->allDay()) {
0133             dateTime = dateTime.addSecs(-1);
0134         }
0135 
0136         event->setDtEnd(dateTime);
0137     } else if (tagName == QLatin1StringView("location")) {
0138         event->setLocation(text);
0139     }
0140 }
0141 
0142 static void parseTodoAttribute(const QDomElement &element, const KCalendarCore::Todo::Ptr &todo)
0143 {
0144     const QString tagName = element.tagName();
0145     const QString text = OXUtils::readString(element.text());
0146 
0147     if (tagName == QLatin1StringView("start_date")) {
0148         const QDateTime dateTime = OXUtils::readDateTime(element.text());
0149         if (dateTime.isValid()) {
0150             todo->setDtStart(dateTime);
0151         }
0152     } else if (tagName == QLatin1StringView("end_date")) {
0153         const QDateTime dateTime = OXUtils::readDateTime(element.text());
0154         if (dateTime.isValid()) {
0155             todo->setDtDue(dateTime);
0156         }
0157     } else if (tagName == QLatin1StringView("priority")) {
0158         const int priorityNumber = OXUtils::readNumber(element.text());
0159         if (priorityNumber < 1 || priorityNumber > 3) {
0160             qDebug() << "Unknown priority:" << text;
0161         } else {
0162             int priority = 0;
0163             switch (priorityNumber) {
0164             case 1:
0165                 priority = 9;
0166                 break;
0167             case 2:
0168                 priority = 5;
0169                 break;
0170             case 3:
0171                 priority = 1;
0172                 break;
0173             }
0174             todo->setPriority(priority);
0175         }
0176     } else if (tagName == QLatin1StringView("percent_completed")) {
0177         todo->setPercentComplete(OXUtils::readNumber(element.text()));
0178     }
0179 }
0180 
0181 static void parseRecurrence(const QDomElement &element, const KCalendarCore::Incidence::Ptr &incidence)
0182 {
0183     QString type;
0184 
0185     int dailyValue = -1;
0186     QDateTime endDate;
0187 
0188     int weeklyValue = -1;
0189     QBitArray days(7); // days, starting with monday
0190     bool daysSet = false;
0191 
0192     int monthlyValueDay = -1;
0193     int monthlyValueMonth = -1;
0194 
0195     int yearlyValueDay = -1;
0196     int yearlyMonth = -1;
0197 
0198     int monthly2Recurrency = 0;
0199     int monthly2ValueMonth = -1;
0200 
0201     int yearly2Recurrency = 0;
0202     int yearly2Day = 0;
0203     int yearly2Month = -1;
0204 
0205     KCalendarCore::DateList deleteExceptions;
0206 
0207     for (QDomElement child = element.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
0208         const QString tagName = child.tagName();
0209         const QString text = OXUtils::readString(child.text());
0210 
0211         if (tagName == QLatin1StringView("recurrence_type")) {
0212             type = text;
0213         } else if (tagName == QLatin1StringView("interval")) {
0214             dailyValue = text.toInt();
0215             weeklyValue = text.toInt();
0216             monthlyValueMonth = text.toInt();
0217             monthly2ValueMonth = text.toInt();
0218         } else if (tagName == QLatin1StringView("days")) {
0219             int tmp = text.toInt(); // OX encodes days binary: 1=Su, 2=Mo, 4=Tu, ...
0220             for (int i = 0; i < 7; ++i) {
0221                 if (tmp & (1 << i)) {
0222                     days.setBit((i + 6) % 7);
0223                 }
0224             }
0225             daysSet = true;
0226         } else if (tagName == QLatin1StringView("day_in_month")) {
0227             monthlyValueDay = text.toInt();
0228             monthly2Recurrency = text.toInt();
0229             yearlyValueDay = text.toInt();
0230             yearly2Recurrency = text.toInt();
0231         } else if (tagName == QLatin1StringView("month")) {
0232             yearlyMonth = text.toInt() + 1; // starts at 0
0233             yearly2Month = text.toInt() + 1;
0234         } else if ((tagName == QLatin1StringView("deleteexceptions")) || (tagName == QLatin1StringView("changeexceptions"))) {
0235             const QStringList exceptionDates = text.split(QLatin1Char(','));
0236             deleteExceptions.reserve(exceptionDates.count());
0237             for (const QString &date : exceptionDates) {
0238                 deleteExceptions.append(OXUtils::readDate(date));
0239             }
0240         } else if (tagName == QLatin1StringView("until")) {
0241             endDate = OXUtils::readDateTime(child.text());
0242         }
0243         // TODO: notification
0244     }
0245 
0246     if (daysSet && type == QLatin1StringView("monthly")) {
0247         type = QStringLiteral("monthly2"); // HACK: OX doesn't cleanly distinguish between monthly and monthly2
0248     }
0249     if (daysSet && type == QLatin1StringView("yearly")) {
0250         type = QStringLiteral("yearly2");
0251     }
0252 
0253     KCalendarCore::Recurrence *recurrence = incidence->recurrence();
0254 
0255     if (type == QLatin1StringView("daily")) {
0256         recurrence->setDaily(dailyValue);
0257     } else if (type == QLatin1StringView("weekly")) {
0258         recurrence->setWeekly(weeklyValue, days);
0259     } else if (type == QLatin1StringView("monthly")) {
0260         recurrence->setMonthly(monthlyValueMonth);
0261         recurrence->addMonthlyDate(monthlyValueDay);
0262     } else if (type == QLatin1StringView("yearly")) {
0263         recurrence->setYearly(1);
0264         recurrence->addYearlyDate(yearlyValueDay);
0265         recurrence->addYearlyMonth(yearlyMonth);
0266     } else if (type == QLatin1StringView("monthly2")) {
0267         recurrence->setMonthly(monthly2ValueMonth);
0268         QBitArray _days(7);
0269         if (daysSet) {
0270             _days = days;
0271         } else {
0272             _days.setBit(incidence->dtStart().date().dayOfWeek());
0273         }
0274         recurrence->addMonthlyPos(monthly2Recurrency, _days);
0275     } else if (type == QLatin1StringView("yearly2")) {
0276         recurrence->setYearly(1);
0277         recurrence->addYearlyMonth(yearly2Month);
0278         QBitArray _days(7);
0279         if (daysSet) {
0280             _days = days;
0281         } else {
0282             _days.setBit((yearly2Day + 5) % 7);
0283         }
0284         recurrence->addYearlyPos(yearly2Recurrency, _days);
0285     }
0286 
0287     if (endDate.isValid()) {
0288         recurrence->setEndDate(endDate.date());
0289     }
0290 
0291     recurrence->setExDates(deleteExceptions);
0292 }
0293 
0294 static void createIncidenceAttributes(QDomDocument &document, QDomElement &parent, const KCalendarCore::Incidence::Ptr &incidence)
0295 {
0296     DAVUtils::addOxElement(document, parent, QStringLiteral("title"), OXUtils::writeString(incidence->summary()));
0297     DAVUtils::addOxElement(document, parent, QStringLiteral("note"), OXUtils::writeString(incidence->description()));
0298 
0299     if (incidence->attendeeCount() > 0) {
0300         QDomElement members = DAVUtils::addOxElement(document, parent, QStringLiteral("participants"));
0301         const KCalendarCore::Attendee::List attendees = incidence->attendees();
0302         for (const KCalendarCore::Attendee &attendee : attendees) {
0303             const User user = Users::self()->lookupEmail(attendee.email());
0304 
0305             if (!user.isValid()) {
0306                 continue;
0307             }
0308 
0309             QString status;
0310             switch (attendee.status()) {
0311             case KCalendarCore::Attendee::Accepted:
0312                 status = QStringLiteral("accept");
0313                 break;
0314             case KCalendarCore::Attendee::Declined:
0315                 status = QStringLiteral("decline");
0316                 break;
0317             default:
0318                 status = QStringLiteral("none");
0319                 break;
0320             }
0321 
0322             QDomElement element = DAVUtils::addOxElement(document, members, QStringLiteral("user"), OXUtils::writeNumber(user.uid()));
0323             DAVUtils::setOxAttribute(element, QStringLiteral("confirm"), status);
0324         }
0325     }
0326 
0327     if (incidence->secrecy() == KCalendarCore::Incidence::SecrecyPublic) {
0328         DAVUtils::addOxElement(document, parent, QStringLiteral("private_flag"), OXUtils::writeBoolean(false));
0329     } else {
0330         DAVUtils::addOxElement(document, parent, QStringLiteral("private_flag"), OXUtils::writeBoolean(true));
0331     }
0332 
0333     // set reminder as the number of minutes to the start of the event
0334     const KCalendarCore::Alarm::List alarms = incidence->alarms();
0335     if (!alarms.isEmpty() && alarms.first()->hasStartOffset() && alarms.first()->enabled()) {
0336         DAVUtils::addOxElement(document, parent, QStringLiteral("alarm_flag"), OXUtils::writeBoolean(true));
0337         DAVUtils::addOxElement(document, parent, QStringLiteral("alarm"), OXUtils::writeNumber((-1) * alarms.first()->startOffset().asSeconds() / 60));
0338     } else {
0339         DAVUtils::addOxElement(document, parent, QStringLiteral("alarm_flag"), OXUtils::writeBoolean(false));
0340         DAVUtils::addOxElement(document, parent, QStringLiteral("alarm"), QStringLiteral("0"));
0341     }
0342 
0343     // categories
0344     DAVUtils::addOxElement(document, parent, QStringLiteral("categories"), OXUtils::writeString(incidence->categories().join(QLatin1StringView(", "))));
0345 }
0346 
0347 static void createEventAttributes(QDomDocument &document, QDomElement &parent, const KCalendarCore::Event::Ptr &event)
0348 {
0349     if (event->allDay()) {
0350         DAVUtils::addOxElement(document, parent, QStringLiteral("start_date"), OXUtils::writeDate(event->dtStart().date()));
0351         if (event->hasEndDate()) {
0352             DAVUtils::addOxElement(document, parent, QStringLiteral("end_date"), OXUtils::writeDate(event->dtEnd().date()));
0353         }
0354     } else {
0355         DAVUtils::addOxElement(document, parent, QStringLiteral("start_date"), OXUtils::writeDateTime(event->dtStart()));
0356         if (event->hasEndDate()) {
0357             DAVUtils::addOxElement(document, parent, QStringLiteral("end_date"), OXUtils::writeDateTime(event->dtEnd()));
0358         }
0359     }
0360 
0361     if (!event->hasEndDate()) {
0362         DAVUtils::addOxElement(document, parent, QStringLiteral("end_date"));
0363     }
0364 
0365     DAVUtils::addOxElement(document, parent, QStringLiteral("location"), OXUtils::writeString(event->location()));
0366     DAVUtils::addOxElement(document, parent, QStringLiteral("full_time"), OXUtils::writeBoolean(event->allDay()));
0367 
0368     if (event->transparency() == KCalendarCore::Event::Transparent) {
0369         DAVUtils::addOxElement(document, parent, QStringLiteral("shown_as"), OXUtils::writeNumber(4));
0370     } else if (event->transparency() == KCalendarCore::Event::Opaque) {
0371         DAVUtils::addOxElement(document, parent, QStringLiteral("shown_as"), OXUtils::writeNumber(1));
0372     }
0373 }
0374 
0375 static void createTaskAttributes(QDomDocument &document, QDomElement &parent, const KCalendarCore::Todo::Ptr &todo)
0376 {
0377     if (todo->hasStartDate()) {
0378         DAVUtils::addOxElement(document, parent, QStringLiteral("start_date"), OXUtils::writeDateTime(todo->dtStart()));
0379     } else {
0380         DAVUtils::addOxElement(document, parent, QStringLiteral("start_date"));
0381     }
0382 
0383     if (todo->hasDueDate()) {
0384         DAVUtils::addOxElement(document, parent, QStringLiteral("end_date"), OXUtils::writeDateTime(todo->dtDue()));
0385     } else {
0386         DAVUtils::addOxElement(document, parent, QStringLiteral("end_date"));
0387     }
0388 
0389     QString priority;
0390     switch (todo->priority()) {
0391     case 9:
0392     case 8:
0393         priority = QStringLiteral("1");
0394         break;
0395     case 2:
0396     case 1:
0397         priority = QStringLiteral("3");
0398         break;
0399     default:
0400         priority = QStringLiteral("2");
0401         break;
0402     }
0403     DAVUtils::addOxElement(document, parent, QStringLiteral("priority"), priority);
0404 
0405     DAVUtils::addOxElement(document, parent, QStringLiteral("percent_completed"), OXUtils::writeNumber(todo->percentComplete()));
0406 }
0407 
0408 static void createRecurrenceAttributes(QDomDocument &document, QDomElement &parent, const KCalendarCore::Incidence::Ptr &incidence)
0409 {
0410     if (!incidence->recurs()) {
0411         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("none"));
0412         return;
0413     }
0414 
0415     const KCalendarCore::Recurrence *recurrence = incidence->recurrence();
0416     int monthOffset = -1;
0417     switch (recurrence->recurrenceType()) {
0418     case KCalendarCore::Recurrence::rDaily:
0419         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("daily"));
0420         DAVUtils::addOxElement(document, parent, QStringLiteral("interval"), OXUtils::writeNumber(recurrence->frequency()));
0421         break;
0422     case KCalendarCore::Recurrence::rWeekly: {
0423         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("weekly"));
0424         DAVUtils::addOxElement(document, parent, QStringLiteral("interval"), OXUtils::writeNumber(recurrence->frequency()));
0425 
0426         int days = 0;
0427         for (int i = 0; i < 7; ++i) {
0428             if (recurrence->days()[i]) {
0429                 days += 1 << ((i + 1) % 7);
0430             }
0431         }
0432 
0433         DAVUtils::addOxElement(document, parent, QStringLiteral("days"), OXUtils::writeNumber(days));
0434         break;
0435     }
0436     case KCalendarCore::Recurrence::rMonthlyDay:
0437         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("monthly"));
0438         DAVUtils::addOxElement(document, parent, QStringLiteral("interval"), OXUtils::writeNumber(recurrence->frequency()));
0439         DAVUtils::addOxElement(document, parent, QStringLiteral("day_in_month"), OXUtils::writeNumber(recurrence->monthDays().first()));
0440         break;
0441     case KCalendarCore::Recurrence::rMonthlyPos: {
0442         const KCalendarCore::RecurrenceRule::WDayPos wdp = recurrence->monthPositions().constFirst();
0443 
0444         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("monthly"));
0445         DAVUtils::addOxElement(document, parent, QStringLiteral("interval"), OXUtils::writeNumber(recurrence->frequency()));
0446         DAVUtils::addOxElement(document, parent, QStringLiteral("days"), OXUtils::writeNumber(1 << wdp.day()));
0447         DAVUtils::addOxElement(document, parent, QStringLiteral("day_in_month"), OXUtils::writeNumber(wdp.pos()));
0448         break;
0449     }
0450     case KCalendarCore::Recurrence::rYearlyMonth:
0451         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("yearly"));
0452         DAVUtils::addOxElement(document, parent, QStringLiteral("interval"), QStringLiteral("1"));
0453         DAVUtils::addOxElement(document, parent, QStringLiteral("day_in_month"), OXUtils::writeNumber(recurrence->yearDates().constFirst()));
0454         DAVUtils::addOxElement(document, parent, QStringLiteral("month"), OXUtils::writeNumber(recurrence->yearMonths().constFirst() + monthOffset));
0455         break;
0456     case KCalendarCore::Recurrence::rYearlyPos: {
0457         const KCalendarCore::RecurrenceRule::WDayPos wdp = recurrence->monthPositions().constFirst();
0458 
0459         DAVUtils::addOxElement(document, parent, QStringLiteral("recurrence_type"), QStringLiteral("yearly"));
0460         DAVUtils::addOxElement(document, parent, QStringLiteral("interval"), QStringLiteral("1"));
0461         DAVUtils::addOxElement(document, parent, QStringLiteral("days"), OXUtils::writeNumber(1 << wdp.day()));
0462         DAVUtils::addOxElement(document, parent, QStringLiteral("day_in_month"), OXUtils::writeNumber(wdp.pos()));
0463         DAVUtils::addOxElement(document, parent, QStringLiteral("month"), OXUtils::writeNumber(recurrence->yearMonths().constFirst() + monthOffset));
0464         break;
0465     }
0466     default:
0467         qDebug() << "unsupported recurrence type:" << recurrence->recurrenceType();
0468     }
0469 
0470     if (recurrence->endDateTime().isValid()) {
0471         DAVUtils::addOxElement(document, parent, QStringLiteral("until"), OXUtils::writeDateTime(recurrence->endDateTime()));
0472     } else {
0473         DAVUtils::addOxElement(document, parent, QStringLiteral("until"));
0474     }
0475 
0476     // delete exceptions
0477     const KCalendarCore::DateList exceptionList = recurrence->exDates();
0478 
0479     QStringList dates;
0480     dates.reserve(exceptionList.count());
0481     for (const QDate &date : exceptionList) {
0482         dates.append(OXUtils::writeDate(date));
0483     }
0484 
0485     DAVUtils::addOxElement(document, parent, QStringLiteral("deleteexceptions"), dates.join(QLatin1Char(',')));
0486 
0487     // TODO: changeexceptions
0488 }
0489 
0490 void OXA::IncidenceUtils::parseEvent(const QDomElement &propElement, Object &object)
0491 {
0492     KCalendarCore::Event::Ptr event(new KCalendarCore::Event);
0493 
0494     const QDomElement fullTimeElement = propElement.firstChildElement(QStringLiteral("full_time"));
0495     if (!fullTimeElement.isNull()) {
0496         event->setAllDay(OXUtils::readBoolean(fullTimeElement.text()));
0497     }
0498 
0499     const QDomElement ShowAsElement = propElement.firstChildElement(QStringLiteral("shown_as"));
0500     if (!ShowAsElement.isNull()) {
0501         int showAs = OXUtils::readNumber(ShowAsElement.text());
0502         switch (showAs) {
0503         case 1:
0504             event->setTransparency(KCalendarCore::Event::Transparent);
0505             break;
0506         case 4:
0507             event->setTransparency(KCalendarCore::Event::Opaque);
0508             break;
0509         default:
0510             event->setTransparency(KCalendarCore::Event::Opaque);
0511         }
0512     }
0513 
0514     bool doesRecur = false;
0515     const QDomElement recurrenceTypeElement = propElement.firstChildElement(QStringLiteral("recurrence_type"));
0516     if (!recurrenceTypeElement.isNull() && recurrenceTypeElement.text() != QLatin1StringView("none")) {
0517         doesRecur = true;
0518     }
0519 
0520     QDomElement element = propElement.firstChildElement();
0521     while (!element.isNull()) {
0522         parseIncidenceAttribute(element, event);
0523         parseEventAttribute(element, event);
0524 
0525         element = element.nextSiblingElement();
0526     }
0527 
0528     if (doesRecur) {
0529         parseRecurrence(propElement, event);
0530     } else {
0531         event->recurrence()->unsetRecurs();
0532     }
0533 
0534     object.setEvent(KCalendarCore::Incidence::Ptr(event));
0535 }
0536 
0537 void OXA::IncidenceUtils::parseTask(const QDomElement &propElement, Object &object)
0538 {
0539     KCalendarCore::Todo::Ptr todo(new KCalendarCore::Todo);
0540     todo->setSecrecy(KCalendarCore::Incidence::SecrecyPrivate);
0541 
0542     bool doesRecur = false;
0543     const QDomElement recurrenceTypeElement = propElement.firstChildElement(QStringLiteral("recurrence_type"));
0544     if (!recurrenceTypeElement.isNull() && recurrenceTypeElement.text() != QLatin1StringView("none")) {
0545         doesRecur = true;
0546     }
0547 
0548     QDomElement element = propElement.firstChildElement();
0549     while (!element.isNull()) {
0550         parseIncidenceAttribute(element, todo);
0551         parseTodoAttribute(element, todo);
0552 
0553         element = element.nextSiblingElement();
0554     }
0555 
0556     if (doesRecur) {
0557         parseRecurrence(propElement, todo);
0558     } else {
0559         todo->recurrence()->unsetRecurs();
0560     }
0561 
0562     object.setTask(KCalendarCore::Incidence::Ptr(todo));
0563 }
0564 
0565 void OXA::IncidenceUtils::addEventElements(QDomDocument &document, QDomElement &propElement, const Object &object)
0566 {
0567     createIncidenceAttributes(document, propElement, object.event());
0568     createEventAttributes(document, propElement, object.event().staticCast<KCalendarCore::Event>());
0569     createRecurrenceAttributes(document, propElement, object.event());
0570 }
0571 
0572 void OXA::IncidenceUtils::addTaskElements(QDomDocument &document, QDomElement &propElement, const Object &object)
0573 {
0574     createIncidenceAttributes(document, propElement, object.task());
0575     createTaskAttributes(document, propElement, object.task().staticCast<KCalendarCore::Todo>());
0576     createRecurrenceAttributes(document, propElement, object.task());
0577 }