KCalendarCore

incidencebase.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  SPDX-FileCopyrightText: 2001,2004 Cornelius Schumacher <[email protected]>
5  SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <[email protected]>
6  SPDX-FileCopyrightText: 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
7  SPDX-FileContributor: Alvaro Manera <[email protected]>
8 
9  SPDX-License-Identifier: LGPL-2.0-or-later
10 */
11 /**
12  @file
13  This file is part of the API for handling calendar data and
14  defines the IncidenceBase class.
15 
16  @brief
17  An abstract base class that provides a common base for all calendar incidence
18  classes.
19 
20  @author Cornelius Schumacher <[email protected]>
21  @author Reinhold Kainhofer <[email protected]>
22 */
23 
24 #include "incidencebase.h"
25 #include "calformat.h"
26 #include "utils_p.h"
27 #include "visitor.h"
28 
29 #include "kcalendarcore_debug.h"
30 #include <QTime>
31 
32 #include <QStringList>
33 
34 #define KCALCORE_MAGIC_NUMBER 0xCA1C012E
35 #define KCALCORE_SERIALIZATION_VERSION 1
36 
37 using namespace KCalendarCore;
38 
39 /**
40  Private class that helps to provide binary compatibility between releases.
41  @internal
42 */
43 //@cond PRIVATE
44 class Q_DECL_HIDDEN KCalendarCore::IncidenceBase::Private
45 {
46 public:
47  Private()
48  : mUpdateGroupLevel(0)
49  , mUpdatedPending(false)
50  , mAllDay(false)
51  , mHasDuration(false)
52  {
53  }
54 
55  Private(const Private &other)
56  : mUpdateGroupLevel(0)
57  , mUpdatedPending(false)
58  , mAllDay(true)
59  , mHasDuration(false)
60  {
61  init(other);
62  }
63 
64  ~Private()
65  {
66  }
67 
68  void init(const Private &other);
69 
70  QDateTime mLastModified; // incidence last modified date
71  QDateTime mDtStart; // incidence start time
72  Person mOrganizer; // incidence person (owner)
73  QString mUid; // incidence unique id
74  Duration mDuration; // incidence duration
75  int mUpdateGroupLevel; // if non-zero, suppresses update() calls
76  bool mUpdatedPending = false; // true if an update has occurred since startUpdates()
77  bool mAllDay = false; // true if the incidence is all-day
78  bool mHasDuration = false; // true if the incidence has a duration
79  Attendee::List mAttendees; // list of incidence attendees
80  QStringList mComments; // list of incidence comments
81  QStringList mContacts; // list of incidence contacts
82  QList<IncidenceObserver *> mObservers; // list of incidence observers
83  QSet<Field> mDirtyFields; // Fields that changed since last time the incidence was created
84  // or since resetDirtyFlags() was called
85  QUrl mUrl; // incidence url property
86 };
87 
88 void IncidenceBase::Private::init(const Private &other)
89 {
90  mLastModified = other.mLastModified;
91  mDtStart = other.mDtStart;
92  mOrganizer = other.mOrganizer;
93  mUid = other.mUid;
94  mDuration = other.mDuration;
95  mAllDay = other.mAllDay;
96  mHasDuration = other.mHasDuration;
97 
98  mComments = other.mComments;
99  mContacts = other.mContacts;
100 
101  mAttendees = other.mAttendees;
102  mAttendees.reserve(other.mAttendees.count());
103  mUrl = other.mUrl;
104 }
105 
106 //@endcond
107 
109  : d(new KCalendarCore::IncidenceBase::Private)
110 {
111  mReadOnly = false;
113 }
114 
116  : CustomProperties(i)
117  , d(new KCalendarCore::IncidenceBase::Private(*i.d))
118 {
119  mReadOnly = i.mReadOnly;
120 }
121 
123 {
124  delete d;
125 }
126 
128 {
129  Q_ASSERT(type() == other.type());
130 
131  startUpdates();
132 
133  // assign is virtual, will call the derived class's
134  IncidenceBase &ret = assign(other);
135  endUpdates();
136  return ret;
137 }
138 
140 {
142  d->init(*other.d);
143  mReadOnly = other.mReadOnly;
144  d->mDirtyFields.clear();
145  d->mDirtyFields.insert(FieldUnknown);
146  return *this;
147 }
148 
150 {
151  if (i2.type() != type()) {
152  return false;
153  } else {
154  // equals is virtual, so here we're calling the derived class method
155  return equals(i2);
156  }
157 }
158 
160 {
161  return !operator==(i2);
162 }
163 
165 {
166  if (attendees().count() != i2.attendees().count()) {
167  // qCDebug(KCALCORE_LOG) << "Attendee count is different";
168  return false;
169  }
170 
171  Attendee::List al1 = attendees();
172  Attendee::List al2 = i2.attendees();
175  // TODO Does the order of attendees in the list really matter?
176  // Please delete this comment if you know it's ok, kthx
177  for (; a1 != al1.constEnd() && a2 != al2.constEnd(); ++a1, ++a2) {
178  if (!(*a1 == *a2)) {
179  // qCDebug(KCALCORE_LOG) << "Attendees are different";
180  return false;
181  }
182  }
183 
184  if (!CustomProperties::operator==(i2)) {
185  // qCDebug(KCALCORE_LOG) << "Properties are different";
186  return false;
187  }
188 
189  // Don't compare lastModified, otherwise the operator is not
190  // of much use. We are not comparing for identity, after all.
191  // no need to compare mObserver
192 
193  bool a = ((dtStart() == i2.dtStart()) || (!dtStart().isValid() && !i2.dtStart().isValid()));
194  bool b = organizer() == i2.organizer();
195  bool c = uid() == i2.uid();
196  bool d = allDay() == i2.allDay();
197  bool e = duration() == i2.duration();
198  bool f = hasDuration() == i2.hasDuration();
199  bool g = url() == i2.url();
200 
201  // qCDebug(KCALCORE_LOG) << a << b << c << d << e << f << g;
202  return a && b && c && d && e && f && g;
203 }
204 
206 {
207  Q_UNUSED(v);
208  Q_UNUSED(incidence);
209  return false;
210 }
211 
213 {
214  if (d->mUid != uid) {
215  update();
216  d->mUid = uid;
217  d->mDirtyFields.insert(FieldUid);
218  updated();
219  }
220 }
221 
223 {
224  return d->mUid;
225 }
226 
228 {
229  // DON'T! updated() because we call this from
230  // Calendar::updateEvent().
231 
232  d->mDirtyFields.insert(FieldLastModified);
233 
234  // Convert to UTC and remove milliseconds part.
235  QDateTime current = lm.toUTC();
236  QTime t = current.time();
237  t.setHMS(t.hour(), t.minute(), t.second(), 0);
238  current.setTime(t);
239 
240  d->mLastModified = current;
241 }
242 
244 {
245  return d->mLastModified;
246 }
247 
249 {
250  update();
251  // we don't check for readonly here, because it is
252  // possible that by setting the organizer we are changing
253  // the event's readonly status...
254  d->mOrganizer = organizer;
255 
256  d->mDirtyFields.insert(FieldOrganizer);
257 
258  updated();
259 }
260 
262 {
263  QString mail(o);
264  if (mail.startsWith(QLatin1String("MAILTO:"), Qt::CaseInsensitive)) {
265  mail.remove(0, 7);
266  }
267 
268  // split the string into full name plus email.
269  const Person organizer = Person::fromFullName(mail);
270  setOrganizer(organizer);
271 }
272 
274 {
275  return d->mOrganizer;
276 }
277 
278 void IncidenceBase::setReadOnly(bool readOnly)
279 {
280  mReadOnly = readOnly;
281 }
282 
284 {
285  return mReadOnly;
286 }
287 
289 {
290  // if ( mReadOnly ) return;
291 
292  if (!dtStart.isValid() && type() != IncidenceBase::TypeTodo) {
293  qCWarning(KCALCORE_LOG) << "Invalid dtStart";
294  }
295 
296  if (d->mDtStart != dtStart) {
297  update();
298  d->mDtStart = dtStart;
299  d->mDirtyFields.insert(FieldDtStart);
300  updated();
301  }
302 }
303 
305 {
306  return d->mDtStart;
307 }
308 
309 bool IncidenceBase::allDay() const
310 {
311  return d->mAllDay;
312 }
313 
315 {
316  if (mReadOnly || f == d->mAllDay) {
317  return;
318  }
319  update();
320  d->mAllDay = f;
321  if (d->mDtStart.isValid()) {
322  d->mDirtyFields.insert(FieldDtStart);
323  }
324  updated();
325 }
326 
327 void IncidenceBase::shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
328 {
329  update();
330  d->mDtStart = d->mDtStart.toTimeZone(oldZone);
331  d->mDtStart.setTimeZone(newZone);
332  d->mDirtyFields.insert(FieldDtStart);
333  d->mDirtyFields.insert(FieldDtEnd);
334  updated();
335 }
336 
337 void IncidenceBase::addComment(const QString &comment)
338 {
339  d->mComments += comment;
340 }
341 
343 {
344  bool found = false;
346 
347  for (i = d->mComments.begin(); !found && i != d->mComments.end(); ++i) {
348  if ((*i) == comment) {
349  found = true;
350  d->mComments.erase(i);
351  }
352  }
353 
354  if (found) {
355  d->mDirtyFields.insert(FieldComment);
356  }
357 
358  return found;
359 }
360 
362 {
363  d->mDirtyFields.insert(FieldComment);
364  d->mComments.clear();
365 }
366 
368 {
369  return d->mComments;
370 }
371 
372 void IncidenceBase::addContact(const QString &contact)
373 {
374  if (!contact.isEmpty()) {
375  d->mContacts += contact;
376  d->mDirtyFields.insert(FieldContact);
377  }
378 }
379 
381 {
382  bool found = false;
384 
385  for (i = d->mContacts.begin(); !found && i != d->mContacts.end(); ++i) {
386  if ((*i) == contact) {
387  found = true;
388  d->mContacts.erase(i);
389  }
390  }
391 
392  if (found) {
393  d->mDirtyFields.insert(FieldContact);
394  }
395 
396  return found;
397 }
398 
400 {
401  d->mDirtyFields.insert(FieldContact);
402  d->mContacts.clear();
403 }
404 
406 {
407  return d->mContacts;
408 }
409 
410 void IncidenceBase::addAttendee(const Attendee &a, bool doupdate)
411 {
412  if (a.isNull() || mReadOnly) {
413  return;
414  }
415  Q_ASSERT(!a.uid().isEmpty());
416 
417  if (doupdate) {
418  update();
419  }
420 
421  d->mAttendees.append(a);
422  if (doupdate) {
423  d->mDirtyFields.insert(FieldAttendees);
424  updated();
425  }
426 }
427 
429 {
430  return d->mAttendees;
431 }
432 
434 {
435  return d->mAttendees.count();
436 }
437 
439 {
440  if (mReadOnly) {
441  return;
442  }
443 
444  if (doUpdate) {
445  update();
446  }
447 
448  // don't simply assign, we need the logic in addAttendee here too
449  clearAttendees();
450  d->mAttendees.reserve(attendees.size());
451  for (const auto &a : attendees) {
452  addAttendee(a, false);
453  }
454 
455  if (doUpdate) {
456  d->mDirtyFields.insert(FieldAttendees);
457  updated();
458  }
459 }
460 
462 {
463  if (mReadOnly) {
464  return;
465  }
466  d->mDirtyFields.insert(FieldAttendees);
467  d->mAttendees.clear();
468 }
469 
471 {
473  for (it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it) {
474  if ((*it).email() == email) {
475  return *it;
476  }
477  }
478 
479  return {};
480 }
481 
482 Attendee IncidenceBase::attendeeByMails(const QStringList &emails, const QString &email) const
483 {
484  QStringList mails = emails;
485  if (!email.isEmpty()) {
486  mails.append(email);
487  }
488 
490  for (itA = d->mAttendees.constBegin(); itA != d->mAttendees.constEnd(); ++itA) {
491  for (QStringList::const_iterator it = mails.constBegin(); it != mails.constEnd(); ++it) {
492  if ((*itA).email() == (*it)) {
493  return *itA;
494  }
495  }
496  }
497 
498  return {};
499 }
500 
502 {
504  for (it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it) {
505  if ((*it).uid() == uid) {
506  return *it;
507  }
508  }
509 
510  return {};
511 }
512 
514 {
515  update();
516  d->mDuration = duration;
517  setHasDuration(true);
518  d->mDirtyFields.insert(FieldDuration);
519  updated();
520 }
521 
523 {
524  return d->mDuration;
525 }
526 
528 {
529  d->mHasDuration = hasDuration;
530 }
531 
533 {
534  return d->mHasDuration;
535 }
536 
538 {
539  d->mDirtyFields.insert(FieldUrl);
540  d->mUrl = url;
541 }
542 
544 {
545  return d->mUrl;
546 }
547 
549 {
550  if (observer && !d->mObservers.contains(observer)) {
551  d->mObservers.append(observer);
552  }
553 }
554 
556 {
557  d->mObservers.removeAll(observer);
558 }
559 
561 {
562  if (!d->mUpdateGroupLevel) {
563  d->mUpdatedPending = true;
564  const auto rid = recurrenceId();
565  for (IncidenceObserver *o : qAsConst(d->mObservers)) {
566  o->incidenceUpdate(uid(), rid);
567  }
568  }
569 }
570 
572 {
573  if (d->mUpdateGroupLevel) {
574  d->mUpdatedPending = true;
575  } else {
576  const auto rid = recurrenceId();
577  for (IncidenceObserver *o : qAsConst(d->mObservers)) {
578  o->incidenceUpdated(uid(), rid);
579  }
580  }
581 }
582 
584 {
585  update();
586  ++d->mUpdateGroupLevel;
587 }
588 
590 {
591  if (d->mUpdateGroupLevel > 0) {
592  if (--d->mUpdateGroupLevel == 0 && d->mUpdatedPending) {
593  d->mUpdatedPending = false;
594  updated();
595  }
596  }
597 }
598 
600 {
601  update();
602 }
603 
605 {
606  updated();
607 }
608 
610 {
611  return QDateTime();
612 }
613 
615 {
616  d->mDirtyFields.clear();
617 }
618 
620 {
621  return d->mDirtyFields;
622 }
623 
625 {
626  d->mDirtyFields.insert(field);
627 }
628 
630 {
631  return QUrl(QStringLiteral("urn:x-ical:") + uid());
632 }
633 
635 {
636  d->mDirtyFields = dirtyFields;
637 }
638 
640 {
641  Q_UNUSED(out);
642 }
643 
645 {
646  Q_UNUSED(in);
647 }
648 
649 /** static */
651 {
652  return KCALCORE_MAGIC_NUMBER;
653 }
654 
656 {
657  if (!i) {
658  return out;
659  }
660 
661  out << static_cast<quint32>(KCALCORE_MAGIC_NUMBER); // Magic number to identify KCalendarCore data
662  out << static_cast<quint32>(KCALCORE_SERIALIZATION_VERSION);
663  out << static_cast<qint32>(i->type());
664 
665  out << *(static_cast<CustomProperties *>(i.data()));
666  serializeQDateTimeAsKDateTime(out, i->d->mLastModified);
667  serializeQDateTimeAsKDateTime(out, i->d->mDtStart);
668  out << i->organizer() << i->d->mUid << i->d->mDuration << i->d->mAllDay << i->d->mHasDuration << i->d->mComments << i->d->mContacts
669  << i->d->mAttendees.count() << i->d->mUrl;
670 
671  for (const Attendee &attendee : qAsConst(i->d->mAttendees)) {
672  out << attendee;
673  }
674 
675  // Serialize the sub-class data.
676  i->serialize(out);
677 
678  return out;
679 }
680 
682 {
683  if (!i) {
684  return in;
685  }
686 
687  qint32 attendeeCount;
688  qint32 type;
689  quint32 magic;
690  quint32 version;
691 
692  in >> magic;
693 
694  if (magic != KCALCORE_MAGIC_NUMBER) {
695  qCWarning(KCALCORE_LOG) << "Invalid magic on serialized data";
696  return in;
697  }
698 
699  in >> version;
700 
701  if (version > KCALCORE_MAGIC_NUMBER) {
702  qCWarning(KCALCORE_LOG) << "Invalid version on serialized data";
703  return in;
704  }
705 
706  in >> type;
707 
708  in >> *(static_cast<CustomProperties *>(i.data()));
709  deserializeKDateTimeAsQDateTime(in, i->d->mLastModified);
710  deserializeKDateTimeAsQDateTime(in, i->d->mDtStart);
711  in >> i->d->mOrganizer >> i->d->mUid >> i->d->mDuration >> i->d->mAllDay >> i->d->mHasDuration >> i->d->mComments >> i->d->mContacts >> attendeeCount
712  >> i->d->mUrl;
713 
714  i->d->mAttendees.clear();
715  i->d->mAttendees.reserve(attendeeCount);
716  for (int it = 0; it < attendeeCount; it++) {
717  Attendee attendee;
718  in >> attendee;
719  i->d->mAttendees.append(attendee);
720  }
721 
722  // Deserialize the sub-class data.
723  i->deserialize(in);
724 
725  return in;
726 }
727 
729 {
730 }
731 
732 QVariantList IncidenceBase::attendeesVariant() const
733 {
734  QVariantList l;
735  l.reserve(d->mAttendees.size());
736  std::transform(d->mAttendees.begin(), d->mAttendees.end(), std::back_inserter(l), [](const Attendee &a) {
737  return QVariant::fromValue(a);
738  });
739  return l;
740 }
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
Alarm serializer.
Definition: alarm.cpp:820
int minute() const const
virtual void serialize(QDataStream &out) const
Sub-type specific serialization.
void setDirtyFields(const QSet< IncidenceBase::Field > &)
Sets which fields are dirty.
void endUpdates()
Call this when a group of updates is complete, to notify observers that the instance has changed...
QDateTime toUTC() const const
virtual IncidenceBase & assign(const IncidenceBase &other)
Provides polymorfic assignment.
virtual void setLastModified(const QDateTime &lm)
Sets the time the incidence was last modified to lm.
void update()
Call this to notify the observers after the IncidenceBase object will be changed. ...
A class to manage custom calendar properties.
This class provides the interface for a visitor of calendar components.
Definition: visitor.h:30
bool hasDuration() const
Returns true if the incidence has a duration; false otherwise.
void clearComments()
Deletes all incidence comments.
bool setHMS(int h, int m, int s, int ms)
virtual QDateTime recurrenceId() const
Returns the incidence recurrenceId.
QUrl uri() const
Returns the uri for the incidence, of form urn:x-ical:<uid>
Represents a person, by name and email address.
Definition: person.h:37
Represents information related to an attendee of an Calendar Incidence, typically a meeting or task (...
Definition: attendee.h:44
static QString createUniqueId()
Creates a unique id string.
Definition: calformat.cpp:105
QVector::const_iterator constEnd() const const
Field representing the URL component.
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
Alarm deserializer.
Definition: alarm.cpp:833
virtual ~IncidenceObserver()
Destroys the IncidenceObserver.
void setTime(const QTime &time)
void customPropertyUpdate() override
static Person fromFullName(const QString &fullName)
Constructs a person with name and email address taken from fullName.
Definition: person.cpp:362
~IncidenceBase() override
Destroys the IncidenceBase.
Field
The different types of incidence fields.
void addContact(const QString &contact)
Adds a contact to thieincidence.
QTime time() const const
void setUrl(const QUrl &url)
Sets the incidences url.
void setOrganizer(const Person &organizer)
Sets the organizer for the incidence.
virtual bool equals(const IncidenceBase &incidenceBase) const
Provides polymorfic comparison for equality.
QString & remove(int position, int n)
typedef ConstIterator
bool operator!=(const IncidenceBase &ib) const
Compares this with IncidenceBase ib for inequality.
T * data() const const
This file is part of the API for handling calendar data and defines the CalFormat abstract base class...
int second() const const
Attendee attendeeByMails(const QStringList &emails, const QString &email=QString()) const
Returns the first incidence attendee with one of the specified email addresses.
virtual void setDuration(const Duration &duration)
Sets the incidence duration.
An abstract class that provides a common base for all calendar incidence classes. ...
Definition: incidencebase.h:97
virtual void setReadOnly(bool readOnly)
Sets readonly status.
IncidenceBase & operator=(const IncidenceBase &other)
Assignment operator.
QStringList comments() const
Returns all incidence comments as a list of strings.
Represents a span of time measured in seconds or days.
Definition: duration.h:43
void clearAttendees()
Removes all attendees from the incidence.
void append(const T &value)
QString & insert(int position, QChar ch)
virtual void setDtStart(const QDateTime &dtStart)
Sets the incidence&#39;s starting date/time with a QDateTime.
Duration duration() const
Returns the length of the incidence duration.
int attendeeCount() const
Returns the number of incidence attendees.
QUrl url() const
Returns the url.
void setHasDuration(bool hasDuration)
Sets if the incidence has a duration.
void addAttendee(const Attendee &attendee, bool doUpdate=true)
Add Attendee to this incidence.
CaseInsensitive
bool isEmpty() const const
void setAttendees(const Attendee::List &attendees, bool doUpdate=true)
Set the attendees of this incidence.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
virtual void shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
Shift the times of the incidence so that they appear at the same clock time as before but in a new ti...
void startUpdates()
Call this when a group of updates is going to be made.
Something changed. Always set when you use the assignment operator.
typedef Iterator
virtual bool accept(Visitor &v, const IncidenceBase::Ptr &incidence)
Accept IncidenceVisitor.
void setUid(const QString &uid)
Sets the unique id for the incidence to uid.
bool operator==(const IncidenceBase &ib) const
Compares this with IncidenceBase ib for equality.
QSet< IncidenceBase::Field > dirtyFields() const
Returns a QSet with all Fields that were changed since the incidence was created or resetDirtyFields(...
virtual IncidenceType type() const =0
Returns the incidence type.
Field representing the CONTACT component.
Field representing the ORGANIZER component.
void addComment(const QString &comment)
Adds a comment to the incidence.
Attendee attendeeByUid(const QString &uid) const
Returns the incidence attendee with the specified attendee UID.
static quint32 magicSerializationIdentifier()
Constant that identifies KCalendarCore data in a binary stream.
int hour() const const
Field representing the DTEND component.
Field representing the ATTENDEE component.
Field representing the COMMENT component.
void updated()
Call this to notify the observers after the IncidenceBase object has changed.
void customPropertyUpdated() override
QVariant fromValue(const T &value)
Person organizer() const
Returns the Person associated with this incidence.
QCA_EXPORT void init()
IncidenceBase()
Constructs an empty IncidenceBase.
bool removeComment(const QString &comment)
Removes a comment from the incidence.
bool isValid() const const
Field representing the DTSTART component.
Field representing the UID component.
QVector::const_iterator constBegin() const const
void setFieldDirty(IncidenceBase::Field field)
Marks Field field as dirty.
This file is part of the API for handling calendar data and defines the IncidenceBase class...
bool isReadOnly() const
Returns true the object is read-only; false otherwise.
void clearContacts()
Deletes all incidence contacts.
bool removeContact(const QString &contact)
Removes a contact from the incidence.
bool allDay() const
Returns true or false depending on whether the incidence is all-day.
QDateTime lastModified() const
Returns the time the incidence was last modified.
QStringList contacts() const
Returns all incidence contacts as a list of strings.
Attendee attendeeByMail(const QString &email) const
Returns the attendee with the specified email address.
void resetDirtyFields()
Resets dirty fields.
virtual void setAllDay(bool allDay)
Sets whether the incidence is all-day, i.e.
virtual QDateTime dtStart() const
Returns an incidence&#39;s starting date/time as a QDateTime.
virtual void deserialize(QDataStream &in)
Sub-type specific deserialization.
QList::const_iterator constEnd() const const
QList::const_iterator constBegin() const const
Field representing the DURATION component.
int size() const const
Field representing the LAST-MODIFIED component.
void unRegisterObserver(IncidenceObserver *observer)
Unregister observer.
Attendee::List attendees() const
Returns a list of incidence attendees.
CustomProperties & operator=(const CustomProperties &other)
Assignment operator.
Namespace for all KCalendarCore types.
Definition: alarm.h:36
QString uid() const
Returns the unique id (uid) for the incidence.
void registerObserver(IncidenceObserver *observer)
Register observer.
bool mReadOnly
Identifies a read-only incidence.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Sep 24 2021 22:51:50 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.