mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 02:42:51 +00:00
881 lines
22 KiB
C++
881 lines
22 KiB
C++
/*
|
|
This file is part of the kcalcore library.
|
|
|
|
Copyright (c) 1998 Preston Brown <pbrown@kde.org>
|
|
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
|
|
Copyright (c) 2003 David Jarvie <software@astrojar.org.uk>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
/**
|
|
@file
|
|
This file is part of the API for handling calendar data and
|
|
defines the Alarm class.
|
|
|
|
@brief
|
|
Represents an alarm notification.
|
|
|
|
@author Cornelius Schumacher \<schumacher@kde.org\>
|
|
*/
|
|
#include "alarm.h"
|
|
#include "duration.h"
|
|
#include "incidence.h"
|
|
|
|
#include <QTime>
|
|
|
|
using namespace KCalCore;
|
|
|
|
/**
|
|
Private class that helps to provide binary compatibility between releases.
|
|
@internal
|
|
*/
|
|
//@cond PRIVATE
|
|
class KCalCore::Alarm::Private
|
|
{
|
|
public:
|
|
Private()
|
|
: mParent(0),
|
|
mType(Alarm::Invalid),
|
|
mAlarmSnoozeTime(5),
|
|
mAlarmRepeatCount(0),
|
|
mEndOffset(false),
|
|
mHasTime(false),
|
|
mAlarmEnabled(false),
|
|
mHasLocationRadius(false),
|
|
mLocationRadius(0)
|
|
{}
|
|
Private(const Private &other)
|
|
: mParent(other.mParent),
|
|
mType(other.mType),
|
|
mDescription(other.mDescription),
|
|
mFile(other.mFile),
|
|
mMailSubject(other.mMailSubject),
|
|
mMailAttachFiles(other.mMailAttachFiles),
|
|
mMailAddresses(other.mMailAddresses),
|
|
mAlarmTime(other.mAlarmTime),
|
|
mAlarmSnoozeTime(other.mAlarmSnoozeTime),
|
|
mAlarmRepeatCount(other.mAlarmRepeatCount),
|
|
mOffset(other.mOffset),
|
|
mEndOffset(other.mEndOffset),
|
|
mHasTime(other.mHasTime),
|
|
mAlarmEnabled(other.mAlarmEnabled),
|
|
mHasLocationRadius(other.mHasLocationRadius),
|
|
mLocationRadius(other.mLocationRadius)
|
|
{}
|
|
|
|
Incidence *mParent; // the incidence which this alarm belongs to
|
|
|
|
Type mType; // type of alarm
|
|
QString mDescription;// text to display/email body/procedure arguments
|
|
QString mFile; // program to run/optional audio file to play
|
|
QString mMailSubject;// subject of email
|
|
QStringList mMailAttachFiles; // filenames to attach to email
|
|
Person::List mMailAddresses; // who to mail for reminder
|
|
|
|
KDateTime mAlarmTime;// time at which to trigger the alarm
|
|
Duration mAlarmSnoozeTime; // how long after alarm to snooze before
|
|
// triggering again
|
|
int mAlarmRepeatCount;// number of times for alarm to repeat
|
|
// after the initial time
|
|
|
|
Duration mOffset; // time relative to incidence DTSTART
|
|
// to trigger the alarm
|
|
bool mEndOffset; // if true, mOffset relates to DTEND, not DTSTART
|
|
bool mHasTime; // use mAlarmTime, not mOffset
|
|
bool mAlarmEnabled;
|
|
|
|
bool mHasLocationRadius;
|
|
int mLocationRadius; // location radius for the alarm
|
|
};
|
|
//@endcond
|
|
|
|
Alarm::Alarm(Incidence *parent) : d(new KCalCore::Alarm::Private)
|
|
{
|
|
d->mParent = parent;
|
|
}
|
|
|
|
Alarm::Alarm(const Alarm &other) :
|
|
CustomProperties(other), d(new KCalCore::Alarm::Private(*other.d))
|
|
{
|
|
}
|
|
|
|
Alarm::~Alarm()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
Alarm &Alarm::operator=(const Alarm &a)
|
|
{
|
|
if (&a != this) {
|
|
d->mParent = a.d->mParent;
|
|
d->mType = a.d->mType;
|
|
d->mDescription = a.d->mDescription;
|
|
d->mFile = a.d->mFile;
|
|
d->mMailAttachFiles = a.d->mMailAttachFiles;
|
|
d->mMailAddresses = a.d->mMailAddresses;
|
|
d->mMailSubject = a.d->mMailSubject;
|
|
d->mAlarmSnoozeTime = a.d->mAlarmSnoozeTime;
|
|
d->mAlarmRepeatCount = a.d->mAlarmRepeatCount;
|
|
d->mAlarmTime = a.d->mAlarmTime;
|
|
d->mOffset = a.d->mOffset;
|
|
d->mEndOffset = a.d->mEndOffset;
|
|
d->mHasTime = a.d->mHasTime;
|
|
d->mAlarmEnabled = a.d->mAlarmEnabled;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
static bool compareMailAddresses(const Person::List &list1, const Person::List &list2)
|
|
{
|
|
if (list1.count() == list2.count()) {
|
|
for (int i=0; i<list1.count(); ++i) {
|
|
if (*list1.at(i) != *list2.at(i)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Alarm::operator==(const Alarm &rhs) const
|
|
{
|
|
if (d->mType != rhs.d->mType ||
|
|
d->mAlarmSnoozeTime != rhs.d->mAlarmSnoozeTime ||
|
|
d->mAlarmRepeatCount != rhs.d->mAlarmRepeatCount ||
|
|
d->mAlarmEnabled != rhs.d->mAlarmEnabled ||
|
|
d->mHasTime != rhs.d->mHasTime ||
|
|
d->mHasLocationRadius != rhs.d->mHasLocationRadius ||
|
|
d->mLocationRadius != rhs.d->mLocationRadius) {
|
|
return false;
|
|
}
|
|
|
|
if (d->mHasTime) {
|
|
if (d->mAlarmTime != rhs.d->mAlarmTime) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (d->mOffset != rhs.d->mOffset || d->mEndOffset != rhs.d->mEndOffset) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
switch (d->mType) {
|
|
case Display:
|
|
return d->mDescription == rhs.d->mDescription;
|
|
|
|
case Email:
|
|
return d->mDescription == rhs.d->mDescription &&
|
|
d->mMailAttachFiles == rhs.d->mMailAttachFiles &&
|
|
compareMailAddresses(d->mMailAddresses, rhs.d->mMailAddresses) &&
|
|
d->mMailSubject == rhs.d->mMailSubject;
|
|
|
|
case Procedure:
|
|
return d->mFile == rhs.d->mFile &&
|
|
d->mDescription == rhs.d->mDescription;
|
|
|
|
case Audio:
|
|
return d->mFile == rhs.d->mFile;
|
|
|
|
case Invalid:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Alarm::operator!=(const Alarm &a) const
|
|
{
|
|
return !operator==(a);
|
|
}
|
|
|
|
void Alarm::setType(Alarm::Type type)
|
|
{
|
|
if (type == d->mType) {
|
|
return;
|
|
}
|
|
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
switch (type) {
|
|
case Display:
|
|
d->mDescription = QLatin1String("");
|
|
break;
|
|
case Procedure:
|
|
d->mFile = d->mDescription = QLatin1String("");
|
|
break;
|
|
case Audio:
|
|
d->mFile = QLatin1String("");
|
|
break;
|
|
case Email:
|
|
d->mMailSubject = d->mDescription = QLatin1String("");
|
|
d->mMailAddresses.clear();
|
|
d->mMailAttachFiles.clear();
|
|
break;
|
|
case Invalid:
|
|
break;
|
|
default:
|
|
if (d->mParent) {
|
|
d->mParent->updated(); // not really
|
|
}
|
|
return;
|
|
}
|
|
d->mType = type;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
Alarm::Type Alarm::type() const
|
|
{
|
|
return d->mType;
|
|
}
|
|
|
|
void Alarm::setAudioAlarm(const QString &audioFile)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mType = Audio;
|
|
d->mFile = audioFile;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setAudioFile(const QString &audioFile)
|
|
{
|
|
if (d->mType == Audio) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mFile = audioFile;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QString Alarm::audioFile() const
|
|
{
|
|
return (d->mType == Audio) ? d->mFile : QString();
|
|
}
|
|
|
|
void Alarm::setProcedureAlarm(const QString &programFile,
|
|
const QString &arguments)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mType = Procedure;
|
|
d->mFile = programFile;
|
|
d->mDescription = arguments;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setProgramFile(const QString &programFile)
|
|
{
|
|
if (d->mType == Procedure) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mFile = programFile;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QString Alarm::programFile() const
|
|
{
|
|
return (d->mType == Procedure) ? d->mFile : QString();
|
|
}
|
|
|
|
void Alarm::setProgramArguments(const QString &arguments)
|
|
{
|
|
if (d->mType == Procedure) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mDescription = arguments;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QString Alarm::programArguments() const
|
|
{
|
|
return (d->mType == Procedure) ? d->mDescription : QString();
|
|
}
|
|
|
|
void Alarm::setEmailAlarm(const QString &subject, const QString &text,
|
|
const Person::List &addressees,
|
|
const QStringList &attachments)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mType = Email;
|
|
d->mMailSubject = subject;
|
|
d->mDescription = text;
|
|
d->mMailAddresses = addressees;
|
|
d->mMailAttachFiles = attachments;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setMailAddress(const Person::Ptr &mailAddress)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailAddresses.clear();
|
|
d->mMailAddresses.append(mailAddress);
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Alarm::setMailAddresses(const Person::List &mailAddresses)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailAddresses += mailAddresses;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Alarm::addMailAddress(const Person::Ptr &mailAddress)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailAddresses.append(mailAddress);
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
Person::List Alarm::mailAddresses() const
|
|
{
|
|
return (d->mType == Email) ? d->mMailAddresses : Person::List();
|
|
}
|
|
|
|
void Alarm::setMailSubject(const QString &mailAlarmSubject)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailSubject = mailAlarmSubject;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QString Alarm::mailSubject() const
|
|
{
|
|
return (d->mType == Email) ? d->mMailSubject : QString();
|
|
}
|
|
|
|
void Alarm::setMailAttachment(const QString &mailAttachFile)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailAttachFiles.clear();
|
|
d->mMailAttachFiles += mailAttachFile;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Alarm::setMailAttachments(const QStringList &mailAttachFiles)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailAttachFiles = mailAttachFiles;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Alarm::addMailAttachment(const QString &mailAttachFile)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mMailAttachFiles += mailAttachFile;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QStringList Alarm::mailAttachments() const
|
|
{
|
|
return (d->mType == Email) ? d->mMailAttachFiles : QStringList();
|
|
}
|
|
|
|
void Alarm::setMailText(const QString &text)
|
|
{
|
|
if (d->mType == Email) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mDescription = text;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QString Alarm::mailText() const
|
|
{
|
|
return (d->mType == Email) ? d->mDescription : QString();
|
|
}
|
|
|
|
void Alarm::setDisplayAlarm(const QString &text)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mType = Display;
|
|
if (!text.isNull()) {
|
|
d->mDescription = text;
|
|
}
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setText(const QString &text)
|
|
{
|
|
if (d->mType == Display) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mDescription = text;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
QString Alarm::text() const
|
|
{
|
|
return (d->mType == Display) ? d->mDescription : QString();
|
|
}
|
|
|
|
void Alarm::setTime(const KDateTime &alarmTime)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mAlarmTime = alarmTime;
|
|
d->mHasTime = true;
|
|
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
KDateTime Alarm::time() const
|
|
{
|
|
if (hasTime()) {
|
|
return d->mAlarmTime;
|
|
} else if (d->mParent) {
|
|
if (d->mEndOffset) {
|
|
KDateTime dt = d->mParent->dateTime(Incidence::RoleAlarmEndOffset);
|
|
return d->mOffset.end(dt);
|
|
} else {
|
|
KDateTime dt = d->mParent->dateTime(Incidence::RoleAlarmStartOffset);
|
|
return d->mOffset.end(dt);
|
|
}
|
|
} else {
|
|
return KDateTime();
|
|
}
|
|
}
|
|
|
|
KDateTime Alarm::nextTime(const KDateTime &preTime, bool ignoreRepetitions) const
|
|
{
|
|
if (d->mParent && d->mParent->recurs()) {
|
|
KDateTime dtEnd = d->mParent->dateTime(Incidence::RoleAlarmEndOffset);
|
|
|
|
KDateTime dtStart = d->mParent->dtStart();
|
|
// Find the incidence's earliest alarm
|
|
// Alarm time is defined by an offset from the event start or end time.
|
|
KDateTime alarmStart = d->mOffset.end(d->mEndOffset ? dtEnd : dtStart);
|
|
// Find the offset from the event start time, which is also used as the
|
|
// offset from the recurrence time.
|
|
Duration alarmOffset(dtStart, alarmStart);
|
|
/*
|
|
kDebug() << "dtStart " << dtStart;
|
|
kDebug() << "dtEnd " << dtEnd;
|
|
kDebug() << "alarmStart " << alarmStart;
|
|
kDebug() << "alarmOffset " << alarmOffset.value();
|
|
kDebug() << "preTime " << preTime;
|
|
*/
|
|
if (alarmStart > preTime) {
|
|
// No need to go further.
|
|
return alarmStart;
|
|
}
|
|
if (d->mAlarmRepeatCount && !ignoreRepetitions) {
|
|
// The alarm has repetitions, so check whether repetitions of previous
|
|
// recurrences happen after given time.
|
|
KDateTime prevRecurrence = d->mParent->recurrence()->getPreviousDateTime(preTime);
|
|
if (prevRecurrence.isValid()) {
|
|
KDateTime prevLastRepeat = alarmOffset.end(duration().end(prevRecurrence));
|
|
// kDebug() << "prevRecurrence" << prevRecurrence;
|
|
// kDebug() << "prevLastRepeat" << prevLastRepeat;
|
|
if (prevLastRepeat > preTime) {
|
|
// Yes they did, return alarm offset to previous recurrence.
|
|
KDateTime prevAlarm = alarmOffset.end(prevRecurrence);
|
|
// kDebug() << "prevAlarm " << prevAlarm;
|
|
return prevAlarm;
|
|
}
|
|
}
|
|
}
|
|
// Check the next recurrence now.
|
|
KDateTime nextRecurrence = d->mParent->recurrence()->getNextDateTime(preTime);
|
|
if (nextRecurrence.isValid()) {
|
|
KDateTime nextAlarm = alarmOffset.end(nextRecurrence);
|
|
/*
|
|
kDebug() << "nextRecurrence" << nextRecurrence;
|
|
kDebug() << "nextAlarm " << nextAlarm;
|
|
*/
|
|
if (nextAlarm > preTime) {
|
|
// It's first alarm takes place after given time.
|
|
return nextAlarm;
|
|
}
|
|
}
|
|
} else {
|
|
// Not recurring.
|
|
KDateTime alarmTime = time();
|
|
if (alarmTime > preTime) {
|
|
return alarmTime;
|
|
}
|
|
}
|
|
return KDateTime();
|
|
}
|
|
|
|
bool Alarm::hasTime() const
|
|
{
|
|
return d->mHasTime;
|
|
}
|
|
|
|
void Alarm::shiftTimes(const KDateTime::Spec &oldSpec,
|
|
const KDateTime::Spec &newSpec)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mAlarmTime = d->mAlarmTime.toTimeSpec(oldSpec);
|
|
d->mAlarmTime.setTimeSpec(newSpec);
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setSnoozeTime(const Duration &alarmSnoozeTime)
|
|
{
|
|
if (alarmSnoozeTime.value() > 0) {
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mAlarmSnoozeTime = alarmSnoozeTime;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
}
|
|
|
|
Duration Alarm::snoozeTime() const
|
|
{
|
|
return d->mAlarmSnoozeTime;
|
|
}
|
|
|
|
void Alarm::setRepeatCount(int alarmRepeatCount)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mAlarmRepeatCount = alarmRepeatCount;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
int Alarm::repeatCount() const
|
|
{
|
|
return d->mAlarmRepeatCount;
|
|
}
|
|
|
|
Duration Alarm::duration() const
|
|
{
|
|
return Duration(d->mAlarmSnoozeTime.value() * d->mAlarmRepeatCount,
|
|
d->mAlarmSnoozeTime.type());
|
|
}
|
|
|
|
KDateTime Alarm::nextRepetition(const KDateTime &preTime) const
|
|
{
|
|
KDateTime at = nextTime(preTime);
|
|
if (at > preTime) {
|
|
return at;
|
|
}
|
|
if (!d->mAlarmRepeatCount) {
|
|
// there isn't an occurrence after the specified time
|
|
return KDateTime();
|
|
}
|
|
qint64 repetition;
|
|
int interval = d->mAlarmSnoozeTime.value();
|
|
bool daily = d->mAlarmSnoozeTime.isDaily();
|
|
if (daily) {
|
|
int daysTo = at.daysTo(preTime);
|
|
if (!preTime.isDateOnly() && preTime.time() <= at.time()) {
|
|
--daysTo;
|
|
}
|
|
repetition = daysTo / interval + 1;
|
|
} else {
|
|
repetition = at.secsTo_long(preTime) / interval + 1;
|
|
}
|
|
if (repetition > d->mAlarmRepeatCount) {
|
|
// all repetitions have finished before the specified time
|
|
return KDateTime();
|
|
}
|
|
return daily ? at.addDays(int(repetition * interval))
|
|
: at.addSecs(repetition * interval);
|
|
}
|
|
|
|
KDateTime Alarm::previousRepetition(const KDateTime &afterTime) const
|
|
{
|
|
KDateTime at = time();
|
|
if (at >= afterTime) {
|
|
// alarm's first/only time is at/after the specified time
|
|
return KDateTime();
|
|
}
|
|
if (!d->mAlarmRepeatCount) {
|
|
return at;
|
|
}
|
|
qint64 repetition;
|
|
int interval = d->mAlarmSnoozeTime.value();
|
|
bool daily = d->mAlarmSnoozeTime.isDaily();
|
|
if (daily) {
|
|
int daysTo = at.daysTo(afterTime);
|
|
if (afterTime.isDateOnly() || afterTime.time() <= at.time()) {
|
|
--daysTo;
|
|
}
|
|
repetition = daysTo / interval;
|
|
} else {
|
|
repetition = (at.secsTo_long(afterTime) - 1) / interval;
|
|
}
|
|
if (repetition > d->mAlarmRepeatCount) {
|
|
repetition = d->mAlarmRepeatCount;
|
|
}
|
|
return daily ? at.addDays(int(repetition * interval))
|
|
: at.addSecs(repetition * interval);
|
|
}
|
|
|
|
KDateTime Alarm::endTime() const
|
|
{
|
|
if (!d->mAlarmRepeatCount) {
|
|
return time();
|
|
}
|
|
if (d->mAlarmSnoozeTime.isDaily()) {
|
|
return time().addDays(d->mAlarmRepeatCount * d->mAlarmSnoozeTime.asDays());
|
|
} else {
|
|
return time().addSecs(d->mAlarmRepeatCount * d->mAlarmSnoozeTime.asSeconds());
|
|
}
|
|
}
|
|
|
|
void Alarm::toggleAlarm()
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mAlarmEnabled = !d->mAlarmEnabled;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setEnabled(bool enable)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mAlarmEnabled = enable;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
bool Alarm::enabled() const
|
|
{
|
|
return d->mAlarmEnabled;
|
|
}
|
|
|
|
void Alarm::setStartOffset(const Duration &offset)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mOffset = offset;
|
|
d->mEndOffset = false;
|
|
d->mHasTime = false;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
Duration Alarm::startOffset() const
|
|
{
|
|
return (d->mHasTime || d->mEndOffset) ? Duration(0) : d->mOffset;
|
|
}
|
|
|
|
bool Alarm::hasStartOffset() const
|
|
{
|
|
return !d->mHasTime && !d->mEndOffset;
|
|
}
|
|
|
|
bool Alarm::hasEndOffset() const
|
|
{
|
|
return !d->mHasTime && d->mEndOffset;
|
|
}
|
|
|
|
void Alarm::setEndOffset(const Duration &offset)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mOffset = offset;
|
|
d->mEndOffset = true;
|
|
d->mHasTime = false;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
Duration Alarm::endOffset() const
|
|
{
|
|
return (d->mHasTime || !d->mEndOffset) ? Duration(0) : d->mOffset;
|
|
}
|
|
|
|
void Alarm::setParent(Incidence *parent)
|
|
{
|
|
d->mParent = parent;
|
|
}
|
|
|
|
QString Alarm::parentUid() const
|
|
{
|
|
return d->mParent ? d->mParent->uid() : QString();
|
|
}
|
|
|
|
void Alarm::customPropertyUpdated()
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
void Alarm::setHasLocationRadius(bool hasLocationRadius)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mHasLocationRadius = hasLocationRadius;
|
|
if (hasLocationRadius) {
|
|
setNonKDECustomProperty("X-LOCATION-RADIUS", QString::number(d->mLocationRadius));
|
|
} else {
|
|
removeNonKDECustomProperty("X-LOCATION-RADIUS");
|
|
}
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
bool Alarm::hasLocationRadius() const
|
|
{
|
|
return d->mHasLocationRadius;
|
|
}
|
|
|
|
void Alarm::setLocationRadius(int locationRadius)
|
|
{
|
|
if (d->mParent) {
|
|
d->mParent->update();
|
|
}
|
|
d->mLocationRadius = locationRadius;
|
|
if (d->mParent) {
|
|
d->mParent->updated();
|
|
}
|
|
}
|
|
|
|
int Alarm::locationRadius() const
|
|
{
|
|
return d->mLocationRadius;
|
|
}
|
|
|
|
QDataStream& KCalCore::operator<<(QDataStream &out, const KCalCore::Alarm::Ptr &a)
|
|
{
|
|
if (a) {
|
|
out << ((quint32)a->d->mType) << a->d->mAlarmSnoozeTime << a->d->mAlarmRepeatCount << a->d->mEndOffset << a->d->mHasTime
|
|
<< a->d->mAlarmEnabled << a->d->mHasLocationRadius << a->d->mLocationRadius << a->d->mOffset << a->d->mAlarmTime
|
|
<< a->d->mFile << a->d->mMailSubject << a->d->mDescription << a->d->mMailAttachFiles << a->d->mMailAddresses;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
QDataStream& KCalCore::operator>>(QDataStream &in, const KCalCore::Alarm::Ptr &a)
|
|
{
|
|
if (a) {
|
|
quint32 type;
|
|
in >> type;
|
|
a->d->mType = static_cast<Alarm::Type>(type);
|
|
in >> a->d->mAlarmSnoozeTime >> a->d->mAlarmRepeatCount >> a->d->mEndOffset >> a->d->mHasTime
|
|
>> a->d->mAlarmEnabled >> a->d->mHasLocationRadius >> a->d->mLocationRadius >> a->d->mOffset >> a->d->mAlarmTime
|
|
>> a->d->mFile >> a->d->mMailSubject >> a->d->mDescription >> a->d->mMailAttachFiles >> a->d->mMailAddresses;
|
|
}
|
|
return in;
|
|
}
|
|
|
|
void Alarm::virtual_hook(int id, void *data)
|
|
{
|
|
Q_UNUSED(id);
|
|
Q_UNUSED(data);
|
|
Q_ASSERT(false);
|
|
}
|