summaryrefslogtreecommitdiff
path: root/libopie2/opiepim/core/orecur.cpp
Side-by-side diff
Diffstat (limited to 'libopie2/opiepim/core/orecur.cpp') (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opiepim/core/orecur.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp
index 257d4fd..daf3506 100644
--- a/libopie2/opiepim/core/orecur.cpp
+++ b/libopie2/opiepim/core/orecur.cpp
@@ -22,6 +22,9 @@ struct ORecur::Data : public QShared {
time_t end;
time_t create;
int rep;
+ QString app;
+ ExceptionList list;
+ QDate start;
};
@@ -55,6 +58,298 @@ ORecur &ORecur::operator=( const ORecur& re) {
return *this;
}
+bool ORecur::doesRecur()const {
+ return !( type() == NoRepeat );
+}
+/*
+ * we try to be smart here
+ *
+ */
+bool ORecur::doesRecur( const QDate& date ) {
+ /* the day before the recurrance */
+ QDate da = date.addDays(-1);
+
+ QDate recur;
+ if (!nextOcurrence( da, recur ) )
+ return false;
+
+ return (recur == date);
+}
+// FIXME unuglify!
+// GPL from Datebookdb.cpp
+// FIXME exception list!
+bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
+
+ // easy checks, first are we too far in the future or too far in the past?
+ QDate tmpDate;
+ int freq = frequency();
+ int diff, diff2, a;
+ int iday, imonth, iyear;
+ int dayOfWeek = 0;
+ int firstOfWeek = 0;
+ int weekOfMonth;
+
+
+ if (hasEndDate() && endDate() < from)
+ return FALSE;
+
+ if (start() >= from) {
+ next = start();
+ return TRUE;
+ }
+
+ switch ( type() ) {
+ case Weekly:
+ /* weekly is just daily by 7 */
+ /* first convert the repeatPattern.Days() mask to the next
+ day of week valid after from */
+ dayOfWeek = from.dayOfWeek();
+ dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
+
+ /* this is done in case freq > 1 and from in week not
+ for this round */
+ // firstOfWeek = 0; this is already done at decl.
+ while(!((1 << firstOfWeek) & days() ))
+ firstOfWeek++;
+
+ /* there is at least one 'day', or there would be no event */
+ while(!((1 << (dayOfWeek % 7)) & days() ))
+ dayOfWeek++;
+
+ dayOfWeek = dayOfWeek % 7; /* the actual day of week */
+ dayOfWeek -= start().dayOfWeek() -1;
+
+ firstOfWeek = firstOfWeek % 7; /* the actual first of week */
+ firstOfWeek -= start().dayOfWeek() -1;
+
+ // dayOfWeek may be negitive now
+ // day of week is number of days to add to start day
+
+ freq *= 7;
+ // FALL-THROUGH !!!!!
+ case Daily:
+ // the add is for the possible fall through from weekly */
+ if(start().addDays(dayOfWeek) > from) {
+ /* first week exception */
+ next = QDate(start().addDays(dayOfWeek) );
+ if ((next > endDate())
+ && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+ /* if from is middle of a non-week */
+
+ diff = start().addDays(dayOfWeek).daysTo(from) % freq;
+ diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
+
+ if(diff != 0)
+ diff = freq - diff;
+ if(diff2 != 0)
+ diff2 = freq - diff2;
+ diff = QMIN(diff, diff2);
+
+ next = QDate(from.addDays(diff));
+ if ( (next > endDate())
+ && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ case MonthlyDay:
+ iday = from.day();
+ iyear = from.year();
+ imonth = from.month();
+ /* find equivelent day of month for this month */
+ dayOfWeek = start().dayOfWeek();
+ weekOfMonth = (start().day() - 1) / 7;
+
+ /* work out when the next valid month is */
+ a = from.year() - start().year();
+ a *= 12;
+ a = a + (imonth - start().month());
+ /* a is e.start()monthsFrom(from); */
+ if(a % freq) {
+ a = freq - (a % freq);
+ imonth = from.month() + a;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ }
+ /* imonth is now the first month after or on
+ from that matches the frequency given */
+
+ /* find for this month */
+ tmpDate = QDate( iyear, imonth, 1 );
+
+ iday = 1;
+ iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
+ iday += 7 * weekOfMonth;
+ while (iday > tmpDate.daysInMonth()) {
+ imonth += freq;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ tmpDate = QDate( iyear, imonth, 1 );
+ /* these loops could go for a while, check end case now */
+ if ((tmpDate > endDate()) && hasEndDate() )
+ return FALSE;
+ iday = 1;
+ iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
+ iday += 7 * weekOfMonth;
+ }
+ tmpDate = QDate(iyear, imonth, iday);
+
+ if (tmpDate >= from) {
+ next = tmpDate;
+ if ((next > endDate() ) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+
+ /* need to find the next iteration */
+ do {
+ imonth += freq;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ tmpDate = QDate( iyear, imonth, 1 );
+ /* these loops could go for a while, check end case now */
+ if ((tmpDate > endDate()) && hasEndDate() )
+ return FALSE;
+ iday = 1;
+ iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
+ iday += 7 * weekOfMonth;
+ } while (iday > tmpDate.daysInMonth());
+ tmpDate = QDate(iyear, imonth, iday);
+
+ next = tmpDate;
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ case MonthlyDate:
+ iday = start().day();
+ iyear = from.year();
+ imonth = from.month();
+
+ a = from.year() - start().year();
+ a *= 12;
+ a = a + (imonth - start().month());
+ /* a is e.start()monthsFrom(from); */
+ if(a % freq) {
+ a = freq - (a % freq);
+ imonth = from.month() + a;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ }
+ /* imonth is now the first month after or on
+ from that matches the frequencey given */
+
+ /* this could go for a while, worse case, 4*12 iterations, probably */
+ while(!QDate::isValid(iyear, imonth, iday) ) {
+ imonth += freq;
+ if (imonth > 12) {
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ }
+ /* these loops could go for a while, check end case now */
+ if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
+ return FALSE;
+ }
+
+ if(QDate(iyear, imonth, iday) >= from) {
+ /* done */
+ next = QDate(iyear, imonth, iday);
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+
+ /* ok, need to cycle */
+ imonth += freq;
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+
+ while(!QDate::isValid(iyear, imonth, iday) ) {
+ imonth += freq;
+ imonth--;
+ iyear += imonth / 12;
+ imonth = imonth % 12;
+ imonth++;
+ if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
+ return FALSE;
+ }
+
+ next = QDate(iyear, imonth, iday);
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ case Yearly:
+ iday = start().day();
+ imonth = start().month();
+ iyear = from.year(); // after all, we want to start in this year
+
+ diff = 1;
+ if(imonth == 2 && iday > 28) {
+ /* leap year, and it counts, calculate actual frequency */
+ if(freq % 4)
+ if (freq % 2)
+ freq = freq * 4;
+ else
+ freq = freq * 2;
+ /* else divides by 4 already, leave freq alone */
+ diff = 4;
+ }
+
+ a = from.year() - start().year();
+ if(a % freq) {
+ a = freq - (a % freq);
+ iyear = iyear + a;
+ }
+
+ /* under the assumption we won't hit one of the special not-leap years twice */
+ if(!QDate::isValid(iyear, imonth, iday)) {
+ /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
+ iyear += freq;
+ }
+
+ if(QDate(iyear, imonth, iday) >= from) {
+ next = QDate(iyear, imonth, iday);
+
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ }
+ /* iyear == from.year(), need to advance again */
+ iyear += freq;
+ /* under the assumption we won't hit one of the special not-leap years twice */
+ if(!QDate::isValid(iyear, imonth, iday)) {
+ /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
+ iyear += freq;
+ }
+
+ next = QDate(iyear, imonth, iday);
+ if ((next > endDate()) && hasEndDate() )
+ return FALSE;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
ORecur::RepeatType ORecur::type()const{
return data->type;
}
@@ -73,6 +368,9 @@ bool ORecur::hasEndDate()const {
QDate ORecur::endDate()const {
return TimeConversion::fromUTC( data->end ).date();
}
+QDate ORecur::start()const{
+ return data->start;
+}
time_t ORecur::endDateUTC()const {
return data->end;
}
@@ -82,6 +380,12 @@ time_t ORecur::createTime()const {
int ORecur::repetition()const {
return data->rep;
}
+QString ORecur::service()const {
+ return data->app;
+}
+ORecur::ExceptionList& ORecur::exceptions() {
+ return data->list;
+}
void ORecur::setType( const RepeatType& z) {
checkOrModify();
data->type = z;
@@ -118,6 +422,14 @@ void ORecur::setRepitition( int rep ) {
checkOrModify();
data->rep = rep;
}
+void ORecur::setService( const QString& app ) {
+ checkOrModify();
+ data->app = app;
+}
+void ORecur::setStart( const QDate& dt ) {
+ checkOrModify();
+ data->start = dt;
+}
void ORecur::checkOrModify() {
if ( data->count != 1 ) {
data->deref();
@@ -130,6 +442,9 @@ void ORecur::checkOrModify() {
d2->end = data->end;
d2->create = data->create;
d2->rep = data->rep;
+ d2->app = data->app;
+ d2->list = data->list;
+ d2->start = data->start;
data = d2;
}
}