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 #include <QUrl>
32 
33 #include <QStringList>
34 
35 #define KCALCORE_MAGIC_NUMBER 0xCA1C012E
36 #define KCALCORE_SERIALIZATION_VERSION 1
37 
38 using namespace KCalendarCore;
39 
40 /**
41  Private class that helps to provide binary compatibility between releases.
42  @internal
43 */
44 //@cond PRIVATE
45 class Q_DECL_HIDDEN KCalendarCore::IncidenceBase::Private
46 {
47 public:
48  Private()
49  : mUpdateGroupLevel(0)
50  , mUpdatedPending(false)
51  , mAllDay(false)
52  , mHasDuration(false)
53  {
54  }
55 
56  Private(const Private &other)
57  : mUpdateGroupLevel(0)
58  , mUpdatedPending(false)
59  , mAllDay(true)
60  , mHasDuration(false)
61  {
62  init(other);
63  }
64 
65  ~Private()
66  {
67  }
68 
69  void init(const Private &other);
70 
71  QDateTime mLastModified; // incidence last modified date
72  QDateTime mDtStart; // incidence start time
73  Person mOrganizer; // incidence person (owner)
74  QString mUid; // incidence unique id
75  Duration mDuration; // incidence duration
76  int mUpdateGroupLevel; // if non-zero, suppresses update() calls
77  bool mUpdatedPending = false; // true if an update has occurred since startUpdates()
78  bool mAllDay = false; // true if the incidence is all-day
79  bool mHasDuration = false; // true if the incidence has a duration
80  Attendee::List mAttendees; // list of incidence attendees
81  QStringList mComments; // list of incidence comments
82  QStringList mContacts; // list of incidence contacts
83  QList<IncidenceObserver *> mObservers; // list of incidence observers
84  QSet<Field> mDirtyFields; // Fields that changed since last time the incidence was created
85  // or since resetDirtyFlags() was called
86  QUrl mUrl; // incidence url property
87 };
88 
89 void IncidenceBase::Private::init(const Private &other)
90 {
91  mLastModified = other.mLastModified;
92  mDtStart = other.mDtStart;
93  mOrganizer = other.mOrganizer;
94  mUid = other.mUid;
95  mDuration = other.mDuration;
96  mAllDay = other.mAllDay;
97  mHasDuration = other.mHasDuration;
98 
99  mComments = other.mComments;
100  mContacts = other.mContacts;
101 
102  mAttendees = other.mAttendees;
103  mAttendees.reserve(other.mAttendees.count());
104  mUrl = other.mUrl;
105 }
106 
107 //@endcond
108 
110  : d(new KCalendarCore::IncidenceBase::Private)
111 {
112  mReadOnly = false;
114 }
115 
117  : CustomProperties(i)
118  , d(new KCalendarCore::IncidenceBase::Private(*i.d))
119 {
120  mReadOnly = i.mReadOnly;
121 }
122 
124 {
125  delete d;
126 }
127 
129 {
130  Q_ASSERT(type() == other.type());
131 
132  startUpdates();
133 
134  // assign is virtual, will call the derived class's
135  IncidenceBase &ret = assign(other);
136  endUpdates();
137  return ret;
138 }
139 
141 {
143  d->init(*other.d);
144  mReadOnly = other.mReadOnly;
145  d->mDirtyFields.clear();
146  d->mDirtyFields.insert(FieldUnknown);
147  return *this;
148 }
149 
151 {
152  if (i2.type() != type()) {
153  return false;
154  } else {
155  // equals is virtual, so here we're calling the derived class method
156  return equals(i2);
157  }
158 }
159 
161 {
162  return !operator==(i2);
163 }
164 
166 {
167  if (attendees().count() != i2.attendees().count()) {
168  // qCDebug(KCALCORE_LOG) << "Attendee count is different";
169  return false;
170  }
171 
172  Attendee::List al1 = attendees();
173  Attendee::List al2 = i2.attendees();
176  // TODO Does the order of attendees in the list really matter?
177  // Please delete this comment if you know it's ok, kthx
178  for (; a1 != al1.constEnd() && a2 != al2.constEnd(); ++a1, ++a2) {
179  if (!(*a1 == *a2)) {
180  // qCDebug(KCALCORE_LOG) << "Attendees are different";
181  return false;
182  }
183  }
184 
185  if (!CustomProperties::operator==(i2)) {
186  // qCDebug(KCALCORE_LOG) << "Properties are different";
187  return false;
188  }
189 
190  // Don't compare lastModified, otherwise the operator is not
191  // of much use. We are not comparing for identity, after all.
192  // no need to compare mObserver
193 
194  bool a = ((dtStart() == i2.dtStart()) || (!dtStart().isValid() && !i2.dtStart().isValid()));
195  bool b = organizer() == i2.organizer();
196  bool c = uid() == i2.uid();
197  bool d = allDay() == i2.allDay();
198  bool e = duration() == i2.duration();
199  bool f = hasDuration() == i2.hasDuration();
200  bool g = url() == i2.url();
201 
202  // qCDebug(KCALCORE_LOG) << a << b << c << d << e << f << g;
203  return a && b && c && d && e && f && g;
204 }
205 
207 {
208  Q_UNUSED(v);
209  Q_UNUSED(incidence);
210  return false;
211 }
212 
214 {
215  if (d->mUid != uid) {
216  update();
217  d->mUid = uid;
218  d->mDirtyFields.insert(FieldUid);
219  updated();
220  }
221 }
222 
224 {
225  return d->mUid;
226 }
227 
229 {
230  // DON'T! updated() because we call this from
231  // Calendar::updateEvent().
232 
233  d->mDirtyFields.insert(FieldLastModified);
234 
235  // Convert to UTC and remove milliseconds part.
236  QDateTime current = lm.toUTC();
237  QTime t = current.time();
238  t.setHMS(t.hour(), t.minute(), t.second(), 0);
239  current.setTime(t);
240 
241  d->mLastModified = current;
242 }
243 
245 {
246  return d->mLastModified;
247 }
248 
250 {
251  update();
252  // we don't check for readonly here, because it is
253  // possible that by setting the organizer we are changing
254  // the event's readonly status...
255  d->mOrganizer = organizer;
256 
257  d->mDirtyFields.insert(FieldOrganizer);
258 
259  updated();
260 }
261 
263 {
264  QString mail(o);
265  if (mail.startsWith(QLatin1String("MAILTO:"), Qt::CaseInsensitive)) {
266  mail.remove(0, 7);
267  }
268 
269  // split the string into full name plus email.
270  const Person organizer = Person::fromFullName(mail);
271  setOrganizer(organizer);
272 }
273 
275 {
276  return d->mOrganizer;
277 }
278 
279 void IncidenceBase::setReadOnly(bool readOnly)
280 {
281  mReadOnly = readOnly;
282 }
283 
285 {
286  return mReadOnly;
287 }
288 
290 {
291  // if ( mReadOnly ) return;
292 
293  if (!dtStart.isValid() && type() != IncidenceBase::TypeTodo) {
294  qCWarning(KCALCORE_LOG) << "Invalid dtStart";
295  }
296 
297  if (d->mDtStart != dtStart) {
298  update();
299  d->mDtStart = dtStart;
300  d->mDirtyFields.insert(FieldDtStart);
301  updated();
302  }
303 }
304 
306 {
307  return d->mDtStart;
308 }
309 
310 bool IncidenceBase::allDay() const
311 {
312  return d->mAllDay;
313 }
314 
316 {
317  if (mReadOnly || f == d->mAllDay) {
318  return;
319  }
320  update();
321  d->mAllDay = f;
322  if (d->mDtStart.isValid()) {
323  d->mDirtyFields.insert(FieldDtStart);
324  }
325  updated();
326 }
327 
328 void IncidenceBase::shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
329 {
330  update();
331  d->mDtStart = d->mDtStart.toTimeZone(oldZone);
332  d->mDtStart.setTimeZone(newZone);
333  d->mDirtyFields.insert(FieldDtStart);
334  d->mDirtyFields.insert(FieldDtEnd);
335  updated();
336 }
337 
338 void IncidenceBase::addComment(const QString &comment)
339 {
340  d->mComments += comment;
341 }
342 
344 {
345  bool found = false;
347 
348  for (i = d->mComments.begin(); !found && i != d->mComments.end(); ++i) {
349  if ((*i) == comment) {
350  found = true;
351  d->mComments.erase(i);
352  }
353  }
354 
355  if (found) {
356  d->mDirtyFields.insert(FieldComment);
357  }
358 
359  return found;
360 }
361 
363 {
364  d->mDirtyFields.insert(FieldComment);
365  d->mComments.clear();
366 }
367 
369 {
370  return d->mComments;
371 }
372 
373 void IncidenceBase::addContact(const QString &contact)
374 {
375  if (!contact.isEmpty()) {
376  d->mContacts += contact;
377  d->mDirtyFields.insert(FieldContact);
378  }
379 }
380 
382 {
383  bool found = false;
385 
386  for (i = d->mContacts.begin(); !found && i != d->mContacts.end(); ++i) {
387  if ((*i) == contact) {
388  found = true;
389  d->mContacts.erase(i);
390  }
391  }
392 
393  if (found) {
394  d->mDirtyFields.insert(FieldContact);
395  }
396 
397  return found;
398 }
399 
401 {
402  d->mDirtyFields.insert(FieldContact);
403  d->mContacts.clear();
404 }
405 
407 {
408  return d->mContacts;
409 }
410 
411 void IncidenceBase::addAttendee(const Attendee &a, bool doupdate)
412 {
413  if (a.isNull() || mReadOnly) {
414  return;
415  }
416  Q_ASSERT(!a.uid().isEmpty());
417 
418  if (doupdate) {
419  update();
420  }
421 
422  d->mAttendees.append(a);
423  if (doupdate) {
424  d->mDirtyFields.insert(FieldAttendees);
425  updated();
426  }
427 }
428 
430 {
431  return d->mAttendees;
432 }
433 
435 {
436  return d->mAttendees.count();
437 }
438 
440 {
441  if (mReadOnly) {
442  return;
443  }
444 
445  if (doUpdate) {
446  update();
447  }
448 
449  // don't simply assign, we need the logic in addAttendee here too
450  clearAttendees();
451  d->mAttendees.reserve(attendees.size());
452  for (const auto &a : attendees) {
453  addAttendee(a, false);
454  }
455 
456  if (doUpdate) {
457  d->mDirtyFields.insert(FieldAttendees);
458  updated();
459  }
460 }
461 
463 {
464  if (mReadOnly) {
465  return;
466  }
467  d->mDirtyFields.insert(FieldAttendees);
468  d->mAttendees.clear();
469 }
470 
472 {
474  for (it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it) {
475  if ((*it).email() == email) {
476  return *it;
477  }
478  }
479 
480  return {};
481 }
482 
483 Attendee IncidenceBase::attendeeByMails(const QStringList &emails, const QString &email) const
484 {
485  QStringList mails = emails;
486  if (!email.isEmpty()) {
487  mails.append(email);
488  }
489 
491  for (itA = d->mAttendees.constBegin(); itA != d->mAttendees.constEnd(); ++itA) {
492  for (QStringList::const_iterator it = mails.constBegin(); it != mails.constEnd(); ++it) {
493  if ((*itA).email() == (*it)) {
494  return *itA;
495  }
496  }
497  }
498 
499  return {};
500 }
501 
503 {
505  for (it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it) {
506  if ((*it).uid() == uid) {
507  return *it;
508  }
509  }
510 
511  return {};
512 }
513 
515 {
516  update();
517  d->mDuration = duration;
518  setHasDuration(true);
519  d->mDirtyFields.insert(FieldDuration);
520  updated();
521 }
522 
524 {
525  return d->mDuration;
526 }
527 
529 {
530  d->mHasDuration = hasDuration;
531 }
532 
534 {
535  return d->mHasDuration;
536 }
537 
539 {
540  d->mDirtyFields.insert(FieldUrl);
541  d->mUrl = url;
542 }
543 
545 {
546  return d->mUrl;
547 }
548 
550 {
551  if (observer && !d->mObservers.contains(observer)) {
552  d->mObservers.append(observer);
553  }
554 }
555 
557 {
558  d->mObservers.removeAll(observer);
559 }
560 
562 {
563  if (!d->mUpdateGroupLevel) {
564  d->mUpdatedPending = true;
565  const auto rid = recurrenceId();
566  for (IncidenceObserver *o : qAsConst(d->mObservers)) {
567  o->incidenceUpdate(uid(), rid);
568  }
569  }
570 }
571 
573 {
574  if (d->mUpdateGroupLevel) {
575  d->mUpdatedPending = true;
576  } else {
577  const auto rid = recurrenceId();
578  for (IncidenceObserver *o : qAsConst(d->mObservers)) {
579  o->incidenceUpdated(uid(), rid);
580  }
581  }
582 }
583 
585 {
586  update();
587  ++d->mUpdateGroupLevel;
588 }
589 
591 {
592  if (d->mUpdateGroupLevel > 0) {
593  if (--d->mUpdateGroupLevel == 0 && d->mUpdatedPending) {
594  d->mUpdatedPending = false;
595  updated();
596  }
597  }
598 }
599 
601 {
602  update();
603 }
604 
606 {
607  updated();
608 }
609 
611 {
612  return QDateTime();
613 }
614 
616 {
617  d->mDirtyFields.clear();
618 }
619 
621 {
622  return d->mDirtyFields;
623 }
624 
626 {
627  d->mDirtyFields.insert(field);
628 }
629 
631 {
632  return QUrl(QStringLiteral("urn:x-ical:") + uid());
633 }
634 
636 {
637  d->mDirtyFields = dirtyFields;
638 }
639 
641 {
642  Q_UNUSED(out);
643 }
644 
646 {
647  Q_UNUSED(in);
648 }
649 
650 /** static */
652 {
653  return KCALCORE_MAGIC_NUMBER;
654 }
655 
657 {
658  if (!i) {
659  return out;
660  }
661 
662  out << static_cast<quint32>(KCALCORE_MAGIC_NUMBER); // Magic number to identify KCalendarCore data
663  out << static_cast<quint32>(KCALCORE_SERIALIZATION_VERSION);
664  out << static_cast<qint32>(i->type());
665 
666  out << *(static_cast<CustomProperties *>(i.data()));
667  serializeQDateTimeAsKDateTime(out, i->d->mLastModified);
668  serializeQDateTimeAsKDateTime(out, i->d->mDtStart);
669  out << i->organizer() << i->d->mUid << i->d->mDuration << i->d->mAllDay << i->d->mHasDuration << i->d->mComments << i->d->mContacts
670  << i->d->mAttendees.count() << i->d->mUrl;
671 
672  for (const Attendee &attendee : qAsConst(i->d->mAttendees)) {
673  out << attendee;
674  }
675 
676  // Serialize the sub-class data.
677  i->serialize(out);
678 
679  return out;
680 }
681 
683 {
684  if (!i) {
685  return in;
686  }
687 
688  qint32 attendeeCount, type;
689  quint32 magic, version;
690 
691  in >> magic;
692 
693  if (magic != KCALCORE_MAGIC_NUMBER) {
694  qCWarning(KCALCORE_LOG) << "Invalid magic on serialized data";
695  return in;
696  }
697 
698  in >> version;
699 
700  if (version > KCALCORE_MAGIC_NUMBER) {
701  qCWarning(KCALCORE_LOG) << "Invalid version on serialized data";
702  return in;
703  }
704 
705  in >> type;
706 
707  in >> *(static_cast<CustomProperties *>(i.data()));
708  deserializeKDateTimeAsQDateTime(in, i->d->mLastModified);
709  deserializeKDateTimeAsQDateTime(in, i->d->mDtStart);
710  in >> i->d->mOrganizer >> i->d->mUid >> i->d->mDuration >> i->d->mAllDay >> i->d->mHasDuration >> i->d->mComments >> i->d->mContacts >> attendeeCount
711  >> i->d->mUrl;
712 
713  i->d->mAttendees.clear();
714  i->d->mAttendees.reserve(attendeeCount);
715  for (int it = 0; it < attendeeCount; it++) {
716  Attendee attendee;
717  in >> attendee;
718  i->d->mAttendees.append(attendee);
719  }
720 
721  // Deserialize the sub-class data.
722  i->deserialize(in);
723 
724  return in;
725 }
726 
728 {
729 }
730 
731 QVariantList IncidenceBase::attendeesVariant() const
732 {
733  QVariantList l;
734  l.reserve(d->mAttendees.size());
735  std::transform(d->mAttendees.begin(), d->mAttendees.end(), std::back_inserter(l), [](const Attendee &a) {
736  return QVariant::fromValue(a);
737  });
738  return l;
739 }
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
Alarm serializer.
Definition: alarm.cpp:821
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:834
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:359
~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 Tue Apr 13 2021 22:50:40 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.