File indexing completed on 2024-12-01 04:47:50

0001 /*
0002     This file is part of the kolab resource - the implementation of the
0003     Kolab storage format. See www.kolab.org for documentation on this.
0004 
0005     SPDX-FileCopyrightText: 2004 Bo Thorsen <bo@sonofthor.dk>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "event.h"
0011 #include "pimkolab_debug.h"
0012 
0013 using namespace KolabV2;
0014 
0015 KCalendarCore::Event::Ptr Event::fromXml(const QDomDocument &xmlDoc, const QString &tz)
0016 {
0017     Event event(tz);
0018     event.loadXML(xmlDoc);
0019     KCalendarCore::Event::Ptr kcalEvent(new KCalendarCore::Event());
0020     event.saveTo(kcalEvent);
0021     return kcalEvent;
0022 }
0023 
0024 QString Event::eventToXML(const KCalendarCore::Event::Ptr &kcalEvent, const QString &tz)
0025 {
0026     Event event(tz, kcalEvent);
0027     return event.saveXML();
0028 }
0029 
0030 Event::Event(const QString &tz, const KCalendarCore::Event::Ptr &event)
0031     : Incidence(tz, event)
0032     , mShowTimeAs(KCalendarCore::Event::Opaque)
0033     , mHasEndDate(false)
0034 {
0035     if (event) {
0036         setFields(event);
0037     }
0038 }
0039 
0040 Event::~Event() = default;
0041 
0042 void Event::setTransparency(KCalendarCore::Event::Transparency transparency)
0043 {
0044     mShowTimeAs = transparency;
0045 }
0046 
0047 KCalendarCore::Event::Transparency Event::transparency() const
0048 {
0049     return mShowTimeAs;
0050 }
0051 
0052 void Event::setEndDate(const QDateTime &date)
0053 {
0054     mEndDate = date;
0055     mHasEndDate = true;
0056     if (mFloatingStatus == AllDay) {
0057         qCDebug(PIMKOLAB_LOG) << "ERROR: Time on end date but no time on the event";
0058     }
0059     mFloatingStatus = HasTime;
0060 }
0061 
0062 void Event::setEndDate(const QDate &date)
0063 {
0064     mEndDate = QDateTime(date, QTime());
0065     mHasEndDate = true;
0066     if (mFloatingStatus == HasTime) {
0067         qCDebug(PIMKOLAB_LOG) << "ERROR: No time on end date but time on the event";
0068     }
0069     mFloatingStatus = AllDay;
0070 }
0071 
0072 void Event::setEndDate(const QString &endDate)
0073 {
0074     if (endDate.length() > 10) {
0075         // This is a date + time
0076         setEndDate(stringToDateTime(endDate));
0077     } else {
0078         // This is only a date
0079         setEndDate(stringToDate(endDate));
0080     }
0081 }
0082 
0083 QDateTime Event::endDate() const
0084 {
0085     return mEndDate;
0086 }
0087 
0088 bool Event::loadAttribute(QDomElement &element)
0089 {
0090     // This method doesn't handle the color-label tag yet
0091     QString tagName = element.tagName();
0092 
0093     if (tagName == QLatin1StringView("show-time-as")) {
0094         // TODO: Support tentative and outofoffice
0095         if (element.text() == QLatin1StringView("free")) {
0096             setTransparency(KCalendarCore::Event::Transparent);
0097         } else {
0098             setTransparency(KCalendarCore::Event::Opaque);
0099         }
0100     } else if (tagName == QLatin1StringView("end-date")) {
0101         setEndDate(element.text());
0102     } else {
0103         return Incidence::loadAttribute(element);
0104     }
0105 
0106     // We handled this
0107     return true;
0108 }
0109 
0110 bool Event::saveAttributes(QDomElement &element) const
0111 {
0112     // Save the base class elements
0113     Incidence::saveAttributes(element);
0114 
0115     // TODO: Support tentative and outofoffice
0116     if (transparency() == KCalendarCore::Event::Transparent) {
0117         writeString(element, QStringLiteral("show-time-as"), QStringLiteral("free"));
0118     } else {
0119         writeString(element, QStringLiteral("show-time-as"), QStringLiteral("busy"));
0120     }
0121     if (mHasEndDate) {
0122         if (mFloatingStatus == HasTime) {
0123             writeString(element, QStringLiteral("end-date"), dateTimeToString(endDate()));
0124         } else {
0125             writeString(element, QStringLiteral("end-date"), dateToString(endDate().date()));
0126         }
0127     }
0128 
0129     return true;
0130 }
0131 
0132 bool Event::loadXML(const QDomDocument &document)
0133 {
0134     QDomElement top = document.documentElement();
0135 
0136     if (top.tagName() != QLatin1StringView("event")) {
0137         qCWarning(PIMKOLAB_LOG) << QStringLiteral("XML error: Top tag was %1 instead of the expected event").arg(top.tagName());
0138         return false;
0139     }
0140 
0141     for (QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling()) {
0142         if (n.isComment()) {
0143             continue;
0144         }
0145         if (n.isElement()) {
0146             QDomElement e = n.toElement();
0147             loadAttribute(e);
0148         } else {
0149             qCDebug(PIMKOLAB_LOG) << "Node is not a comment or an element???";
0150         }
0151     }
0152 
0153     return true;
0154 }
0155 
0156 QString Event::saveXML() const
0157 {
0158     QDomDocument document = domTree();
0159     QDomElement element = document.createElement(QStringLiteral("event"));
0160     element.setAttribute(QStringLiteral("version"), QStringLiteral("1.0"));
0161     saveAttributes(element);
0162     document.appendChild(element);
0163     return document.toString();
0164 }
0165 
0166 void Event::setFields(const KCalendarCore::Event::Ptr &event)
0167 {
0168     Incidence::setFields(event);
0169 
0170     // note: if hasEndDate() is false and hasDuration() is true
0171     // dtEnd() returns start+duration
0172     if (event->hasEndDate() || event->hasDuration()) {
0173         if (event->allDay()) {
0174             // This is an all-day event. Don't timezone move this one
0175             mFloatingStatus = AllDay;
0176             setEndDate(event->dtEnd().date());
0177         } else {
0178             mFloatingStatus = HasTime;
0179             setEndDate(localToUTC(event->dtEnd()));
0180         }
0181     } else {
0182         mHasEndDate = false;
0183     }
0184     setTransparency(event->transparency());
0185 }
0186 
0187 void Event::saveTo(const KCalendarCore::Event::Ptr &event)
0188 {
0189     Incidence::saveTo(event);
0190 
0191     // PORT KF6 ? method removed event->setHasEndDate( mHasEndDate );
0192     if (mHasEndDate) {
0193         if (mFloatingStatus == AllDay) {
0194             // This is an all-day event. Don't timezone move this one
0195             event->setDtEnd(endDate());
0196         } else {
0197             event->setDtEnd(utcToLocal(endDate()));
0198         }
0199     }
0200     event->setTransparency(transparency());
0201 }