libkcal

recurrencerule.h

00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 1998 Preston Brown <pbrown@kde.org>
00005     Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
00006     Copyright (c) 2002 David Jarvie <software@astrojar.org.uk>
00007     Copyright (c) 2005, Reinhold Kainhofer <reinhold@kainhofer.com>
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Library General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Library General Public License for more details.
00018 
00019     You should have received a copy of the GNU Library General Public License
00020     along with this library; see the file COPYING.LIB.  If not, write to
00021     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022     Boston, MA 02110-1301, USA.
00023 */
00024 #ifndef KCAL_RECURRENCERULE_H
00025 #define KCAL_RECURRENCERULE_H
00026 
00027 #include <tqdatetime.h>
00028 #include <libkcal/listbase.h>
00029 
00030 #include "libkcal_export.h"
00031 
00032 template <class T>
00033 TQ_INLINE_TEMPLATES void qSortUnique( TQValueList<T> &lst )
00034 {
00035   qHeapSort( lst );
00036   if ( lst.isEmpty() ) return;
00037   // Remove all duplicates from the times list
00038   // TODO: Make this more efficient!
00039   TQValueListIterator<T> it = lst.begin();
00040   T last = *it;
00041   ++it;
00042   T newlast;
00043   while ( it != lst.end() ) {
00044     newlast = (*it);
00045     if ( newlast == last ) it = lst.remove( it );
00046     else {
00047       last = newlast;
00048       ++it;
00049     }
00050   }
00051 }
00052 
00053 template <class T>
00054 TQ_INLINE_TEMPLATES int findGE( const TQValueList<T> &lst, const T &value, int start )
00055 {
00056   // Do a binary search to find the first item >= value
00057   int st = start - 1;
00058   int end = lst.count();
00059   while ( end - st > 1 ) {
00060     int i = ( st + end ) / 2;
00061     if ( value <= lst[i] ) {
00062       end = i;
00063     } else {
00064       st = i;
00065     }
00066   }
00067   ++st;
00068   return ( st == int( lst.count() ) ) ? -1 : st;
00069 }
00070 
00071 template <class T>
00072 TQ_INLINE_TEMPLATES int findGT( const TQValueList<T> &lst, const T &value, int start )
00073 {
00074   // Do a binary search to find the first item > value
00075   int st = start - 1;
00076   int end = lst.count();
00077   while ( end - st > 1 ) {
00078     int i = ( st + end ) / 2;
00079     if ( value < lst[i] ) {
00080       end = i;
00081     } else {
00082       st = i;
00083     }
00084   }
00085   ++st;
00086   return ( st == int( lst.count() ) ) ? -1 : st;
00087 }
00088 
00089 template <class T>
00090 TQ_INLINE_TEMPLATES int findLE( const TQValueList<T> &lst, const T &value, int start )
00091 {
00092   // Do a binary search to find the last item <= value
00093   int st = start - 1;
00094   int end = lst.count();
00095   while ( end - st > 1 ) {
00096     int i = ( st + end ) / 2;
00097     if ( value < lst[i] ) {
00098       end = i;
00099     } else {
00100       st = i;
00101     }
00102   }
00103   return ( end > start ) ? st : -1;
00104 }
00105 
00106 template <class T>
00107 TQ_INLINE_TEMPLATES int findLT( const TQValueList<T> &lst, const T &value, int start )
00108 {
00109   // Do a binary search to find the last item < value
00110   int st = start - 1;
00111   int end = lst.count();
00112   while ( end - st > 1 ) {
00113     int i = ( st + end ) / 2;
00114     if ( value <= lst[i] ) {
00115       end = i;
00116     } else {
00117       st = i;
00118     }
00119   }
00120   return ( end > start ) ? st : -1;
00121 }
00122 
00123 template <class T>
00124 TQ_INLINE_TEMPLATES int findSorted( const TQValueList<T> &lst, const T &value, int start )
00125 {
00126   // Do a binary search to find the item == value
00127   int st = start - 1;
00128   int end = lst.count();
00129   while ( end - st > 1 ) {
00130     int i = ( st + end ) / 2;
00131     if ( value < lst[i] ) {
00132       end = i;
00133     } else {
00134       st = i;
00135     }
00136   }
00137   return ( end > start && value == lst[st] ) ? st : -1;
00138 }
00139 
00140 template <class T>
00141 TQ_INLINE_TEMPLATES int removeSorted( TQValueList<T> &lst, const T &value, int start )
00142 {
00143   int i = findSorted( lst, value, start );
00144   if ( i >= 0 ) {
00145     lst.remove( lst.at( i ) );
00146   }
00147   return i;
00148 }
00149 
00150 template <class T>
00151 TQ_INLINE_TEMPLATES bool containsSorted( const TQValueList<T> &lst, const T &value )
00152 {
00153   return findSorted( lst, value, 0 ) >= 0;
00154 }
00155 
00156 
00157 namespace KCal {
00158 
00159 typedef TQValueList<TQDateTime> DateTimeList;
00160 typedef TQValueList<TQDate> DateList;
00161 typedef TQValueList<TQTime> TimeList;
00162 
00163 
00164 
00165 
00169 class LIBKCAL_EXPORT RecurrenceRule
00170 {
00171   public:
00172     class Observer {
00173       public:
00174         virtual ~Observer() {}
00176         virtual void recurrenceChanged( RecurrenceRule * ) = 0;
00177     };
00178     typedef ListBase<RecurrenceRule> List;
00180     enum PeriodType { rNone = 0,
00181            rSecondly, rMinutely, rHourly,
00182            rDaily, rWeekly, rMonthly, rYearly
00183          };
00185     class WDayPos {
00186     public:
00187       WDayPos( int ps = 0 , short dy = 0 ) : mDay(dy), mPos(ps) {}
00188       short day() const { return mDay; }
00189       int pos() const { return mPos; }
00190       void setDay( short dy ) { mDay = dy; }
00191       void setPos( int ps ) { mPos = ps; }
00192 
00193       bool operator==( const RecurrenceRule::WDayPos &pos2 ) const {
00194           return ( mDay == pos2.mDay ) && ( mPos == pos2.mPos );
00195         }
00196     protected:
00197       short mDay;  // Weekday, 1=monday, 7=sunday
00198       int mPos;    // week of the day (-1 for last, 1 for first, 0 for all weeks)
00199                    // Bounded by -366 and +366, 0 means all weeks in that period
00200     };
00201 
00202     RecurrenceRule( /*Incidence *parent, int compatVersion = 0*/ );
00203     RecurrenceRule(const RecurrenceRule&);
00204     ~RecurrenceRule();
00205 
00206     bool operator==( const RecurrenceRule& ) const;
00207     bool operator!=( const RecurrenceRule& r ) const  { return !operator==(r); }
00208     RecurrenceRule &operator=(const RecurrenceRule&);
00209 
00210 //     Incidence *parent() const { return mParent; }
00211 
00212 
00214     void setReadOnly(bool readOnly) { mIsReadOnly = readOnly; }
00216     bool isReadOnly() const  { return mIsReadOnly; }
00217 
00218 
00221     bool doesRecur() const { return mPeriod!=rNone; }
00222     void setRecurrenceType( PeriodType period );
00223     PeriodType recurrenceType() const { return mPeriod; }
00225     void clear();
00226 
00227 
00229     uint frequency() const { return mFrequency; }
00231     void setFrequency( int freq );
00232 
00233 
00235     TQDateTime startDt() const   { return mDateStart; }
00237     void setStartDt(const TQDateTime &start);
00238 
00241     bool doesFloat() const { return mFloating; }
00243     void setFloats( bool floats );
00244 
00245 
00251     TQDateTime endDt( bool* result = 0 ) const;
00254     void setEndDt(const TQDateTime &endDateTime);
00255 
00256 
00261     int duration() const { return mDuration; }
00264     void setDuration(int duration);
00265 //     /** Returns the number of recurrences up to and including the date specified. */
00266 //     int durationTo(const TQDate &) const;
00268     int durationTo(const TQDateTime &) const;
00270     int durationTo( const TQDate &date ) const { return durationTo( TQDateTime( date, TQTime( 23, 59, 59 ) ) ); }
00271 
00272 
00273 
00276     bool recursOn( const TQDate &qd ) const;
00280     bool recursAt( const TQDateTime & ) const;
00285     bool dateMatchesRules( const TQDateTime &qdt ) const;
00286 
00287 
00292     TimeList recurTimesOn( const TQDate &date ) const;
00293 
00305     DateTimeList timesInInterval( const TQDateTime &start, const TQDateTime &end ) const;
00306 
00312     TQDateTime getNextDate( const TQDateTime& preDateTime ) const;
00319     TQDateTime getPreviousDate( const TQDateTime& afterDateTime ) const;
00320 
00321 
00322 
00323 
00324     void setBySeconds( const TQValueList<int> bySeconds );
00325     void setByMinutes( const TQValueList<int> byMinutes );
00326     void setByHours( const TQValueList<int> byHours );
00327 
00328     void setByDays( const TQValueList<WDayPos> byDays );
00329     void setByMonthDays( const TQValueList<int> byMonthDays );
00330     void setByYearDays( const TQValueList<int> byYearDays );
00331     void setByWeekNumbers( const TQValueList<int> byWeekNumbers );
00332     void setByMonths( const TQValueList<int> byMonths );
00333     void setBySetPos( const TQValueList<int> bySetPos );
00334     void setWeekStart( short weekStart );
00335 
00336     const TQValueList<int> &bySeconds() const { return mBySeconds; }
00337     const TQValueList<int> &byMinutes() const { return mByMinutes; }
00338     const TQValueList<int> &byHours() const { return mByHours; }
00339 
00340     const TQValueList<WDayPos> &byDays() const { return mByDays; }
00341     const TQValueList<int> &byMonthDays() const { return mByMonthDays; }
00342     const TQValueList<int> &byYearDays() const { return mByYearDays; }
00343     const TQValueList<int> &byWeekNumbers() const { return mByWeekNumbers; }
00344     const TQValueList<int> &byMonths() const { return mByMonths; }
00345     const TQValueList<int> &bySetPos() const { return mBySetPos; }
00346     short weekStart() const { return mWeekStart; }
00347 
00348 
00349     void setDirty();
00357     void addObserver( Observer *observer );
00364     void removeObserver( Observer *observer );
00365 
00369     void dump() const;
00370     TQString mRRule;
00371 
00372   private:
00373     class Constraint {
00374       public:
00375         typedef TQValueList<Constraint> List;
00376 
00377         Constraint( int wkst = 1 );
00378 /*         Constraint( const Constraint &con ) :
00379                      year(con.year), month(con.month), day(con.day),
00380                      hour(con.hour), minute(con.minute), second(con.second),
00381                      weekday(con.weekday), weeknumber(con.weeknumber),
00382                      yearday(con.yearday), weekstart(con.weekstart) {}*/
00383         Constraint( const TQDateTime &preDate, PeriodType type, int wkst );
00384         void clear();
00385 
00386         int year;       // 0 means unspecified
00387         int month;      // 0 means unspecified
00388         int day;        // 0 means unspecified
00389         int hour;       // -1 means unspecified
00390         int minute;     // -1 means unspecified
00391         int second;     // -1 means unspecified
00392         int weekday;    //  0 means unspecified
00393         int weekdaynr;  // index of weekday in month/year (0=unspecified)
00394         int weeknumber; //  0 means unspecified
00395         int yearday;    //  0 means unspecified
00396         int weekstart;  //  first day of week (1=monday, 7=sunday, 0=unspec.)
00397 
00398         bool readDateTime( const TQDateTime &preDate, PeriodType type );
00399         bool matches( const TQDate &dt, RecurrenceRule::PeriodType type ) const;
00400         bool matches( const TQDateTime &dt, RecurrenceRule::PeriodType type ) const;
00401         bool isConsistent() const;
00402         bool isConsistent( PeriodType period ) const;
00403         bool increase( PeriodType type, int freq );
00404         TQDateTime intervalDateTime( PeriodType type ) const;
00405         DateTimeList dateTimes( PeriodType type ) const;
00406         void dump() const;
00407     };
00408 
00409     Constraint getNextValidDateInterval( const TQDateTime &preDate, PeriodType type ) const;
00410     Constraint getPreviousValidDateInterval( const TQDateTime &preDate, PeriodType type ) const;
00411     DateTimeList datesForInterval( const Constraint &interval, PeriodType type ) const;
00412     bool mergeIntervalConstraint( Constraint *merged, const Constraint &conit,
00413                                   const Constraint &interval ) const;
00414     bool buildCache() const;
00415 
00416 
00417     PeriodType mPeriod;
00418     TQDateTime mDateStart;
00423     int mDuration;
00424     TQDateTime mDateEnd;
00425     uint mFrequency;
00426 
00427     bool mIsReadOnly;
00428     bool mFloating;
00429 
00430     TQValueList<int> mBySeconds;     // values: second 0-59
00431     TQValueList<int> mByMinutes;     // values: minute 0-59
00432     TQValueList<int> mByHours;       // values: hour 0-23
00433 
00434     TQValueList<WDayPos> mByDays;   // n-th weekday of the month or year
00435     TQValueList<int> mByMonthDays;   // values: day -31 to -1 and 1-31
00436     TQValueList<int> mByYearDays;    // values: day -366 to -1 and 1-366
00437     TQValueList<int> mByWeekNumbers; // values: week -53 to -1 and 1-53
00438     TQValueList<int> mByMonths;      // values: month 1-12
00439     TQValueList<int> mBySetPos;      // values: position -366 to -1 and 1-366
00440     short mWeekStart;               // first day of the week (1=Monday, 7=Sunday)
00441 
00442     Constraint::List mConstraints;
00443     void buildConstraints();
00444     bool mDirty;
00445     TQValueList<Observer*> mObservers;
00446 
00447     // Cache for duration
00448     mutable DateTimeList mCachedDates;
00449     mutable TQDateTime mCachedDateEnd;
00450     mutable TQDateTime mCachedLastDate;   // when mCachedDateEnd invalid, last date checked
00451     mutable bool mCached;
00452 
00453     bool mNoByRules;        // no BySeconds, ByMinutes, ... rules exist
00454     uint mTimedRepetition;  // repeats at a regular number of seconds interval, or 0
00455 
00456     class Private;
00457     Private *d;
00458 };
00459 
00460 }
00461 
00462 #endif