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 <[email protected]>
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 <[email protected]>
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 
27 using namespace KCalendarCore;
28 
29 /**
30  Private class that helps to provide binary compatibility between releases.
31  @internal
32 */
33 //@cond PRIVATE
34 class KCalendarCore::EventPrivate : public IncidencePrivate
35 {
36 public:
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.
49 EventPrivate::EventPrivate(const Incidence &other)
50  : IncidencePrivate(other)
51 {
52 }
53 
54 bool EventPrivate::validStatus(Incidence::Status status)
55 {
56  constexpr unsigned validSet
57  = 1u << Incidence::StatusNone
61  return validSet & (1u << status);
62 }
63 //@endcond
64 
66  : Incidence(new EventPrivate)
67 {
68 }
69 
70 Event::Event(const Event &other)
71  : Incidence(other, new EventPrivate(*(other.d_func())))
72 {
73 }
74 
75 Event::Event(const Incidence &other)
76  : Incidence(other, new EventPrivate(other))
77 {
78 }
79 
80 Event::~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 
101 bool 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 
129 void 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 
146 QDateTime 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 
178 bool Event::hasEndDate() const
179 {
180  Q_D(const Event);
181  return d->mDtEnd.isValid();
182 }
183 
184 bool 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 
223 void 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 
248 Event::Transparency Event::transparency() const
249 {
250  Q_D(const Event);
251  return d->mTransparency;
252 }
253 
254 void Event::setDuration(const Duration &duration)
255 {
256  // These both call update()/updated() and setFieldDirty().
257  setDtEnd(QDateTime());
259 }
260 
261 void Event::setAllDay(bool allday)
262 {
263  if (allday != allDay() && !mReadOnly) {
264  update();
266  Incidence::setAllDay(allday);
267  updated();
268  }
269 }
270 
271 bool Event::accept(Visitor &v, const IncidenceBase::Ptr &incidence)
272 {
273  return v.visit(incidence.staticCast<Event>());
274 }
275 
277 {
278  switch (role) {
279  case RoleRecurrenceStart:
281  case RoleStartTimeZone:
282  case RoleSort:
283  return dtStart();
284  case RoleCalendarHashing:
285  return !recurs() && !isMultiDay() ? dtStart() : QDateTime();
286  case RoleAlarmEndOffset:
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 
306 void 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 
324 void Event::virtual_hook(VirtualHook id, void *data)
325 {
326  Q_UNUSED(id);
327  Q_UNUSED(data);
328 }
329 
331 {
332  return Event::eventMimeType();
333 }
334 
336 {
337  return QLatin1String("application/x-vnd.akonadi.calendar.event");
338 }
339 
341 {
342  return QLatin1String("view-calendar-day");
343 }
344 
345 void 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 
353 void 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"
@ FieldTransparency
Field representing the TRANSPARENCY component.
Status
The different types of overall incidence status or confirmation.
Definition: incidence.h:84
void serialize(QDataStream &out) const override
Sub-type specific serialization.
Definition: incidence.cpp:1207
QDateTime addSecs(qint64 s) const const
void setTransparency(Transparency transparency)
Sets the event's time transparency level.
Definition: event.cpp:236
void setDateTime(const QDateTime &dateTime, DateTimeRole role) override
Definition: event.cpp:306
Represents a span of time measured in seconds or days.
Definition: duration.h:43
@ RoleDisplayEnd
Role used for display purposes, represents the end boundary if an incidence supports dtEnd.
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
bool recurs() const
Returns whether the event recurs at all.
Definition: incidence.cpp:607
@ StatusNone
No status.
Definition: incidence.h:85
DateTimeRole
The different types of incidence date/times roles.
QLatin1String mimeType() const override
Definition: event.cpp:330
@ RoleStartTimeZone
Role for determining an incidence's starting timezone.
Namespace for all KCalendarCore types.
Definition: alarm.h:36
void update()
Call this to notify the observers after the IncidenceBase object will be changed.
@ RoleAlarm
Role for determining the date/time of the first alarm.
KCALENDARCORE_EXPORT bool identical(QDateTime, QDateTime)
Compare two QDateTimes for extended equality.
@ RoleAlarmStartOffset
Role for an incidence alarm's starting offset date/time.
@ RoleSort
Role for an incidence's date/time used when sorting.
Provides the abstract base class common to non-FreeBusy (Events, To-dos, Journals) calendar component...
Definition: incidence.h:59
@ StatusTentative
event is tentative
Definition: incidence.h:86
void setAllDay(bool allDay) override
Definition: incidence.cpp:323
QLatin1String iconName(const QDateTime &recurrenceId={}) const override
Definition: event.cpp:340
QDate dateEnd() const
Returns the date when the event ends.
Definition: event.cpp:168
void setDtEnd(const QDateTime &dtEnd)
Sets the event end date and time.
Definition: event.cpp:129
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
void setDtStart(const QDateTime &dt) override
Sets the incidence starting date/time.
Definition: event.cpp:122
void setHasDuration(bool hasDuration)
Sets if the incidence has a duration.
bool hasDuration() const
Returns true if the incidence has a duration; false otherwise.
QDateTime toTimeZone(const QTimeZone &timeZone) const const
An abstract class that provides a common base for all calendar incidence classes.
Definition: incidencebase.h:98
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...
Definition: incidence.cpp:385
Q_SCRIPTABLE Q_NOREPLY void start()
void updated()
Call this to notify the observers after the IncidenceBase object has changed.
qint64 secsTo(const QDateTime &other) const const
virtual void setDuration(const Duration &duration)
Sets the incidence duration.
void virtual_hook(VirtualHook id, void *data) override
Definition: event.cpp:324
const T & at(int i) const const
bool equals(const IncidenceBase &incidence) const override
Compares this with Incidence incidence for equality.
Definition: incidence.cpp:198
static QLatin1String eventMimeType()
Returns the Akonadi specific sub MIME type of a KCalendarCore::Event.
Definition: event.cpp:335
void deserialize(QDataStream &in) override
Sub-type specific deserialization.
Definition: incidence.cpp:1235
bool isValid() const const
Q_SCRIPTABLE CaptureState status()
@ RoleDisplayStart
Role for display purposes, represents the start boundary of an incidence.
Event * clone() const override
Returns an exact copy of this Event.
Definition: event.cpp:82
@ RoleCalendarHashing
Role for looking up an incidence in a Calendar.
This class provides the interface for a visitor of calendar components.
Definition: visitor.h:30
@ RoleEnd
Role for determining an incidence's dtEnd, will return an invalid QDateTime if the incidence does not...
bool supportsGroupwareCommunication() const override
Definition: event.cpp:366
void setDtStart(const QDateTime &dt) override
Sets the incidence starting date/time.
Definition: incidence.cpp:376
@ StatusCanceled
event or to-do canceled; journal removed
Definition: incidence.h:90
IncidenceType
The different types of incidences, per RFC2445.
Event()
Constructs an event.
Definition: event.cpp:65
~Event() override
Destroys the event.
void setAllDay(bool allDay) override
Definition: event.cpp:261
@ RoleEndTimeZone
Role for determining an incidence's ending timezone.
bool isValid() const const
@ RoleRecurrenceStart
Role for determining the start of the recurrence.
@ TypeEvent
Type is an event.
IncidenceType type() const override
Definition: event.cpp:112
IncidenceBase & assign(const IncidenceBase &other) override
Provides polymorfic assignment.
Definition: incidence.cpp:184
@ RoleDnD
Role for determining new start and end dates after a DnD.
QByteArray typeStr() const override
Definition: event.cpp:117
@ StatusConfirmed
event is definite
Definition: incidence.h:87
@ RoleAlarmEndOffset
Role for an incidence alarm's ending offset date/time.
QSharedPointer< X > staticCast() const const
IncidenceBase & assign(const IncidenceBase &other) override
Definition: event.cpp:87
bool mReadOnly
Identifies a read-only incidence.
bool isMultiDay(const QTimeZone &zone={}) const
Returns true if the event spans multiple days, otherwise return false.
Definition: event.cpp:184
void setFieldDirty(IncidenceBase::Field field)
Marks Field field as dirty.
@ FieldDtEnd
Field representing the DTEND component.
@ Opaque
Event appears in free/busy time.
Definition: event.h:42
Alarm::List alarms() const
Returns a list of all incidence alarms.
Definition: incidence.cpp:888
Duration duration() const
Returns the length of the incidence duration.
Transparency
The different Event transparency types.
Definition: event.h:41
void setDuration(const Duration &duration) override
Sets the duration of this event.
Definition: event.cpp:254
Q_D(Todo)
Private class that helps to provide binary compatibility between releases.
bool equals(const IncidenceBase &event) const override
Compares two events for equality.
Definition: event.cpp:101
QDateTime dateTime(DateTimeRole role) const override
Definition: event.cpp:276
bool hasEndDate() const
Returns whether the event has an end date/time.
Definition: event.cpp:178
This class provides an Event in the sense of RFC2445.
Definition: event.h:32
void shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone) override
Definition: event.cpp:223
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Sep 28 2023 03:53:12 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.