/* * karecurrence.h - recurrence with special yearly February 29th handling * This file is part of kalarmcal library, which provides access to KAlarm * calendar data. * Copyright © 2005-2012 by David Jarvie * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef KALARM_KARECURRENCE_H #define KALARM_KARECURRENCE_H #include "kalarmcal_export.h" #ifndef KALARMCAL_USE_KRESOURCES #include #include namespace KCalCore { class Recurrence; } #else #include #include namespace KCal { class Recurrence; } #endif #include namespace KAlarmCal { /** * @short Represents recurrences for KAlarm. * * This class represents the restricted range of recurrence types which are * handled by KAlarm, and translates between these and the libkcalcore * Recurrence class. In particular, it handles yearly recurrences on 29th * February in non-leap years specially: * * KARecurrence allows annual 29th February recurrences to fall on 28th * February or 1st March, or not at all, in non-leap years. It allows such * 29th February recurrences to be combined with the 29th of other months in * a simple way, represented simply as the 29th of multiple months including * February. For storage in the libkcalcore calendar, the 29th day of the month * recurrence for other months is combined with a last-day-of-February or a * 60th-day-of-the-year recurrence rule, thereby conforming to RFC2445. * * @author David Jarvie */ class KALARMCAL_EXPORT KARecurrence { public: /** The recurrence's period type. * This is a subset of the possible KCalCore recurrence types. */ enum Type { NO_RECUR, //!< does not recur MINUTELY, //!< at an hours/minutes interval DAILY, //!< daily WEEKLY, //!< weekly, on specified weekdays MONTHLY_POS, //!< monthly, on specified weekdays in a specified week of the month MONTHLY_DAY, //!< monthly, on a specified day of the month ANNUAL_DATE, //!< yearly, on a specified date in each of the specified months ANNUAL_POS //!< yearly, on specified weekdays in the specified weeks of the specified months }; /** When annual February 29th recurrences should occur in non-leap years. */ enum Feb29Type { Feb29_Feb28, //!< occurs on 28 February in non-leap years Feb29_Mar1, //!< occurs on 1 March in non-leap years Feb29_None //!< does not occur in non-leap years }; KARecurrence(); #ifndef KALARMCAL_USE_KRESOURCES KARecurrence(const KCalCore::Recurrence& r); #else KARecurrence(const KCal::Recurrence& r); #endif KARecurrence(const KARecurrence& r); ~KARecurrence(); /** * Assignment operator. * @param r the recurrence which will be assigned to this. */ KARecurrence& operator=(const KARecurrence& r); /** * Comparison operator for equality. * @param r instance to compare with * @return true if recurrences are the same, false otherwise */ bool operator==(const KARecurrence& r) const; /** * Comparison operator for inequality. * @param r instance to compare with * @return true if recurrences are the different, false if the same */ bool operator!=(const KARecurrence& r) const { return !operator==(r); } /** Initialise the recurrence from an iCalendar RRULE string. * @return true if successful, false if an error occurred. */ bool set(const QString& icalRRULE); /** Set up a KARecurrence from recurrence parameters, using the start date to * determine the recurrence day/month as appropriate. * Annual 29th February recurrences in non-leap years will be handled * according to the default set by setDefaultFeb29Type(). * Only a restricted subset of recurrence types is allowed: minutely, daily, * weekly, monthly, yearly or none. * @return true if successful. */ bool set(Type t, int freq, int count, const KDateTime& start, const KDateTime& end); /** Set up a KARecurrence from recurrence parameters, using the start date to * determine the recurrence day/month as appropriate, and specifying how * annual 29th February recurrences in non-leap years should be handled. * @return true if successful. */ bool set(Type t, int freq, int count, const KDateTime& start, const KDateTime& end, Feb29Type f29); /** Set up a KARecurrence from recurrence parameters. * Annual 29th February recurrences in non-leap years will be handled * according to the default set by setDefaultFeb29Type(). * Only a restricted subset of recurrence types is allowed: minutely, daily, * weekly, monthly, yearly or none. * @return true if successful. */ #ifndef KALARMCAL_USE_KRESOURCES bool init(KCalCore::RecurrenceRule::PeriodType t, int freq, int count, const KDateTime& start, const KDateTime& end); #else bool init(KCal::RecurrenceRule::PeriodType t, int freq, int count, const KDateTime& start, const KDateTime& end); #endif /** Set up a KARecurrence from recurrence parameters, specifying how * annual 29th February recurrences in non-leap years should be handled. * Only a restricted subset of recurrence types is allowed: minutely, daily, * weekly, monthly, yearly or none. * @return true if successful. */ #ifndef KALARMCAL_USE_KRESOURCES bool init(KCalCore::RecurrenceRule::PeriodType t, int freq, int count, const KDateTime& start, const KDateTime& end, Feb29Type f29); #else bool init(KCal::RecurrenceRule::PeriodType t, int freq, int count, const KDateTime& start, const KDateTime& end, Feb29Type f29); #endif /** Removes all recurrence and exception rules and dates. */ void clear(); /** Initialise a KCalCore::Recurrence to be the same as this instance. * Additional recurrence rules are created as necessary if it recurs on Feb 29th. */ #ifndef KALARMCAL_USE_KRESOURCES void writeRecurrence(KCalCore::Recurrence&) const; #else void writeRecurrence(KCal::Recurrence&) const; #endif /** Convert the recurrence to KARecurrence types. * Must be called after presetting with a KCalCore::Recurrence. * - Convert hourly recurrences to minutely. * - Remove all but the first day in yearly date recurrences. * - Check for yearly recurrences falling on February 29th and adjust them as * necessary. A 29th of the month rule can be combined with either a 60th day * of the year rule or a last day of February rule. */ void fix(); /** Return the start date/time of the recurrence (Time for all-day recurrences will be 0:00). * @return the current start/time of the recurrence. */ KDateTime startDateTime() const; /** Return the start date/time of the recurrence */ QDate startDate() const; /** Set the recurrence start date/time, and optionally set it to all-day. * @param dt start date/time. * @param dateOnly if true, sets the recurrence to all-day. */ void setStartDateTime(const KDateTime& dt, bool dateOnly); /** Return the date/time of the last recurrence. */ KDateTime endDateTime() const; /** Return the date of the last recurrence. */ QDate endDate() const; /** Sets the date of the last recurrence. The end time is set to the recurrence start time. * @param endDate the ending date after which to stop recurring. If the * recurrence is not all-day, the end time will be 23:59. */ void setEndDate(const QDate& endDate); /** Sets the date and time of the last recurrence. * @param endDateTime the ending date/time after which to stop recurring. */ void setEndDateTime(const KDateTime& endDateTime); /** Set whether the recurrence has no time, just a date. * All-day means -- according to rfc2445 -- that the event has no time * associated. * N.B. This property is derived by default from whether setStartDateTime() is * called with a date-only or date/time parameter. * @return whether the recurrence has a time (false) or it is just a date (true). */ bool allDay() const; /** Set if recurrence is read-only or can be changed. */ void setRecurReadOnly(bool readOnly); /** Returns true if the recurrence is read-only, or false if it can be changed. */ bool recurReadOnly() const; /** Returns whether the event recurs at all. */ bool recurs() const; /** Returns week day mask (bit 0 = Monday). */ QBitArray days() const; // Emulate the old behavior /** Returns list of day positions in months. */ #ifndef KALARMCAL_USE_KRESOURCES QList monthPositions() const; #else QList monthPositions() const; #endif /** Returns list of day numbers of a month. */ // Emulate old behavior QList monthDays() const; /** Returns the day numbers within a yearly recurrence. * @return the days of the year for the event. E.g. if the list contains * 60, this means the recurrence happens on day 60 of the year, i.e. * on Feb 29 in leap years and March 1 in non-leap years. */ QList yearDays() const; /** Returns the dates within a yearly recurrence. * @return the days of the month for the event. E.g. if the list contains * 13, this means the recurrence happens on the 13th of the month. * The months for the recurrence can be obtained through * yearlyMonths(). If this list is empty, the month of the start * date is used. */ QList yearDates() const; /** Returns the months within a yearly recurrence. * @return the months for the event. E.g. if the list contains * 11, this means the recurrence happens in November. * The days for the recurrence can be obtained either through * yearDates() if they are given as dates within the month or * through yearlyPositions() if they are given as positions within the * month. If none is specified, the date of the start date is used. */ QList yearMonths() const; /** Returns the positions within a yearly recurrence. * @return the positions for the event, either within a month (if months * are set through addYearlyMonth()) or within the year. * E.g. if the list contains {Pos=3, Day=5}, this means the third * friday. If a month is set this position is understoodas third * Friday in the given months, otherwise as third Friday of the * year. */ #ifndef KALARMCAL_USE_KRESOURCES QList yearPositions() const; #else QList yearPositions() const; #endif /** Adds days to the weekly day recurrence list. * @param days a 7 bit array indicating which days on which to recur (bit 0 = Monday). */ void addWeeklyDays(const QBitArray& days); /** Adds day number of year within a yearly recurrence. * By default infinite recurrence is used. To set an end date use the * method setEndDate and to set the number of occurrences use setDuration. * @param day the day of the year for the event. E.g. if day is 60, this * means Feb 29 in leap years and March 1 in non-leap years. */ void addYearlyDay(int day); /** Adds date within a yearly recurrence. The month(s) for the recurrence * can be specified with addYearlyMonth(), otherwise the month of the * start date is used. * * By default infinite recurrence is used. To set an end date use the * method setEndDate and to set the number of occurrences use setDuration. * @param date the day of the month for the event */ void addYearlyDate(int date); /** Adds month in yearly recurrence. You can specify specific day numbers * within the months (by calling addYearlyDate()) or specific day positions * within the month (by calling addYearlyPos). * @param month the month in which the event will recur. */ void addYearlyMonth(short month); /** Adds position within month/year within a yearly recurrence. If months * are specified (via addYearlyMonth()), the parameters are understood as * position within these months, otherwise within the year. * * By default infinite recurrence is used. * To set an end date use the method setEndDate and to set the number * of occurrences use setDuration. * @param pos the position in the month/year for the recurrence, with valid * values being 1 to 53 and -1 to -53 (53 weeks max in a year). * @param days the days for the position to recur on (bit 0 = Monday). * Example: pos = 2, and bits 0 and 2 are set in days * If months are specified (via addYearlyMonth), e.g. March, the rule is * to repeat every year on the 2nd Monday and Wednesday of March. * If no months are specified, the fule is to repeat every year on the * 2nd Monday and Wednesday of the year. */ void addYearlyPos(short pos, const QBitArray& days); /** Adds a position (e.g. first monday) to the monthly recurrence rule. * @param pos the position in the month for the recurrence, with valid * values being 1-5 (5 weeks max in a month). * @param days the days for the position to recur on (bit 0 = Monday). * Example: pos = 2, and bits 0 and 2 are set in days: * the rule is to repeat every 2nd Monday and Wednesday in the month. */ void addMonthlyPos(short pos, const QBitArray& days); void addMonthlyPos(short pos, ushort day); /** Adds a date (e.g. the 15th of each month) to the monthly day * recurrence list. * @param day the date in the month to recur. */ void addMonthlyDate(short day); /** Get the next time the recurrence occurs, strictly after a specified time. */ KDateTime getNextDateTime(const KDateTime& preDateTime) const; /** Get the previous time the recurrence occurred, strictly before a specified time. */ KDateTime getPreviousDateTime(const KDateTime& afterDateTime) const; /** Return whether the event will recur on the specified date. * The start date only returns true if it matches the recurrence rules. */ bool recursOn(const QDate&, const KDateTime::Spec&) const; /** * Returns true if the date/time specified is one at which the event will * recur. Times are rounded down to the nearest minute to determine the result. * * @param dt is the date/time to check. */ bool recursAt(const KDateTime& dt) const; /** Returns a list of the times on the specified date at which the * recurrence will occur. The returned times should be interpreted in the * context of @p timeSpec. * @param date the date for which to find the recurrence times * @param timeSpec time specification for @p date */ #ifndef KALARMCAL_USE_KRESOURCES KCalCore::TimeList recurTimesOn(const QDate& date, const KDateTime::Spec& timeSpec) const; #else KCal::TimeList recurTimesOn(const QDate& date, const KDateTime::Spec& timeSpec) const; #endif /** Returns a list of all the times at which the recurrence will occur * between two specified times. * * There is a (large) maximum limit to the number of times returned. If due to * this limit the list is incomplete, this is indicated by the last entry being * set to an invalid KDateTime value. If you need further values, call the * method again with a start time set to just after the last valid time returned. * * @param start inclusive start of interval * @param end inclusive end of interval * @return list of date/time values */ #ifndef KALARMCAL_USE_KRESOURCES KCalCore::DateTimeList timesInInterval(const KDateTime& start, const KDateTime& end) const; #else KCal::DateTimeList timesInInterval(const KDateTime& start, const KDateTime& end) const; #endif /** Returns frequency of recurrence, in terms of the recurrence time period type. */ int frequency() const; /** Sets the frequency of recurrence, in terms of the recurrence time period type. */ void setFrequency(int freq); /** * Returns -1 if the event recurs infinitely, 0 if the end date is set, * otherwise the total number of recurrences, including the initial occurrence. */ int duration() const; /** Sets the total number of times the event is to occur, including both the * first and last. */ void setDuration(int duration); /** Returns the number of recurrences up to and including the date/time specified. * @warning This function can be very time consuming - use it sparingly! */ int durationTo(const KDateTime& dt) const; /** Returns the number of recurrences up to and including the date specified. * @warning This function can be very time consuming - use it sparingly! */ int durationTo(const QDate& date) const; /** Return the longest interval between recurrences. * @return 0 if it never recurs. */ #ifndef KALARMCAL_USE_KRESOURCES KCalCore::Duration longestInterval() const; #else KCal::Duration longestInterval() const; #endif /** Return the interval between recurrences, if the interval between * successive occurrences does not vary. * @return 0 if recurrence does not occur at fixed intervals. */ #ifndef KALARMCAL_USE_KRESOURCES KCalCore::Duration regularInterval() const; #else KCal::Duration regularInterval() const; #endif #ifndef KALARMCAL_USE_KRESOURCES KCalCore::DateTimeList exDateTimes() const; KCalCore::DateList exDates() const; void setExDateTimes(const KCalCore::DateTimeList& exdates); void setExDates(const KCalCore::DateList& exdates); #else KCal::DateTimeList exDateTimes() const; KCal::DateList exDates() const; void setExDateTimes(const KCal::DateTimeList& exdates); void setExDates(const KCal::DateList& exdates); #endif void addExDateTime(const KDateTime& exdate); void addExDate(const QDate& exdate); /** * Shift the times of the recurrence 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 recurrence time zone. * * For example, shifting a recurrence whose start time is 09:00 America/New York, * using an old viewing time zone (@p oldSpec) of Europe/London, to a new time * zone (@p newSpec) of Europe/Paris, will result in the time being shifted * from 14:00 (which is the London time of the recurrence start) to 14:00 Paris * time. * * @param oldSpec the time specification which provides the clock times * @param newSpec the new time specification */ void shiftTimes(const KDateTime::Spec& oldSpec, const KDateTime::Spec& newSpec); #ifndef KALARMCAL_USE_KRESOURCES KCalCore::RecurrenceRule* defaultRRuleConst() const; #else KCal::RecurrenceRule* defaultRRuleConst() const; #endif /** Return the recurrence's period type. */ Type type() const; /** Return the type of a recurrence rule. */ #ifndef KALARMCAL_USE_KRESOURCES static Type type(const KCalCore::RecurrenceRule*); #else static Type type(const KCal::RecurrenceRule*); #endif /** Check if the recurrence rule is a daily rule with or without BYDAYS specified. */ #ifndef KALARMCAL_USE_KRESOURCES static bool dailyType(const KCalCore::RecurrenceRule*); #else static bool dailyType(const KCal::RecurrenceRule*); #endif /** Return when 29th February annual recurrences should occur in non-leap years. */ Feb29Type feb29Type() const; /** Return the default way that 29th February annual recurrences should occur * in non-leap years. * @see setDefaultFeb29Type(). */ static Feb29Type defaultFeb29Type(); /** Set the default way that 29th February annual recurrences should occur * in non-leap years. * @see defaultFeb29Type(). */ static void setDefaultFeb29Type(Feb29Type t); private: //@cond PRIVATE class Private; Private* const d; //@endcond }; } // namespace KAlarmCal #endif // KALARM_KARECURRENCE_H // vim: et sw=4: