/* This file is part of the kcalcore library. SPDX-FileCopyrightText: 2001-2003 Cornelius Schumacher SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer SPDX-FileCopyrightText: 2005 Rafal Rzepecki SPDX-FileCopyrightText: 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. SPDX-FileContributor: Alvaro Manera SPDX-License-Identifier: LGPL-2.0-or-later */ /* @file This file is part of the API for handling calendar data and defines the IncidenceBase class. @glossary @anchor incidence @b incidence: General term for a calendar component. Examples are events, to-dos, and journals. @glossary @anchor event @b event: An \l incidence that has a start and end time, typically representing some occurrence of social or personal importance. May be recurring. Examples are appointments, meetings, or holidays. @glossary @anchor to-do @b to-do: An \l incidence that has an optional start time and an optional due time typically representing some undertaking to be performed. May be recurring. Examples are "fix the bug" or "pay the bills". @glossary @anchor todo @b todo: See \l to-do. @glossary @anchor journal @b journal: An \l incidence with a start date that represents a diary or daily record of one's activities. May @b not be recurring. */ #ifndef KCALCORE_INCIDENCEBASE_H #define KCALCORE_INCIDENCEBASE_H #include "attendee.h" #include "customproperties.h" #include "duration.h" #include "person.h" #include #include #include #include #include class QUrl; class QDate; class QTimeZone; namespace KCalendarCore { /*! List of dates */ typedef QList DateList; /*! List of times */ typedef QList DateTimeList; class Event; class Todo; class Journal; class FreeBusy; class Visitor; class IncidenceBasePrivate; /*! \qmlvaluetype incidenceBase \inqmlmodule org.kde.kcalendarcore \nativetype KCalendarCore::IncidenceBase \brief An abstract class that provides a common base for all calendar incidence classes. define: organizer (person) define: uid (same as the attendee uid?) Several properties are not allowed for VFREEBUSY objects (see rfc:2445), so they are not in IncidenceBase. The hierarchy is: \list \li IncidenceBase \list \li FreeBusy \li Incidence \list \li KCalendarCore::Event \li KCalendarCore::Todo \li KCalendarCore::Journal \endlist \endlist \endlist So IncidenceBase contains all properties that are common to all classes, and Incidence contains all additional properties that are common to Events, Todos and Journals, but are not allowed for FreeBusy entries. */ /*! \class KCalendarCore::IncidenceBase \inmodule KCalendarCore \inheaderfile KCalendarCore/IncidenceBase \brief An abstract class that provides a common base for all calendar incidence classes. define: organizer (person) define: uid (same as the attendee uid?) Several properties are not allowed for VFREEBUSY objects (see rfc:2445), so they are not in IncidenceBase. The hierarchy is: \list \li IncidenceBase \list \li FreeBusy \li Incidence \list \li KCalendarCore::Event \li KCalendarCore::Todo \li KCalendarCore::Journal \endlist \endlist \endlist So IncidenceBase contains all properties that are common to all classes, and Incidence contains all additional properties that are common to Events, Todos and Journals, but are not allowed for FreeBusy entries. */ class KCALENDARCORE_EXPORT IncidenceBase : public CustomProperties { Q_GADGET /*! * \qmlproperty string incidenceBase::uid */ /*! * \property KCalendarCore::IncidenceBase::uid */ Q_PROPERTY(QString uid READ uid WRITE setUid) /*! * \qmlproperty date incidenceBase::lastModified */ /*! * \property KCalendarCore::IncidenceBase::lastModified */ Q_PROPERTY(QDateTime lastModified READ lastModified WRITE setLastModified) /*! * \qmlproperty date incidenceBase::dtStart */ /*! * \property KCalendarCore::IncidenceBase::dtStart */ Q_PROPERTY(QDateTime dtStart READ dtStart WRITE setDtStart) /*! * \qmlproperty bool incidenceBase::allDay */ /*! * \property KCalendarCore::IncidenceBase::allDay */ Q_PROPERTY(bool allDay READ allDay WRITE setAllDay) /*! * \qmlproperty KCalendarCore::Person incidenceBase::organizer */ /*! * \property KCalendarCore::IncidenceBase::organizer */ Q_PROPERTY(KCalendarCore::Person organizer READ organizer WRITE setOrganizer) /*! * \qmlproperty list incidenceBase::attendees */ /*! * \property KCalendarCore::IncidenceBase::attendees */ Q_PROPERTY(QList attendees READ attendees) /*! * \qmlproperty url incidenceBase::url */ /*! * \property KCalendarCore::IncidenceBase::url */ Q_PROPERTY(QUrl url READ url WRITE setUrl) public: /*! A shared pointer to an IncidenceBase. */ typedef QSharedPointer Ptr; /*! \enum KCalendarCore::IncidenceBase::IncidenceType \brief The different types of incidences, per RFC2445. \value TypeEvent Type is an event. \value TypeTodo Type is a to-do. \value TypeJournal Type is a journal. \value TypeFreeBusy Type is a free/busy. \value TypeUnknown Type unknown. \sa type(), typeStr() */ enum IncidenceType { TypeEvent = 0, TypeTodo, TypeJournal, TypeFreeBusy, TypeUnknown, }; /*! \enum KCalendarCore::IncidenceBase::DateTimeRole \brief The different types of incidence date/times roles. \value RoleAlarmStartOffset Role for an incidence alarm's starting offset date/time. \value RoleAlarmEndOffset Role for an incidence alarm's ending offset date/time. \value RoleSort Role for an incidence's date/time used when sorting. \value RoleCalendarHashing Role for looking up an incidence in a Calendar. \value RoleStartTimeZone Role for determining an incidence's starting timezone. \value RoleEndTimeZone Role for determining an incidence's ending timezone. \value RoleEndRecurrenceBase \value RoleEnd Role for determining an incidence's dtEnd, will return an invalid QDateTime if the incidence does not support dtEnd. \value RoleDisplayEnd Role used for display purposes, represents the end boundary if an incidence supports dtEnd. \value RoleAlarm Role for determining the date/time of the first alarm. Returns invalid time if the incidence doesn't have any alarm. \value RoleRecurrenceStart Role for determining the start of the recurrence. Currently that's DTSTART for an event and DTDUE for a to-do. \note If the incidence is a to-do, recurrence should be calculated having DTSTART for a reference, not DT-DUE. This is one place KCalendarCore isn't compliant with RFC2445. \value RoleDisplayStart Role for display purposes, represents the start boundary of an incidence. To-dos return dtDue here, for historical reasons. \value RoleDnD Role for determining new start and end dates after a DnD. \sa dateTime() */ enum DateTimeRole { RoleAlarmStartOffset = 0, RoleAlarmEndOffset, RoleSort, RoleCalendarHashing, RoleStartTimeZone, RoleEndTimeZone, RoleEndRecurrenceBase, RoleEnd, RoleDisplayEnd, RoleAlarm, RoleRecurrenceStart, RoleDisplayStart, RoleDnD, }; /*! \enum KCalendarCore::IncidenceBase::Field \brief The different types of incidence fields. \value FieldDtStart Field representing the DTSTART component. \value FieldDtEnd Field representing the DTEND component. \value FieldLastModified Field representing the LAST-MODIFIED component. \value FieldDescription Field representing the DESCRIPTION component. \value FieldSummary Field representing the SUMMARY component. \value FieldLocation Field representing the LOCATION component. \value FieldCompleted Field representing the COMPLETED component. \value FieldPercentComplete Field representing the PERCENT-COMPLETE component. \value FieldDtDue Field representing the DUE component. \value FieldCategories Field representing the CATEGORIES component. \value FieldRelatedTo Field representing the RELATED-TO component. \value FieldRecurrence Field representing the EXDATE, EXRULE, RDATE, and RRULE components. \value FieldAttachment Field representing the ATTACH component. \value FieldSecrecy Field representing the CLASS component. \value FieldStatus Field representing the STATUS component. \value FieldTransparency Field representing the TRANSPARENCY component. \value FieldResources Field representing the RESOURCES component. \value FieldPriority Field representing the PRIORITY component. \value FieldGeoLatitude Field representing the latitude part of the GEO component. \value FieldGeoLongitude Field representing the longitude part of the GEO component. \value FieldRecurrenceId Field representing the RECURRENCE-ID component. \value FieldAlarms Field representing the VALARM component. \value FieldSchedulingId Field representing the X-KDE-LIBKCAL-ID component. \value FieldAttendees Field representing the ATTENDEE component. \value FieldOrganizer Field representing the ORGANIZER component. \value FieldCreated Field representing the CREATED component. \value FieldRevision Field representing the SEQUENCE component. \value FieldDuration Field representing the DURATION component. \value FieldContact Field representing the CONTACT component. \value FieldComment Field representing the COMMENT component. \value FieldUid Field representing the UID component. \value FieldUnknown Something changed. Always set when you use the assignment operator. \value FieldUrl Field representing the URL component. \value FieldConferences Field representing the CONFERENCE component. \value FieldColor Field representing the COLOR component. */ enum Field { FieldDtStart, FieldDtEnd, FieldLastModified, FieldDescription, FieldSummary, FieldLocation, FieldCompleted, FieldPercentComplete, FieldDtDue, FieldCategories, FieldRelatedTo, FieldRecurrence, FieldAttachment, FieldSecrecy, FieldStatus, FieldTransparency, FieldResources, FieldPriority, FieldGeoLatitude, FieldGeoLongitude, FieldRecurrenceId, FieldAlarms, FieldSchedulingId, FieldAttendees, FieldOrganizer, FieldCreated, FieldRevision, FieldDuration, FieldContact, FieldComment, FieldUid, FieldUnknown, FieldUrl, FieldConferences, FieldColor, }; /*! \class KCalendarCore::IncidenceBase::IncidenceObserver \inmodule KCalendarCore \brief The IncidenceObserver class. */ class KCALENDARCORE_EXPORT IncidenceObserver { public: /*! Destroys the IncidenceObserver. */ virtual ~IncidenceObserver(); /*! The IncidenceObserver interface. This function is called before any changes are made. \a uid is the string containing the incidence \l uid. \a recurrenceId is possible recurrenceid of incidence. */ virtual void incidenceUpdate(const QString &uid, const QDateTime &recurrenceId) = 0; /*! The IncidenceObserver interface. This function is called after changes are completed. \a uid is the string containing the incidence \l uid. \a recurrenceId is possible recurrenceid of incidence. */ virtual void incidenceUpdated(const QString &uid, const QDateTime &recurrenceId) = 0; }; IncidenceBase() = delete; /*! Constructs an empty IncidenceBase. \a p (non-null) a Private data object provided by the instantiated class (Event, Todo, Journal, FreeBusy). It takes ownership of the object. */ KCALENDARCORE_NO_EXPORT explicit IncidenceBase(IncidenceBasePrivate *p); /*! Destroys the IncidenceBase. */ ~IncidenceBase() override; /*! Assignment operator. All data belonging to derived classes are also copied. \sa assign(). The caller guarantees that both types match. \code if ( i1.type() == i2.type() ) { i1 = i2; } else { qCDebug(KCALCORE_LOG) << "Invalid assignment!"; } \endcode Dirty field FieldUnknown will be set. \a other is the IncidenceBase to assign. */ IncidenceBase &operator=(const IncidenceBase &other); /*! Compares this with IncidenceBase \a ib for equality. All data belonging to derived classes are also compared. \sa equals(). \a ib is the IncidenceBase to compare against. Returns true if the incidences are equal; false otherwise. */ bool operator==(const IncidenceBase &ib) const; /*! Compares this with IncidenceBase \a ib for inequality. \a ib is the IncidenceBase to compare against. Returns true if the incidences are /not/ equal; false otherwise. */ bool operator!=(const IncidenceBase &ib) const; /*! Accept IncidenceVisitor. A class taking part in the visitor mechanism has to provide this implementation: \code bool accept(Visitor &v) { return v.visit(this); } \endcode \a v is a reference to a Visitor object. \a incidence is a valid IncidenceBase object for visiting. */ virtual bool accept(Visitor &v, const IncidenceBase::Ptr &incidence); /*! Returns the incidence type. */ virtual IncidenceType type() const = 0; /*! Prints the type of incidence as a string. */ virtual QByteArray typeStr() const = 0; /*! Sets the unique id for the incidence to \a uid. \a uid is the string containing the incidence \l uid. \sa uid() */ void setUid(const QString &uid); /*! Returns the unique id (\l uid) for the incidence. \sa setUid() */ Q_REQUIRED_RESULT QString uid() const; /*! Returns the uri for the incidence, of form urn:x-ical:\ */ Q_REQUIRED_RESULT QUrl uri() const; /*! Sets the time the incidence was last modified to \a lm. It is stored as a UTC date/time. \a lm is the QDateTime when the incidence was last modified. \sa lastModified() */ virtual void setLastModified(const QDateTime &lm); /*! Returns the time the incidence was last modified. \sa setLastModified() */ Q_REQUIRED_RESULT QDateTime lastModified() const; /*! Sets the organizer for the incidence. \a organizer is a non-null Person to use as the incidence \l organizer. \sa organizer(), setOrganizer(const QString &) */ void setOrganizer(const Person &organizer); /*! Sets the incidence organizer to any string \a organizer. \a organizer is a string to use as the incidence \l organizer. \sa organizer() */ void setOrganizer(const QString &organizer); /*! Returns the Person associated with this incidence. If no Person was set through setOrganizer(), a default Person() is returned. \sa setOrganizer() */ Person organizer() const; /*! Sets readonly status. \a readOnly if set, the incidence is read-only; else the incidence can be modified. \sa isReadOnly(). */ virtual void setReadOnly(bool readOnly); /*! Returns true the object is read-only; false otherwise. \sa setReadOnly() */ Q_REQUIRED_RESULT bool isReadOnly() const; /*! Sets the incidence's starting date/time with a QDateTime. \a dtStart is the incidence start date/time. \sa dtStart(). */ virtual void setDtStart(const QDateTime &dtStart); /*! Returns an incidence's starting date/time as a QDateTime. \sa setDtStart(). */ virtual QDateTime dtStart() const; /*! Sets the incidence duration. \a duration the incidence duration \sa duration() */ virtual void setDuration(const Duration &duration); /*! Returns the length of the incidence duration. \sa setDuration() */ Q_REQUIRED_RESULT Duration duration() const; /*! Sets if the incidence has a duration. \a hasDuration true if the incidence has a duration; false otherwise. \sa hasDuration() */ void setHasDuration(bool hasDuration); /*! Returns true if the incidence has a duration; false otherwise. \sa setHasDuration() */ Q_REQUIRED_RESULT bool hasDuration() const; /*! Returns true or false depending on whether the incidence is all-day. i.e. has a date but no time attached to it. \sa setAllDay() */ Q_REQUIRED_RESULT bool allDay() const; /*! Sets whether the incidence is all-day, i.e. has a date but no time attached to it. \a allDay sets whether the incidence is all-day. \sa allDay() */ virtual void setAllDay(bool allDay); /*! Shift the times of the incidence so that they appear at the same clock time as before but in a new time zone. The shift is done from a viewing time zone rather than from the actual incidence time zone. For example, shifting an incidence whose start time is 09:00 America/New York, using an old viewing time zone (\a oldZone) of Europe/London, to a new time zone (\a newZone) of Europe/Paris, will result in the time being shifted from 14:00 (which is the London time of the incidence start) to 14:00 Paris time. \a oldZone the time zone which provides the clock times \a newZone the new time zone */ virtual void shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone); /*! Adds a comment to the incidence. Does not add a linefeed character; simply appends the text as specified. \a comment is the QString containing the comment to add. \sa removeComment(). */ void addComment(const QString &comment); /*! Removes a comment from the incidence. Removes the first comment whose string is an exact match for the specified string in \a comment. \a comment is the QString containing the comment to remove. Returns true if match found, false otherwise. \sa addComment(). */ Q_REQUIRED_RESULT bool removeComment(const QString &comment); /*! Deletes all incidence comments. */ void clearComments(); /*! Returns all incidence comments as a list of strings. */ Q_REQUIRED_RESULT QStringList comments() const; /*! Adds a contact to thieincidence. Does not add a linefeed character; simply appends the text as specified. \a contact is the QString containing the contact to add. \sa removeContact(). */ void addContact(const QString &contact); /*! Removes a contact from the incidence. Removes the first contact whose string is an exact match for the specified string in \a contact. \a contact is the QString containing the contact to remove. Returns true if match found, false otherwise. \sa addContact(). */ Q_REQUIRED_RESULT bool removeContact(const QString &contact); /*! Deletes all incidence contacts. */ void clearContacts(); /*! Returns all incidence contacts as a list of strings. */ Q_REQUIRED_RESULT QStringList contacts() const; /*! Add Attendee to this incidence. \a attendee is the attendee to add \a doUpdate If true the Observers are notified, if false they are not. */ void addAttendee(const Attendee &attendee, bool doUpdate = true); /*! Removes all attendees from the incidence. */ void clearAttendees(); /*! Set the attendees of this incidence. This replaces all previously set attendees, unlike addAttendee. \a attendees is a list of attendees. \a doUpdate If true the Observers are notified, if false they are not. */ void setAttendees(const Attendee::List &attendees, bool doUpdate = true); /*! Returns a list of incidence attendees. All pointers in the list are valid. */ Q_REQUIRED_RESULT Attendee::List attendees() const; /*! Returns the number of incidence attendees. */ Q_REQUIRED_RESULT int attendeeCount() const; /*! Returns the attendee with the specified email address. \a email is a QString containing an email address of the form "FirstName LastName ". \sa attendeeByMails(), attendeeByUid(). */ Attendee attendeeByMail(const QString &email) const; /*! Returns the first incidence attendee with one of the specified email addresses. \a emails is a list of QStrings containing email addresses of the form "FirstName LastName ". \a email is a QString containing a single email address to search in addition to the list specified in \a emails. \sa attendeeByMail(), attendeeByUid(). */ Attendee attendeeByMails(const QStringList &emails, const QString &email = QString()) const; /*! Returns the incidence attendee with the specified attendee UID. \a uid is a QString containing an attendee UID. \sa attendeeByMail(), attendeeByMails(). */ Attendee attendeeByUid(const QString &uid) const; /*! Sets the incidences url. This property can be used to point to a more dynamic rendition of the incidence. I.e. a website related to the incidence. \a url is the URL of the incidence. \sa url() \since 4.12 */ void setUrl(const QUrl &url); /*! Returns the url. Returns incidences url value \sa setUrl() \since 4.12 */ Q_REQUIRED_RESULT QUrl url() const; /*! Register observer. The observer is notified when the observed object changes. \a observer is a pointer to an IncidenceObserver object that will be watching this incidence. \sa unRegisterObserver() */ void registerObserver(IncidenceObserver *observer); /*! Unregister observer. It isn't notified anymore about changes. \a observer is a pointer to an IncidenceObserver object that will be watching this incidence. \sa registerObserver(). */ void unRegisterObserver(IncidenceObserver *observer); /*! Call this to notify the observers after the IncidenceBase object will be changed. */ void update(); /*! Call this to notify the observers after the IncidenceBase object has changed. */ void updated(); /*! Call this when a group of updates is going to be made. This suppresses change notifications until endUpdates() is called, at which point updated() will automatically be called. */ void startUpdates(); /*! Call this when a group of updates is complete, to notify observers that the instance has changed. This should be called in conjunction with startUpdates(). */ void endUpdates(); /*! Returns a date/time corresponding to the specified DateTimeRole. \a role is a DateTimeRole. */ virtual QDateTime dateTime(DateTimeRole role) const = 0; /*! Sets the date/time corresponding to the specified DateTimeRole. \a dateTime is QDateTime value to set. \a role is a DateTimeRole. */ virtual void setDateTime(const QDateTime &dateTime, DateTimeRole role) = 0; /*! Returns the Akonadi specific sub MIME type of a KCalendarCore::IncidenceBase item, e.g. getting "application/x-vnd.akonadi.calendar.event" for a KCalendarCore::Event. */ virtual QLatin1String mimeType() const = 0; /*! Returns the incidence recurrenceId. */ virtual QDateTime recurrenceId() const; /*! Returns a QSet with all Fields that were changed since the incidence was created or resetDirtyFields() was called. \sa resetDirtyFields() */ QSet dirtyFields() const; /*! Sets which fields are dirty. \sa dirtyFields() \since 4.8 */ void setDirtyFields(const QSet &); /*! Resets dirty fields. \sa dirtyFields() */ void resetDirtyFields(); /*! * Constant that identifies KCalendarCore data in a binary stream. * * \since 4.12 */ Q_REQUIRED_RESULT static quint32 magicSerializationIdentifier(); protected: /*! Marks Field \a field as dirty. \a field is the Field type to mark as dirty. \sa dirtyFields() */ void setFieldDirty(IncidenceBase::Field field); /*! \reimp */ void customPropertyUpdate() override; /*! \reimp */ void customPropertyUpdated() override; IncidenceBase(const IncidenceBase &) = delete; /*! Constructs an IncidenceBase as a copy of another IncidenceBase object. \a ib is the IncidenceBase to copy. \a p (non-null) a Private data object provided by the instantiated class (Event, Todo, Journal, FreeBusy). It takes ownership of the object. */ KCALENDARCORE_NO_EXPORT IncidenceBase(const IncidenceBase &ib, IncidenceBasePrivate *p); /*! Provides polymorfic comparison for equality. Only called by IncidenceBase::operator==() which guarantees that \a incidenceBase is of the right type. \a incidenceBase is the IncidenceBase to compare against. Returns true if the incidences are equal; false otherwise. */ virtual bool equals(const IncidenceBase &incidenceBase) const; /*! Provides polymorphic assignment. \a other is the IncidenceBase to assign. */ virtual IncidenceBase &assign(const IncidenceBase &other); /*! * Sub-type specific serialization. * * \a out is the output data stream * */ virtual void serialize(QDataStream &out) const; /*! * Sub-type specific deserialization. * * \a in is the input data stream * */ virtual void deserialize(QDataStream &in); enum VirtualHook {}; /*! Standard trick to add virtuals later. \a id is any integer unique to this class which we will use to identify the method to be called. \a data is a pointer to some glob of data, typically a struct. */ virtual void virtual_hook(VirtualHook id, void *data) = 0; /*! Identifies a read-only incidence. */ bool mReadOnly; Q_DECLARE_PRIVATE(IncidenceBase) protected: IncidenceBasePrivate *const d_ptr; private: friend KCALENDARCORE_EXPORT QDataStream &operator<<(QDataStream &stream, const KCalendarCore::IncidenceBase::Ptr &); friend KCALENDARCORE_EXPORT QDataStream &operator>>(QDataStream &stream, KCalendarCore::IncidenceBase::Ptr &); }; /*! * Compare two QDateTimes \a dt1 and \a dt2 for extended equality. * * QDateTime::operator==() in Qt 5.12 returns true if its operands represent * the same instant in time, regardless of their time zones or TimeSpecs (and * contrary to the documentation). This function returns true if and only if * their times, time zones, and TimeSpecs are equal, or both are invalid(). * * \since 5.93 */ KCALENDARCORE_EXPORT bool identical(const QDateTime &dt1, const QDateTime &dt2); /*! * Incidence serializer. * * \since 4.12 */ KCALENDARCORE_EXPORT QDataStream &operator<<(QDataStream &out, const KCalendarCore::IncidenceBase::Ptr &); /*! * Incidence deserializer. * * \since 4.12 */ KCALENDARCORE_EXPORT QDataStream &operator>>(QDataStream &in, KCalendarCore::IncidenceBase::Ptr &); } Q_DECLARE_METATYPE(KCalendarCore::IncidenceBase *) Q_DECLARE_METATYPE(KCalendarCore::IncidenceBase::Ptr) #endif