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
75Event::Event(const Incidence &other)
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
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
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"
QSharedPointer< Alarm > Ptr
A shared pointer to an Alarm object.
Definition alarm.h:67
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.
QSharedPointer< IncidenceBase > Ptr
A shared pointer to an IncidenceBase.
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 QString start(QString train="")
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.
const_reference at(qsizetype 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-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:53:53 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.