KCalendarCore

event.cpp
Go to the documentation of this file.
1/*
2 This file is part of the kcalcore library.
3
4 SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8/**
9 @file
10 This file is part of the API for handling calendar data and
11 defines the Event class.
12
13 @brief
14 This class provides an Event in the sense of RFC2445.
15
16 @author Cornelius Schumacher <schumacher@kde.org>
17*/
18
19#include "event.h"
20#include "incidence_p.h"
21#include "kcalendarcore_debug.h"
22#include "utils_p.h"
23#include "visitor.h"
24
25#include <QDate>
26
27using namespace KCalendarCore;
28
29/**
30 Private class that helps to provide binary compatibility between releases.
31 @internal
32*/
33//@cond PRIVATE
34class KCalendarCore::EventPrivate : public IncidencePrivate
35{
36public:
37 EventPrivate() = default;
38 explicit EventPrivate(const Incidence &);
39 bool validStatus(Incidence::Status) override;
40
41 QDateTime mDtEnd;
42 Event::Transparency mTransparency = Event::Opaque;
43 bool mMultiDayValid = false;
44 bool mMultiDay = false;
45};
46
47// Copy IncidencePrivate and IncidenceBasePrivate members,
48// but default-initialize EventPrivate members.
49EventPrivate::EventPrivate(const Incidence &other)
50 : IncidencePrivate(other)
51{
52}
53
54bool EventPrivate::validStatus(Incidence::Status status)
55{
56 constexpr unsigned validSet
61 return validSet & (1u << status);
62}
63//@endcond
64
66 : Incidence(new EventPrivate)
67{
68}
69
70Event::Event(const Event &other)
71 : Incidence(other, new EventPrivate(*(other.d_func())))
72{
73}
74
76 : Incidence(other, new EventPrivate(other))
77{
78}
79
80Event::~Event() = default;
81
83{
84 return new Event(*this);
85}
86
88{
89 Q_D(Event);
90 if (&other != this) {
91 Incidence::assign(other);
92 const auto o = static_cast<const Event *>(&other)->d_func();
93 d->mDtEnd = o->mDtEnd;
94 d->mTransparency = o->mTransparency;
95 d->mMultiDayValid = o->mMultiDayValid;
96 d->mMultiDay = o->mMultiDay;
97 }
98 return *this;
99}
100
101bool Event::equals(const IncidenceBase &event) const
102{
103 if (!Incidence::equals(event)) {
104 return false;
105 } else {
106 // If they weren't the same type IncidenceBase::equals would had returned false already
107 const Event *e = static_cast<const Event *>(&event);
108 return identical(dtEnd(), e->dtEnd()) && transparency() == e->transparency();
109 }
110}
111
113{
114 return TypeEvent;
115}
116
118{
119 return QByteArrayLiteral("Event");
120}
121
123{
124 Q_D(Event);
125 d->mMultiDayValid = false;
127}
128
129void Event::setDtEnd(const QDateTime &dtEnd)
130{
131 if (mReadOnly) {
132 return;
133 }
134
135 Q_D(Event);
136 if (!identical(d->mDtEnd, dtEnd) || hasDuration() == dtEnd.isValid()) {
137 update();
138 d->mDtEnd = dtEnd;
139 d->mMultiDayValid = false;
140 setHasDuration(!dtEnd.isValid());
142 updated();
143 }
144}
145
146QDateTime Event::dtEnd() const
147{
148 Q_D(const Event);
149 if (d->mDtEnd.isValid()) {
150 return d->mDtEnd;
151 }
152
153 if (hasDuration()) {
154 if (allDay()) {
155 // For all day events, dtEnd is always inclusive
156 QDateTime end = duration().end(dtStart().addDays(-1));
157 return end >= dtStart() ? end : dtStart();
158 } else {
159 return duration().end(dtStart());
160 }
161 }
162
163 // It is valid for a VEVENT to be without a DTEND. See RFC2445, Sect4.6.1.
164 // Be careful to use Event::dateEnd() as appropriate due to this possibility.
165 return dtStart();
166}
167
169{
170 QDateTime end = dtEnd().toTimeZone(dtStart().timeZone());
171 if (allDay()) {
172 return end.date();
173 } else {
174 return end.addSecs(-1).date();
175 }
176}
177
179{
180 Q_D(const Event);
181 return d->mDtEnd.isValid();
182}
183
184bool Event::isMultiDay(const QTimeZone &zone) const
185{
186 Q_D(const Event);
187 // First off, if spec's not valid, we can check for cache
188 if (!zone.isValid() && d->mMultiDayValid) {
189 return d->mMultiDay;
190 }
191
192 // Not in cache -> do it the hard way
194 QDateTime end;
195
196 if (!zone.isValid()) {
197 start = dtStart();
198 end = dtEnd();
199 } else {
200 start = dtStart().toTimeZone(zone);
201 end = dtEnd().toTimeZone(zone);
202 }
203
204 bool multi = (start < end && start.date() != end.date());
205
206 // End date is non inclusive
207 // If we have an incidence that duration is one day and ends with a start of a new day
208 // than it is not a multiday event
209 if (multi && end.time() == QTime(0, 0, 0)) {
210 multi = start.daysTo(end) > 1;
211 }
212
213 // Update the cache
214 // Also update Cache if spec is invalid
215 {
216 auto d = static_cast<EventPrivate *>(d_ptr);
217 d->mMultiDayValid = true;
218 d->mMultiDay = multi;
219 }
220 return multi;
221}
222
223void Event::shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
224{
225 Q_D(Event);
226 Incidence::shiftTimes(oldZone, newZone);
227 if (d->mDtEnd.isValid()) {
228 update();
229 d->mDtEnd = d->mDtEnd.toTimeZone(oldZone);
230 d->mDtEnd.setTimeZone(newZone);
232 updated();
233 }
234}
235
237{
238 if (mReadOnly) {
239 return;
240 }
241 update();
242 Q_D(Event);
243 d->mTransparency = transparency;
245 updated();
246}
247
248Event::Transparency Event::transparency() const
249{
250 Q_D(const Event);
251 return d->mTransparency;
252}
253
254void Event::setDuration(const Duration &duration)
255{
256 // These both call update()/updated() and setFieldDirty().
259}
260
261void Event::setAllDay(bool allday)
262{
263 if (allday != allDay() && !mReadOnly) {
264 update();
266 Incidence::setAllDay(allday);
267 updated();
268 }
269}
270
271bool Event::accept(Visitor &v, const IncidenceBase::Ptr &incidence)
272{
273 return v.visit(incidence.staticCast<Event>());
274}
275
277{
278 switch (role) {
282 case RoleSort:
283 return dtStart();
285 return !recurs() && !isMultiDay() ? dtStart() : QDateTime();
287 case RoleEndTimeZone:
288 case RoleEndRecurrenceBase:
289 case RoleEnd:
290 case RoleDisplayEnd:
291 return dtEnd();
292 case RoleDisplayStart:
293 return dtStart();
294 case RoleAlarm:
295 if (alarms().isEmpty()) {
296 return QDateTime();
297 } else {
298 Alarm::Ptr alarm = alarms().at(0);
299 return alarm->hasStartOffset() ? dtStart() : dtEnd();
300 }
301 default:
302 return QDateTime();
303 }
304}
305
306void Event::setDateTime(const QDateTime &dateTime, DateTimeRole role)
307{
308 switch (role) {
309 case RoleDnD: {
310 const qint64 duration = dtStart().secsTo(dtEnd());
311
313 setDtEnd(dateTime.addSecs(duration <= 0 ? 3600 : duration));
314 break;
315 }
316 case RoleEnd:
318 break;
319 default:
320 qCDebug(KCALCORE_LOG) << "Unhandled role" << role;
321 }
322}
323
324void Event::virtual_hook(VirtualHook id, void *data)
325{
326 Q_UNUSED(id);
327 Q_UNUSED(data);
328}
329
334
336{
337 return QLatin1String("application/x-vnd.akonadi.calendar.event");
338}
339
341{
342 return QLatin1String("view-calendar-day");
343}
344
345void Event::serialize(QDataStream &out) const
346{
347 Q_D(const Event);
349 serializeQDateTimeAsKDateTime(out, d->mDtEnd);
350 out << hasEndDate() << static_cast<quint32>(d->mTransparency) << d->mMultiDayValid << d->mMultiDay;
351}
352
353void Event::deserialize(QDataStream &in)
354{
355 Q_D(Event);
357 bool hasEndDateDummy = true;
358 deserializeKDateTimeAsQDateTime(in, d->mDtEnd);
359 in >> hasEndDateDummy;
360 quint32 transp;
361 in >> transp;
362 d->mTransparency = static_cast<Transparency>(transp);
363 in >> d->mMultiDayValid >> d->mMultiDay;
364}
365
367{
368 return true;
369}
370
371#include "moc_event.cpp"
Represents a span of time measured in seconds or days.
Definition duration.h:44
QDateTime end(const QDateTime &start) const
Computes a duration end time by adding the number of seconds or days in the duration to the specified...
Definition duration.cpp:171
This class provides an Event in the sense of RFC2445.
Definition event.h:33
Transparency
The different Event transparency types.
Definition event.h:41
@ Opaque
Event appears in free/busy time.
Definition event.h:42
QLatin1String iconName(const QDateTime &recurrenceId={}) const override
Definition event.cpp:340
void setDtEnd(const QDateTime &dtEnd)
Sets the event end date and time.
Definition event.cpp:129
void virtual_hook(VirtualHook id, void *data) override
Definition event.cpp:324
QByteArray typeStr() const override
Definition event.cpp:117
QLatin1String mimeType() const override
Definition event.cpp:330
void setAllDay(bool allDay) override
Definition event.cpp:261
void setTransparency(Transparency transparency)
Sets the event's time transparency level.
Definition event.cpp:236
Event()
Constructs an event.
Definition event.cpp:65
bool isMultiDay(const QTimeZone &zone={}) const
Returns true if the event spans multiple days, otherwise return false.
Definition event.cpp:184
void setDuration(const Duration &duration) override
Sets the duration of this event.
Definition event.cpp:254
bool supportsGroupwareCommunication() const override
Definition event.cpp:366
QDate dateEnd() const
Returns the date when the event ends.
Definition event.cpp:168
Event * clone() const override
Returns an exact copy of this Event.
Definition event.cpp:82
QDateTime dateTime(DateTimeRole role) const override
Definition event.cpp:276
IncidenceBase & assign(const IncidenceBase &other) override
Definition event.cpp:87
IncidenceType type() const override
Definition event.cpp:112
void setDateTime(const QDateTime &dateTime, DateTimeRole role) override
Definition event.cpp:306
static QLatin1String eventMimeType()
Returns the Akonadi specific sub MIME type of a KCalendarCore::Event.
Definition event.cpp:335
bool hasEndDate() const
Returns whether the event has an end date/time.
Definition event.cpp:178
void setDtStart(const QDateTime &dt) override
Sets the incidence starting date/time.
Definition event.cpp:122
void shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone) override
Definition event.cpp:223
bool equals(const IncidenceBase &event) const override
Compares two events for equality.
Definition event.cpp:101
~Event() override
Destroys the event.
An abstract class that provides a common base for all calendar incidence classes.
void updated()
Call this to notify the observers after the IncidenceBase object has changed.
bool mReadOnly
Identifies a read-only incidence.
IncidenceType
The different types of incidences, per RFC2445.
@ TypeEvent
Type is an event.
Duration duration() const
Returns the length of the incidence duration.
void update()
Call this to notify the observers after the IncidenceBase object will be changed.
virtual void setDuration(const Duration &duration)
Sets the incidence duration.
@ FieldDtEnd
Field representing the DTEND component.
@ FieldTransparency
Field representing the TRANSPARENCY component.
void setHasDuration(bool hasDuration)
Sets if the incidence has a duration.
void setFieldDirty(IncidenceBase::Field field)
Marks Field field as dirty.
DateTimeRole
The different types of incidence date/times roles.
@ RoleAlarmStartOffset
Role for an incidence alarm's starting offset date/time.
@ RoleEndTimeZone
Role for determining an incidence's ending timezone.
@ RoleCalendarHashing
Role for looking up an incidence in a Calendar.
@ RoleDisplayEnd
Role used for display purposes, represents the end boundary if an incidence supports dtEnd.
@ RoleAlarmEndOffset
Role for an incidence alarm's ending offset date/time.
@ RoleSort
Role for an incidence's date/time used when sorting.
@ RoleStartTimeZone
Role for determining an incidence's starting timezone.
@ RoleEnd
Role for determining an incidence's dtEnd, will return an invalid QDateTime if the incidence does not...
@ RoleDnD
Role for determining new start and end dates after a DnD.
@ RoleRecurrenceStart
Role for determining the start of the recurrence.
@ RoleAlarm
Role for determining the date/time of the first alarm.
@ RoleDisplayStart
Role for display purposes, represents the start boundary of an incidence.
bool hasDuration() const
Returns true if the incidence has a duration; false otherwise.
Provides the abstract base class common to non-FreeBusy (Events, To-dos, Journals) calendar component...
Definition incidence.h:60
Status
The different types of overall incidence status or confirmation.
Definition incidence.h:80
@ StatusCanceled
event or to-do canceled; journal removed
Definition incidence.h:86
@ StatusTentative
event is tentative
Definition incidence.h:82
@ StatusConfirmed
event is definite
Definition incidence.h:83
Alarm::List alarms() const
Returns a list of all incidence alarms.
bool recurs() const
Returns whether the event recurs at all.
void setAllDay(bool allDay) override
Sets whether the incidence is all-day, i.e.
void serialize(QDataStream &out) const override
Sub-type specific serialization.
void shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone) override
Shift the times of the incidence so that they appear at the same clock time as before but in a new ti...
IncidenceBase & assign(const IncidenceBase &other) override
Provides polymorfic assignment.
bool equals(const IncidenceBase &incidence) const override
Compares this with Incidence incidence for equality.
void setDtStart(const QDateTime &dt) override
Sets the incidence starting date/time.
void deserialize(QDataStream &in) override
Sub-type specific deserialization.
This class provides the interface for a visitor of calendar components.
Definition visitor.h:31
virtual bool visit(const Event::Ptr &event)
Reimplement this function in your concrete subclass of IncidenceBase::Visitor to perform actions on a...
Definition visitor.cpp:25
This file is part of the API for handling calendar data and defines the Event class.
Q_SCRIPTABLE Q_NOREPLY void start()
Q_SCRIPTABLE CaptureState status()
Namespace for all KCalendarCore types.
Definition alarm.h:37
KCALENDARCORE_EXPORT bool identical(const QDateTime &dt1, const QDateTime &dt2)
Compare two QDateTimes for extended equality.
QDateTime addSecs(qint64 s) const const
bool isValid() const const
qint64 secsTo(const QDateTime &other) const const
QDateTime toTimeZone(const QTimeZone &timeZone) const const
const T & at(int i) const const
QSharedPointer< X > staticCast() const const
bool isValid() const const
Q_D(Todo)
Private class that helps to provide binary compatibility between releases.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:39:07 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.