File indexing completed on 2024-04-28 11:34:02

0001 /*
0002   This file is part of the kcalcore library.
0003 
0004   SPDX-FileCopyrightText: 1998 Preston Brown <pbrown@kde.org>
0005   SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
0006   SPDX-FileCopyrightText: 2003 David Jarvie <djarvie@kde.org>
0007 
0008   SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 /**
0011   @file
0012   This file is part of the API for handling calendar data and
0013   defines the Alarm class.
0014 
0015   @brief
0016   Represents an alarm notification.
0017 
0018   @author Cornelius Schumacher \<schumacher@kde.org\>
0019 */
0020 #include "alarm.h"
0021 #include "incidence.h"
0022 #include "utils_p.h"
0023 
0024 #include <QTime>
0025 #include <QTimeZone>
0026 
0027 using namespace KCalendarCore;
0028 
0029 /**
0030   Private class that helps to provide binary compatibility between releases.
0031   @internal
0032 */
0033 //@cond PRIVATE
0034 class Q_DECL_HIDDEN KCalendarCore::Alarm::Private
0035 {
0036 public:
0037     Private()
0038         : mParent(nullptr)
0039         , mType(Alarm::Invalid)
0040         , mAlarmSnoozeTime(5)
0041         , mAlarmRepeatCount(0)
0042         , mEndOffset(false)
0043         , mHasTime(false)
0044         , mAlarmEnabled(false)
0045         , mHasLocationRadius(false)
0046         , mLocationRadius(0)
0047     {
0048     }
0049 
0050     Incidence *mParent = nullptr; // the incidence which this alarm belongs to
0051 
0052     Type mType; // type of alarm
0053     QString mDescription; // text to display/email body/procedure arguments
0054     QString mFile; // program to run/optional audio file to play
0055     QString mMailSubject; // subject of email
0056     QStringList mMailAttachFiles; // filenames to attach to email
0057     Person::List mMailAddresses; // who to mail for reminder
0058 
0059     QDateTime mAlarmTime; // time at which to trigger the alarm
0060     Duration mAlarmSnoozeTime; // how long after alarm to snooze before
0061     // triggering again
0062     int mAlarmRepeatCount; // number of times for alarm to repeat
0063     // after the initial time
0064 
0065     Duration mOffset; // time relative to incidence DTSTART
0066     // to trigger the alarm
0067     bool mEndOffset; // if true, mOffset relates to DTEND, not DTSTART
0068     bool mHasTime; // use mAlarmTime, not mOffset
0069     bool mAlarmEnabled;
0070 
0071     bool mHasLocationRadius;
0072     int mLocationRadius; // location radius for the alarm
0073 };
0074 //@endcond
0075 
0076 Alarm::Alarm(Incidence *parent)
0077     : d(new KCalendarCore::Alarm::Private)
0078 {
0079     d->mParent = parent;
0080 }
0081 
0082 Alarm::Alarm(const Alarm &other)
0083     : CustomProperties(other)
0084     , d(new KCalendarCore::Alarm::Private(*other.d))
0085 {
0086 }
0087 
0088 Alarm::~Alarm()
0089 {
0090     delete d;
0091 }
0092 
0093 Alarm &Alarm::operator=(const Alarm &a)
0094 {
0095     if (&a != this) {
0096         d->mParent = a.d->mParent;
0097         d->mType = a.d->mType;
0098         d->mDescription = a.d->mDescription;
0099         d->mFile = a.d->mFile;
0100         d->mMailAttachFiles = a.d->mMailAttachFiles;
0101         d->mMailAddresses = a.d->mMailAddresses;
0102         d->mMailSubject = a.d->mMailSubject;
0103         d->mAlarmSnoozeTime = a.d->mAlarmSnoozeTime;
0104         d->mAlarmRepeatCount = a.d->mAlarmRepeatCount;
0105         d->mAlarmTime = a.d->mAlarmTime;
0106         d->mOffset = a.d->mOffset;
0107         d->mEndOffset = a.d->mEndOffset;
0108         d->mHasTime = a.d->mHasTime;
0109         d->mAlarmEnabled = a.d->mAlarmEnabled;
0110     }
0111 
0112     return *this;
0113 }
0114 
0115 static bool compareMailAddresses(const Person::List &list1, const Person::List &list2)
0116 {
0117     if (list1.count() == list2.count()) {
0118         for (int i = 0; i < list1.count(); ++i) {
0119             if (list1.at(i) != list2.at(i)) {
0120                 return false;
0121             }
0122         }
0123         return true;
0124     }
0125 
0126     return false;
0127 }
0128 
0129 bool Alarm::operator==(const Alarm &rhs) const
0130 {
0131     if (d->mType != rhs.d->mType //
0132         || d->mAlarmSnoozeTime != rhs.d->mAlarmSnoozeTime //
0133         || d->mAlarmRepeatCount != rhs.d->mAlarmRepeatCount //
0134         || d->mAlarmEnabled != rhs.d->mAlarmEnabled //
0135         || d->mHasTime != rhs.d->mHasTime //
0136         || d->mHasLocationRadius != rhs.d->mHasLocationRadius //
0137         || d->mLocationRadius != rhs.d->mLocationRadius) {
0138         return false;
0139     }
0140 
0141     if (d->mHasTime) {
0142         if (d->mAlarmTime != rhs.d->mAlarmTime) {
0143             return false;
0144         }
0145     } else {
0146         if (d->mOffset != rhs.d->mOffset || d->mEndOffset != rhs.d->mEndOffset) {
0147             return false;
0148         }
0149     }
0150 
0151     switch (d->mType) {
0152     case Display:
0153         return d->mDescription == rhs.d->mDescription;
0154 
0155     case Email:
0156         return d->mDescription == rhs.d->mDescription //
0157             && d->mMailAttachFiles == rhs.d->mMailAttachFiles //
0158             && compareMailAddresses(d->mMailAddresses, rhs.d->mMailAddresses) //
0159             && d->mMailSubject == rhs.d->mMailSubject;
0160 
0161     case Procedure:
0162         return d->mFile == rhs.d->mFile && d->mDescription == rhs.d->mDescription;
0163 
0164     case Audio:
0165         return d->mFile == rhs.d->mFile;
0166 
0167     case Invalid:
0168         break;
0169     }
0170     return false;
0171 }
0172 
0173 bool Alarm::operator!=(const Alarm &a) const
0174 {
0175     return !operator==(a);
0176 }
0177 
0178 void Alarm::setType(Alarm::Type type)
0179 {
0180     if (type == d->mType) {
0181         return;
0182     }
0183 
0184     if (d->mParent) {
0185         d->mParent->update();
0186     }
0187     switch (type) {
0188     case Display:
0189         d->mDescription.clear();
0190         break;
0191     case Procedure:
0192         d->mFile.clear();
0193         d->mDescription.clear();
0194         break;
0195     case Audio:
0196         d->mFile.clear();
0197         break;
0198     case Email:
0199         d->mMailSubject.clear();
0200         d->mDescription.clear();
0201         d->mMailAddresses.clear();
0202         d->mMailAttachFiles.clear();
0203         break;
0204     case Invalid:
0205         break;
0206     default:
0207         if (d->mParent) {
0208             d->mParent->updated(); // not really
0209         }
0210         return;
0211     }
0212     d->mType = type;
0213     if (d->mParent) {
0214         d->mParent->updated();
0215     }
0216 }
0217 
0218 Alarm::Type Alarm::type() const
0219 {
0220     return d->mType;
0221 }
0222 
0223 void Alarm::setAudioAlarm(const QString &audioFile)
0224 {
0225     if (d->mParent) {
0226         d->mParent->update();
0227     }
0228     d->mType = Audio;
0229     d->mFile = audioFile;
0230     if (d->mParent) {
0231         d->mParent->updated();
0232     }
0233 }
0234 
0235 void Alarm::setAudioFile(const QString &audioFile)
0236 {
0237     if (d->mType == Audio) {
0238         if (d->mParent) {
0239             d->mParent->update();
0240         }
0241         d->mFile = audioFile;
0242         if (d->mParent) {
0243             d->mParent->updated();
0244         }
0245     }
0246 }
0247 
0248 QString Alarm::audioFile() const
0249 {
0250     return (d->mType == Audio) ? d->mFile : QString();
0251 }
0252 
0253 void Alarm::setProcedureAlarm(const QString &programFile, const QString &arguments)
0254 {
0255     if (d->mParent) {
0256         d->mParent->update();
0257     }
0258     d->mType = Procedure;
0259     d->mFile = programFile;
0260     d->mDescription = arguments;
0261     if (d->mParent) {
0262         d->mParent->updated();
0263     }
0264 }
0265 
0266 void Alarm::setProgramFile(const QString &programFile)
0267 {
0268     if (d->mType == Procedure) {
0269         if (d->mParent) {
0270             d->mParent->update();
0271         }
0272         d->mFile = programFile;
0273         if (d->mParent) {
0274             d->mParent->updated();
0275         }
0276     }
0277 }
0278 
0279 QString Alarm::programFile() const
0280 {
0281     return (d->mType == Procedure) ? d->mFile : QString();
0282 }
0283 
0284 void Alarm::setProgramArguments(const QString &arguments)
0285 {
0286     if (d->mType == Procedure) {
0287         if (d->mParent) {
0288             d->mParent->update();
0289         }
0290         d->mDescription = arguments;
0291         if (d->mParent) {
0292             d->mParent->updated();
0293         }
0294     }
0295 }
0296 
0297 QString Alarm::programArguments() const
0298 {
0299     return (d->mType == Procedure) ? d->mDescription : QString();
0300 }
0301 
0302 void Alarm::setEmailAlarm(const QString &subject, const QString &text, const Person::List &addressees, const QStringList &attachments)
0303 {
0304     if (d->mParent) {
0305         d->mParent->update();
0306     }
0307     d->mType = Email;
0308     d->mMailSubject = subject;
0309     d->mDescription = text;
0310     d->mMailAddresses = addressees;
0311     d->mMailAttachFiles = attachments;
0312     if (d->mParent) {
0313         d->mParent->updated();
0314     }
0315 }
0316 
0317 void Alarm::setMailAddress(const Person &mailAddress)
0318 {
0319     if (d->mType == Email) {
0320         if (d->mParent) {
0321             d->mParent->update();
0322         }
0323         d->mMailAddresses.clear();
0324         d->mMailAddresses.append(mailAddress);
0325         if (d->mParent) {
0326             d->mParent->updated();
0327         }
0328     }
0329 }
0330 
0331 void Alarm::setMailAddresses(const Person::List &mailAddresses)
0332 {
0333     if (d->mType == Email) {
0334         if (d->mParent) {
0335             d->mParent->update();
0336         }
0337         d->mMailAddresses += mailAddresses;
0338         if (d->mParent) {
0339             d->mParent->updated();
0340         }
0341     }
0342 }
0343 
0344 void Alarm::addMailAddress(const Person &mailAddress)
0345 {
0346     if (d->mType == Email) {
0347         if (d->mParent) {
0348             d->mParent->update();
0349         }
0350         d->mMailAddresses.append(mailAddress);
0351         if (d->mParent) {
0352             d->mParent->updated();
0353         }
0354     }
0355 }
0356 
0357 Person::List Alarm::mailAddresses() const
0358 {
0359     return (d->mType == Email) ? d->mMailAddresses : Person::List();
0360 }
0361 
0362 void Alarm::setMailSubject(const QString &mailAlarmSubject)
0363 {
0364     if (d->mType == Email) {
0365         if (d->mParent) {
0366             d->mParent->update();
0367         }
0368         d->mMailSubject = mailAlarmSubject;
0369         if (d->mParent) {
0370             d->mParent->updated();
0371         }
0372     }
0373 }
0374 
0375 QString Alarm::mailSubject() const
0376 {
0377     return (d->mType == Email) ? d->mMailSubject : QString();
0378 }
0379 
0380 void Alarm::setMailAttachment(const QString &mailAttachFile)
0381 {
0382     if (d->mType == Email) {
0383         if (d->mParent) {
0384             d->mParent->update();
0385         }
0386         d->mMailAttachFiles.clear();
0387         d->mMailAttachFiles += mailAttachFile;
0388         if (d->mParent) {
0389             d->mParent->updated();
0390         }
0391     }
0392 }
0393 
0394 void Alarm::setMailAttachments(const QStringList &mailAttachFiles)
0395 {
0396     if (d->mType == Email) {
0397         if (d->mParent) {
0398             d->mParent->update();
0399         }
0400         d->mMailAttachFiles = mailAttachFiles;
0401         if (d->mParent) {
0402             d->mParent->updated();
0403         }
0404     }
0405 }
0406 
0407 void Alarm::addMailAttachment(const QString &mailAttachFile)
0408 {
0409     if (d->mType == Email) {
0410         if (d->mParent) {
0411             d->mParent->update();
0412         }
0413         d->mMailAttachFiles += mailAttachFile;
0414         if (d->mParent) {
0415             d->mParent->updated();
0416         }
0417     }
0418 }
0419 
0420 QStringList Alarm::mailAttachments() const
0421 {
0422     return (d->mType == Email) ? d->mMailAttachFiles : QStringList();
0423 }
0424 
0425 void Alarm::setMailText(const QString &text)
0426 {
0427     if (d->mType == Email) {
0428         if (d->mParent) {
0429             d->mParent->update();
0430         }
0431         d->mDescription = text;
0432         if (d->mParent) {
0433             d->mParent->updated();
0434         }
0435     }
0436 }
0437 
0438 QString Alarm::mailText() const
0439 {
0440     return (d->mType == Email) ? d->mDescription : QString();
0441 }
0442 
0443 void Alarm::setDisplayAlarm(const QString &text)
0444 {
0445     if (d->mParent) {
0446         d->mParent->update();
0447     }
0448     d->mType = Display;
0449     if (!text.isNull()) {
0450         d->mDescription = text;
0451     }
0452     if (d->mParent) {
0453         d->mParent->updated();
0454     }
0455 }
0456 
0457 void Alarm::setText(const QString &text)
0458 {
0459     if (d->mType == Display) {
0460         if (d->mParent) {
0461             d->mParent->update();
0462         }
0463         d->mDescription = text;
0464         if (d->mParent) {
0465             d->mParent->updated();
0466         }
0467     }
0468 }
0469 
0470 QString Alarm::text() const
0471 {
0472     return (d->mType == Display) ? d->mDescription : QString();
0473 }
0474 
0475 void Alarm::setTime(const QDateTime &alarmTime)
0476 {
0477     if (d->mParent) {
0478         d->mParent->update();
0479     }
0480     d->mAlarmTime = alarmTime;
0481     d->mHasTime = true;
0482 
0483     if (d->mParent) {
0484         d->mParent->updated();
0485     }
0486 }
0487 
0488 QDateTime Alarm::time() const
0489 {
0490     if (hasTime()) {
0491         return d->mAlarmTime;
0492     } else if (d->mParent) {
0493         if (d->mEndOffset) {
0494             QDateTime dt = d->mParent->dateTime(Incidence::RoleAlarmEndOffset);
0495             return d->mOffset.end(dt);
0496         } else {
0497             QDateTime dt = d->mParent->dateTime(Incidence::RoleAlarmStartOffset);
0498             return d->mOffset.end(dt);
0499         }
0500     } else {
0501         return QDateTime();
0502     }
0503 }
0504 
0505 QDateTime Alarm::nextTime(const QDateTime &preTime, bool ignoreRepetitions) const
0506 {
0507     if (d->mParent && d->mParent->recurs()) {
0508         QDateTime dtEnd = d->mParent->dateTime(Incidence::RoleAlarmEndOffset);
0509 
0510         QDateTime dtStart = d->mParent->dtStart();
0511         // Find the incidence's earliest alarm
0512         // Alarm time is defined by an offset from the event start or end time.
0513         QDateTime alarmStart = d->mOffset.end(d->mEndOffset ? dtEnd : dtStart);
0514         // Find the offset from the event start time, which is also used as the
0515         // offset from the recurrence time.
0516         Duration alarmOffset(dtStart, alarmStart);
0517         /*
0518         qCDebug(KCALCORE_LOG) << "dtStart       " << dtStart;
0519         qCDebug(KCALCORE_LOG) << "dtEnd         " << dtEnd;
0520         qCDebug(KCALCORE_LOG) << "alarmStart    " << alarmStart;
0521         qCDebug(KCALCORE_LOG) << "alarmOffset   " << alarmOffset.value();
0522         qCDebug(KCALCORE_LOG) << "preTime       " << preTime;
0523         */
0524         if (alarmStart > preTime) {
0525             // No need to go further.
0526             return alarmStart;
0527         }
0528         if (d->mAlarmRepeatCount && !ignoreRepetitions) {
0529             // The alarm has repetitions, so check whether repetitions of previous
0530             // recurrences happen after given time.
0531             QDateTime prevRecurrence = d->mParent->recurrence()->getPreviousDateTime(preTime);
0532             if (prevRecurrence.isValid()) {
0533                 QDateTime prevLastRepeat = alarmOffset.end(duration().end(prevRecurrence));
0534                 // qCDebug(KCALCORE_LOG) << "prevRecurrence" << prevRecurrence;
0535                 // qCDebug(KCALCORE_LOG) << "prevLastRepeat" << prevLastRepeat;
0536                 if (prevLastRepeat > preTime) {
0537                     // Yes they did, return alarm offset to previous recurrence.
0538                     QDateTime prevAlarm = alarmOffset.end(prevRecurrence);
0539                     // qCDebug(KCALCORE_LOG) << "prevAlarm     " << prevAlarm;
0540                     return prevAlarm;
0541                 }
0542             }
0543         }
0544         // Check the next recurrence now.
0545         QDateTime nextRecurrence = d->mParent->recurrence()->getNextDateTime(preTime);
0546         if (nextRecurrence.isValid()) {
0547             QDateTime nextAlarm = alarmOffset.end(nextRecurrence);
0548             /*
0549             qCDebug(KCALCORE_LOG) << "nextRecurrence" << nextRecurrence;
0550             qCDebug(KCALCORE_LOG) << "nextAlarm     " << nextAlarm;
0551             */
0552             if (nextAlarm > preTime) {
0553                 // It's first alarm takes place after given time.
0554                 return nextAlarm;
0555             }
0556         }
0557     } else {
0558         // Not recurring.
0559         QDateTime alarmTime = time();
0560         if (alarmTime > preTime) {
0561             return alarmTime;
0562         }
0563     }
0564     return QDateTime();
0565 }
0566 
0567 bool Alarm::hasTime() const
0568 {
0569     return d->mHasTime;
0570 }
0571 
0572 void Alarm::shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
0573 {
0574     if (d->mParent) {
0575         d->mParent->update();
0576     }
0577     d->mAlarmTime = d->mAlarmTime.toTimeZone(oldZone);
0578     d->mAlarmTime.setTimeZone(newZone);
0579     if (d->mParent) {
0580         d->mParent->updated();
0581     }
0582 }
0583 
0584 void Alarm::setSnoozeTime(const Duration &alarmSnoozeTime)
0585 {
0586     if (alarmSnoozeTime.value() > 0) {
0587         if (d->mParent) {
0588             d->mParent->update();
0589         }
0590         d->mAlarmSnoozeTime = alarmSnoozeTime;
0591         if (d->mParent) {
0592             d->mParent->updated();
0593         }
0594     }
0595 }
0596 
0597 Duration Alarm::snoozeTime() const
0598 {
0599     return d->mAlarmSnoozeTime;
0600 }
0601 
0602 void Alarm::setRepeatCount(int alarmRepeatCount)
0603 {
0604     if (d->mParent) {
0605         d->mParent->update();
0606     }
0607     d->mAlarmRepeatCount = alarmRepeatCount;
0608     if (d->mParent) {
0609         d->mParent->updated();
0610     }
0611 }
0612 
0613 int Alarm::repeatCount() const
0614 {
0615     return d->mAlarmRepeatCount;
0616 }
0617 
0618 Duration Alarm::duration() const
0619 {
0620     return Duration(d->mAlarmSnoozeTime.value() * d->mAlarmRepeatCount, d->mAlarmSnoozeTime.type());
0621 }
0622 
0623 QDateTime Alarm::nextRepetition(const QDateTime &preTime) const
0624 {
0625     QDateTime at = nextTime(preTime);
0626     if (at > preTime) {
0627         return at;
0628     }
0629     if (!d->mAlarmRepeatCount) {
0630         // there isn't an occurrence after the specified time
0631         return QDateTime();
0632     }
0633     qint64 repetition;
0634     int interval = d->mAlarmSnoozeTime.value();
0635     bool daily = d->mAlarmSnoozeTime.isDaily();
0636     if (daily) {
0637         qint64 daysTo = at.daysTo(preTime);
0638         if (preTime.time() <= at.time()) {
0639             --daysTo;
0640         }
0641         repetition = daysTo / interval + 1;
0642     } else {
0643         repetition = at.secsTo(preTime) / interval + 1;
0644     }
0645     if (repetition > d->mAlarmRepeatCount) {
0646         // all repetitions have finished before the specified time
0647         return QDateTime();
0648     }
0649     return daily ? at.addDays(int(repetition * interval)) : at.addSecs(repetition * interval);
0650 }
0651 
0652 QDateTime Alarm::previousRepetition(const QDateTime &afterTime) const
0653 {
0654     QDateTime at = time();
0655     if (at >= afterTime) {
0656         // alarm's first/only time is at/after the specified time
0657         return QDateTime();
0658     }
0659     if (!d->mAlarmRepeatCount) {
0660         return at;
0661     }
0662     qint64 repetition;
0663     int interval = d->mAlarmSnoozeTime.value();
0664     bool daily = d->mAlarmSnoozeTime.isDaily();
0665     if (daily) {
0666         qint64 daysTo = at.daysTo(afterTime);
0667         if (afterTime.time() <= at.time()) {
0668             --daysTo;
0669         }
0670         repetition = daysTo / interval;
0671     } else {
0672         repetition = (at.secsTo(afterTime) - 1) / interval;
0673     }
0674     if (repetition > d->mAlarmRepeatCount) {
0675         repetition = d->mAlarmRepeatCount;
0676     }
0677     return daily ? at.addDays(int(repetition * interval)) : at.addSecs(repetition * interval);
0678 }
0679 
0680 QDateTime Alarm::endTime() const
0681 {
0682     if (!d->mAlarmRepeatCount) {
0683         return time();
0684     }
0685     if (d->mAlarmSnoozeTime.isDaily()) {
0686         return time().addDays(d->mAlarmRepeatCount * d->mAlarmSnoozeTime.asDays());
0687     } else {
0688         return time().addSecs(d->mAlarmRepeatCount * d->mAlarmSnoozeTime.asSeconds());
0689     }
0690 }
0691 
0692 void Alarm::toggleAlarm()
0693 {
0694     if (d->mParent) {
0695         d->mParent->update();
0696     }
0697     d->mAlarmEnabled = !d->mAlarmEnabled;
0698     if (d->mParent) {
0699         d->mParent->updated();
0700     }
0701 }
0702 
0703 void Alarm::setEnabled(bool enable)
0704 {
0705     if (d->mParent) {
0706         d->mParent->update();
0707     }
0708     d->mAlarmEnabled = enable;
0709     if (d->mParent) {
0710         d->mParent->updated();
0711     }
0712 }
0713 
0714 bool Alarm::enabled() const
0715 {
0716     return d->mAlarmEnabled;
0717 }
0718 
0719 void Alarm::setStartOffset(const Duration &offset)
0720 {
0721     if (d->mParent) {
0722         d->mParent->update();
0723     }
0724     d->mOffset = offset;
0725     d->mEndOffset = false;
0726     d->mHasTime = false;
0727     if (d->mParent) {
0728         d->mParent->updated();
0729     }
0730 }
0731 
0732 Duration Alarm::startOffset() const
0733 {
0734     return (d->mHasTime || d->mEndOffset) ? Duration(0) : d->mOffset;
0735 }
0736 
0737 bool Alarm::hasStartOffset() const
0738 {
0739     return !d->mHasTime && !d->mEndOffset;
0740 }
0741 
0742 bool Alarm::hasEndOffset() const
0743 {
0744     return !d->mHasTime && d->mEndOffset;
0745 }
0746 
0747 void Alarm::setEndOffset(const Duration &offset)
0748 {
0749     if (d->mParent) {
0750         d->mParent->update();
0751     }
0752     d->mOffset = offset;
0753     d->mEndOffset = true;
0754     d->mHasTime = false;
0755     if (d->mParent) {
0756         d->mParent->updated();
0757     }
0758 }
0759 
0760 Duration Alarm::endOffset() const
0761 {
0762     return (d->mHasTime || !d->mEndOffset) ? Duration(0) : d->mOffset;
0763 }
0764 
0765 void Alarm::setParent(Incidence *parent)
0766 {
0767     d->mParent = parent;
0768 }
0769 
0770 QString Alarm::parentUid() const
0771 {
0772     return d->mParent ? d->mParent->uid() : QString();
0773 }
0774 
0775 void Alarm::customPropertyUpdated()
0776 {
0777     if (d->mParent) {
0778         d->mParent->update();
0779         d->mParent->updated();
0780     }
0781 }
0782 
0783 void Alarm::setHasLocationRadius(bool hasLocationRadius)
0784 {
0785     if (d->mParent) {
0786         d->mParent->update();
0787     }
0788     d->mHasLocationRadius = hasLocationRadius;
0789     if (hasLocationRadius) {
0790         setNonKDECustomProperty("X-LOCATION-RADIUS", QString::number(d->mLocationRadius));
0791     } else {
0792         removeNonKDECustomProperty("X-LOCATION-RADIUS");
0793     }
0794     if (d->mParent) {
0795         d->mParent->updated();
0796     }
0797 }
0798 
0799 bool Alarm::hasLocationRadius() const
0800 {
0801     return d->mHasLocationRadius;
0802 }
0803 
0804 void Alarm::setLocationRadius(int locationRadius)
0805 {
0806     if (d->mParent) {
0807         d->mParent->update();
0808     }
0809     d->mLocationRadius = locationRadius;
0810     if (d->mParent) {
0811         d->mParent->updated();
0812     }
0813 }
0814 
0815 int Alarm::locationRadius() const
0816 {
0817     return d->mLocationRadius;
0818 }
0819 
0820 QDataStream &KCalendarCore::operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &a)
0821 {
0822     if (a) {
0823         out << ((quint32)a->d->mType) << a->d->mAlarmSnoozeTime << a->d->mAlarmRepeatCount << a->d->mEndOffset << a->d->mHasTime << a->d->mAlarmEnabled
0824             << a->d->mHasLocationRadius << a->d->mLocationRadius << a->d->mOffset;
0825 
0826         serializeQDateTimeAsKDateTime(out, a->d->mAlarmTime);
0827 
0828         out << a->d->mFile << a->d->mMailSubject << a->d->mDescription << a->d->mMailAttachFiles << a->d->mMailAddresses;
0829     }
0830     return out;
0831 }
0832 
0833 QDataStream &KCalendarCore::operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &a)
0834 {
0835     if (a) {
0836         quint32 type;
0837         in >> type;
0838         a->d->mType = static_cast<Alarm::Type>(type);
0839         in >> a->d->mAlarmSnoozeTime >> a->d->mAlarmRepeatCount >> a->d->mEndOffset >> a->d->mHasTime >> a->d->mAlarmEnabled >> a->d->mHasLocationRadius
0840             >> a->d->mLocationRadius >> a->d->mOffset;
0841         deserializeKDateTimeAsQDateTime(in, a->d->mAlarmTime);
0842         in >> a->d->mFile >> a->d->mMailSubject >> a->d->mDescription >> a->d->mMailAttachFiles >> a->d->mMailAddresses;
0843     }
0844     return in;
0845 }
0846 
0847 void Alarm::virtual_hook(int id, void *data)
0848 {
0849     Q_UNUSED(id);
0850     Q_UNUSED(data);
0851     Q_ASSERT(false);
0852 }