You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
13 KiB
344 lines
13 KiB
/*
|
|
This file is part of libkcal.
|
|
|
|
Copyright (c) 1998 Preston Brown <pbrown@kde.org>
|
|
Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
|
|
Copyright (c) 2002 David Jarvie <software@astrojar.org.uk>
|
|
Copyright (c) 2005, Reinhold Kainhofer <reinhold@kainhofer.com>
|
|
|
|
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 KCAL_RECURRENCERULE_H
|
|
#define KCAL_RECURRENCERULE_H
|
|
|
|
#include <qdatetime.h>
|
|
#include <libkcal/listbase.h>
|
|
|
|
#include "libkcal_export.h"
|
|
|
|
template <class T>
|
|
Q_INLINE_TEMPLATES void qSortUnique( QValueList<T> &lst )
|
|
{
|
|
qHeapSort( lst );
|
|
if ( lst.isEmpty() ) return;
|
|
// Remove all duplicates from the times list
|
|
// TODO: Make this more efficient!
|
|
QValueListIterator<T> it = lst.begin();
|
|
T last = *it;
|
|
++it;
|
|
T newlast;
|
|
while ( it != lst.end() ) {
|
|
newlast = (*it);
|
|
if ( newlast == last ) it = lst.remove( it );
|
|
else {
|
|
last = newlast;
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
namespace KCal {
|
|
|
|
typedef QValueList<QDateTime> DateTimeList;
|
|
typedef QValueList<QDate> DateList;
|
|
typedef QValueList<QTime> TimeList;
|
|
|
|
|
|
|
|
|
|
/**
|
|
This class represents a recurrence rule for a calendar incidence.
|
|
*/
|
|
class LIBKCAL_EXPORT RecurrenceRule
|
|
{
|
|
public:
|
|
class Observer {
|
|
public:
|
|
virtual ~Observer() {}
|
|
/** This method will be called on each change of the recurrence object */
|
|
virtual void recurrenceChanged( RecurrenceRule * ) = 0;
|
|
};
|
|
typedef ListBase<RecurrenceRule> List;
|
|
/** enum for describing the frequency how an event recurs, if at all. */
|
|
enum PeriodType { rNone = 0,
|
|
rSecondly, rMinutely, rHourly,
|
|
rDaily, rWeekly, rMonthly, rYearly
|
|
};
|
|
/** structure for describing the n-th weekday of the month/year. */
|
|
class WDayPos {
|
|
public:
|
|
WDayPos( int ps = 0 , short dy = 0 ) : mDay(dy), mPos(ps) {}
|
|
short day() const { return mDay; }
|
|
int pos() const { return mPos; }
|
|
void setDay( short dy ) { mDay = dy; }
|
|
void setPos( int ps ) { mPos = ps; }
|
|
|
|
bool operator==( const RecurrenceRule::WDayPos &pos2 ) const {
|
|
return ( mDay == pos2.mDay ) && ( mPos == pos2.mPos );
|
|
}
|
|
protected:
|
|
short mDay; // Weekday, 1=monday, 7=sunday
|
|
int mPos; // week of the day (-1 for last, 1 for first, 0 for all weeks)
|
|
// Bounded by -366 and +366, 0 means all weeks in that period
|
|
};
|
|
|
|
RecurrenceRule( /*Incidence *parent, int compatVersion = 0*/ );
|
|
RecurrenceRule(const RecurrenceRule&);
|
|
~RecurrenceRule();
|
|
|
|
bool operator==( const RecurrenceRule& ) const;
|
|
bool operator!=( const RecurrenceRule& r ) const { return !operator==(r); }
|
|
RecurrenceRule &operator=(const RecurrenceRule&);
|
|
|
|
// Incidence *parent() const { return mParent; }
|
|
|
|
|
|
/** Set if recurrence is read-only or can be changed. */
|
|
void setReadOnly(bool readOnly) { mIsReadOnly = readOnly; }
|
|
/** Returns true if the recurrence is read-only, or false if it can be changed. */
|
|
bool isReadOnly() const { return mIsReadOnly; }
|
|
|
|
|
|
/** Returns the event's recurrence status. See the enumeration at the top
|
|
* of this file for possible values. */
|
|
bool doesRecur() const { return mPeriod!=rNone; }
|
|
void setRecurrenceType( PeriodType period );
|
|
PeriodType recurrenceType() const { return mPeriod; }
|
|
/** Turns off recurrence for the event. */
|
|
void clear();
|
|
|
|
|
|
/** Returns frequency of recurrence, in terms of the recurrence time period type. */
|
|
uint frequency() const { return mFrequency; }
|
|
/** Sets the frequency of recurrence, in terms of the recurrence time period type. */
|
|
void setFrequency( int freq );
|
|
|
|
|
|
/** Return the start of the recurrence */
|
|
QDateTime startDt() const { return mDateStart; }
|
|
/** Set start of recurrence, as a date and time. */
|
|
void setStartDt(const QDateTime &start);
|
|
|
|
/** Returns whether the start date has no time associated. Floating
|
|
means -- according to rfc2445 -- that the event has no time associate. */
|
|
bool doesFloat() const { return mFloating; }
|
|
/** Sets whether the dtstart is a floating time (i.e. has no time attached) */
|
|
void setFloats( bool floats );
|
|
|
|
|
|
/** Returns the date and time of the last recurrence.
|
|
* An invalid date is returned if the recurrence has no end.
|
|
* @param result if non-null, *result is updated to true if successful,
|
|
* or false if there is no recurrence.
|
|
*/
|
|
QDateTime endDt( bool* result = 0 ) const;
|
|
/** Sets the date and time of the last recurrence.
|
|
* @param endDateTime the ending date/time after which to stop recurring. */
|
|
void setEndDt(const QDateTime &endDateTime);
|
|
|
|
|
|
/**
|
|
* 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 { return mDuration; }
|
|
/** 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 specified. */
|
|
// int durationTo(const QDate &) const;
|
|
/** Returns the number of recurrences up to and including the date/time specified. */
|
|
int durationTo(const QDateTime &) const;
|
|
/** Returns the number of recurrences up to and including the date specified. */
|
|
int durationTo( const QDate &date ) const { return durationTo( QDateTime( date, QTime( 23, 59, 59 ) ) ); }
|
|
|
|
|
|
|
|
/** Returns true if the date specified is one on which the event will
|
|
* recur. The start date returns true only if it actually matches the rule. */
|
|
bool recursOn( const QDate &qd ) 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.
|
|
* The start date/time returns true only if it actually matches the rule. */
|
|
bool recursAt( const QDateTime & ) const;
|
|
/** Returns true if the date matches the rules. It does not necessarily
|
|
mean that this is an actual occurrence. In particular, the method does
|
|
not check if the date is after the end date, or if the frequency interval
|
|
matches */
|
|
bool dateMatchesRules( const QDateTime &qdt ) const;
|
|
|
|
|
|
/** Returns a list of the times on the specified date at which the
|
|
* recurrence will occur.
|
|
* @param date the date for which to find the recurrence times.
|
|
*/
|
|
TimeList recurTimesOn( const QDate &date ) const;
|
|
|
|
|
|
/** Returns the date and time of the next recurrence, after the specified date/time.
|
|
* If the recurrence has no time, the next date after the specified date is returned.
|
|
* @param preDateTime the date/time after which to find the recurrence.
|
|
* @return date/time of next recurrence, or invalid date if none.
|
|
*/
|
|
QDateTime getNextDate( const QDateTime& preDateTime ) const;
|
|
/** Returns the date and time of the last previous recurrence, before the specified date/time.
|
|
* If a time later than 00:00:00 is specified and the recurrence has no time, 00:00:00 on
|
|
* the specified date is returned if that date recurs.
|
|
* @param afterDateTime the date/time before which to find the recurrence.
|
|
* @return date/time of previous recurrence, or invalid date if none.
|
|
*/
|
|
QDateTime getPreviousDate( const QDateTime& afterDateTime ) const;
|
|
|
|
|
|
|
|
|
|
void setBySeconds( const QValueList<int> bySeconds );
|
|
void setByMinutes( const QValueList<int> byMinutes );
|
|
void setByHours( const QValueList<int> byHours );
|
|
|
|
void setByDays( const QValueList<WDayPos> byDays );
|
|
void setByMonthDays( const QValueList<int> byMonthDays );
|
|
void setByYearDays( const QValueList<int> byYearDays );
|
|
void setByWeekNumbers( const QValueList<int> byWeekNumbers );
|
|
void setByMonths( const QValueList<int> byMonths );
|
|
void setBySetPos( const QValueList<int> bySetPos );
|
|
void setWeekStart( short weekStart );
|
|
|
|
const QValueList<int> &bySeconds() const { return mBySeconds; }
|
|
const QValueList<int> &byMinutes() const { return mByMinutes; }
|
|
const QValueList<int> &byHours() const { return mByHours; }
|
|
|
|
const QValueList<WDayPos> &byDays() const { return mByDays; }
|
|
const QValueList<int> &byMonthDays() const { return mByMonthDays; }
|
|
const QValueList<int> &byYearDays() const { return mByYearDays; }
|
|
const QValueList<int> &byWeekNumbers() const { return mByWeekNumbers; }
|
|
const QValueList<int> &byMonths() const { return mByMonths; }
|
|
const QValueList<int> &bySetPos() const { return mBySetPos; }
|
|
short weekStart() const { return mWeekStart; }
|
|
|
|
|
|
void setDirty();
|
|
/**
|
|
Installs an observer. Whenever some setting of this recurrence
|
|
object is changed, the recurrenceUpdated( Recurrence* ) method
|
|
of each observer will be called to inform it of changes.
|
|
@param observer the Recurrence::Observer-derived object, which
|
|
will be installed as an observer of this object.
|
|
*/
|
|
void addObserver( Observer *observer );
|
|
/**
|
|
Removes an observer that was added with addObserver. If the
|
|
given object was not an observer, it does nothing.
|
|
@param observer the Recurrence::Observer-derived object to
|
|
be removed from the list of observers of this object.
|
|
*/
|
|
void removeObserver( Observer *observer );
|
|
|
|
/**
|
|
Debug output.
|
|
*/
|
|
void dump() const;
|
|
QString mRRule;
|
|
|
|
private:
|
|
class Constraint {
|
|
public:
|
|
typedef QValueList<Constraint> List;
|
|
|
|
Constraint( int wkst = 1 );
|
|
/* Constraint( const Constraint &con ) :
|
|
year(con.year), month(con.month), day(con.day),
|
|
hour(con.hour), minute(con.minute), second(con.second),
|
|
weekday(con.weekday), weeknumber(con.weeknumber),
|
|
yearday(con.yearday), weekstart(con.weekstart) {}*/
|
|
Constraint( const QDateTime &preDate, PeriodType type, int wkst );
|
|
void clear();
|
|
|
|
int year; // 0 means unspecified
|
|
int month; // 0 means unspecified
|
|
int day; // 0 means unspecified
|
|
int hour; // -1 means unspecified
|
|
int minute; // -1 means unspecified
|
|
int second; // -1 means unspecified
|
|
int weekday; // 0 means unspecified
|
|
int weekdaynr; // index of weekday in month/year (0=unspecified)
|
|
int weeknumber; // 0 means unspecified
|
|
int yearday; // 0 means unspecified
|
|
int weekstart; // first day of week (1=monday, 7=sunday, 0=unspec.)
|
|
|
|
bool readDateTime( const QDateTime &preDate, PeriodType type );
|
|
bool matches( const QDate &dt, RecurrenceRule::PeriodType type ) const;
|
|
bool matches( const QDateTime &dt, RecurrenceRule::PeriodType type ) const;
|
|
bool isConsistent() const;
|
|
bool isConsistent( PeriodType period ) const;
|
|
bool increase( PeriodType type, int freq );
|
|
QDateTime intervalDateTime( PeriodType type ) const;
|
|
DateTimeList dateTimes( PeriodType type ) const;
|
|
void dump() const;
|
|
};
|
|
|
|
Constraint getNextValidDateInterval( const QDateTime &preDate, PeriodType type ) const;
|
|
Constraint getPreviousValidDateInterval( const QDateTime &preDate, PeriodType type ) const;
|
|
DateTimeList datesForInterval( const Constraint &interval, PeriodType type ) const;
|
|
bool mergeIntervalConstraint( Constraint *merged, const Constraint &conit,
|
|
const Constraint &interval ) const;
|
|
bool buildCache() const;
|
|
|
|
|
|
PeriodType mPeriod;
|
|
QDateTime mDateStart;
|
|
/** how often it recurs (including dtstart):
|
|
-1 means infinitely,
|
|
0 means an explicit end date,
|
|
positive values give the number of occurrences */
|
|
int mDuration;
|
|
QDateTime mDateEnd;
|
|
uint mFrequency;
|
|
|
|
bool mIsReadOnly;
|
|
bool mFloating;
|
|
|
|
QValueList<int> mBySeconds; // values: second 0-59
|
|
QValueList<int> mByMinutes; // values: minute 0-59
|
|
QValueList<int> mByHours; // values: hour 0-23
|
|
|
|
QValueList<WDayPos> mByDays; // n-th weekday of the month or year
|
|
QValueList<int> mByMonthDays; // values: day -31 to -1 and 1-31
|
|
QValueList<int> mByYearDays; // values: day -366 to -1 and 1-366
|
|
QValueList<int> mByWeekNumbers; // values: week -53 to -1 and 1-53
|
|
QValueList<int> mByMonths; // values: month 1-12
|
|
QValueList<int> mBySetPos; // values: position -366 to -1 and 1-366
|
|
short mWeekStart; // first day of the week (1=Monday, 7=Sunday)
|
|
|
|
Constraint::List mConstraints;
|
|
void buildConstraints();
|
|
bool mDirty;
|
|
QValueList<Observer*> mObservers;
|
|
|
|
// Cache for duration
|
|
mutable DateTimeList mCachedDates;
|
|
mutable bool mCached;
|
|
mutable QDateTime mCachedDateEnd;
|
|
|
|
class Private;
|
|
Private *d;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|