kde-playground/kdepimlibs/kalarmcal/karecurrence.h
2015-04-14 21:49:29 +00:00

520 lines
22 KiB
C++

/*
* 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 <djarvie@kde.org>
*
* 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 <kcalcore/recurrencerule.h>
#include <kcalcore/duration.h>
namespace KCalCore { class Recurrence; }
#else
#include <kcal/recurrencerule.h>
#include <kcal/duration.h>
namespace KCal { class Recurrence; }
#endif
#include <QtCore/QBitArray>
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 <djarvie@kde.org>
*/
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<KCalCore::RecurrenceRule::WDayPos> monthPositions() const;
#else
QList<KCal::RecurrenceRule::WDayPos> monthPositions() const;
#endif
/** Returns list of day numbers of a month. */
// Emulate old behavior
QList<int> 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<int> 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<int> 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<int> 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<KCalCore::RecurrenceRule::WDayPos> yearPositions() const;
#else
QList<KCal::RecurrenceRule::WDayPos> 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: