-rw-r--r-- | korganizer/komonthview.cpp | 15 | ||||
-rw-r--r-- | libkcal/recurrence.cpp | 26 |
2 files changed, 10 insertions, 31 deletions
diff --git a/korganizer/komonthview.cpp b/korganizer/komonthview.cpp index cb69832..004ff50 100644 --- a/korganizer/komonthview.cpp +++ b/korganizer/komonthview.cpp @@ -1071,430 +1071,421 @@ QPtrList<Incidence> KOMonthView::selectedIncidences() DateList KOMonthView::selectedDates() { DateList selected; if ( mSelectedCell ) { QDate qd = mSelectedCell->selectedIncidenceDate(); if ( qd.isValid() ) selected.append( qd ); } return selected; } void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd, const QDate &td) { #ifndef KORG_NOPRINTER calPrinter->preview(CalPrinter::Month, fd, td); #endif } void KOMonthView::updateConfig() { mWeekStartsMonday = KGlobal::locale()->weekStartsMonday(); if ( mShowWeekView ) { mWeekStartsMonday = true; } QFontMetrics fontmetric(mDayLabels[0]->font()); mWidthLongDayLabel = 0; for (int i = 0; i < 7; i++) { int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1)); if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width; } bool temp = mShowSatSunComp ; mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ; if ( ! mShowWeekView ) { if ( temp != KOPrefs::instance()->mMonthViewSatSunTog ) computeLayout(); } updateDayLabels(); //qDebug("KOMonthView::updateConfig() %d %d %d ",height(), mDayLabels[0]->sizeHint().height() ,mNumWeeks); //int cellHeight = (height() - mDayLabels[0]->sizeHint().height()) /mNumWeeks; //resizeEvent( 0 ); for (uint i = 0; i < mCells.count(); ++i) { mCells[i]->updateConfig(); } for (uint i = 0; i < mCellsW.count(); ++i) { mCellsW[i]->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont); } #ifdef DESKTOP_VERSION MonthViewCell::toolTipGroup()->setEnabled(KOPrefs::instance()->mEnableToolTips); #endif updateView(); } void KOMonthView::updateDayLabels() { QPtrVector<QLabel> *mDayLabelsT; mDayLabelsT = &mDayLabelsW; for (int i = 0; i < 7; i++) { if (mWeekStartsMonday) { bool show = mShortDayLabelsW; if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() ) show = true; (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show)); } else { if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsW)); else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsW)); } } mDayLabelsT = &mDayLabels; for (int i = 0; i < 7; i++) { if (mWeekStartsMonday) { bool show = mShortDayLabelsM; if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() ) show = true; (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show)); } else { if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsM)); else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsM)); } } } void KOMonthView::showDates(const QDate &start, const QDate &) { // kdDebug() << "KOMonthView::showDates(): " << start.toString() << endl; QPtrVector<MonthViewCell> *cells; QPtrVector<QLabel> *dayLabels; QPtrVector<KOWeekButton> *weekLabels; int weekNum = 6; if ( mShowWeekView ) { weekNum = 1; cells = &mCellsW; dayLabels = &mDayLabelsW; weekLabels = &mWeekLabelsW; } else { cells = &mCells; dayLabels = &mDayLabels; weekLabels = &mWeekLabels; } mStartDate = start; int startWeekDay = mWeekStartsMonday ? 1 : 7; while( KOGlobals::self()->calendarSystem()->dayOfWeek(mStartDate) != startWeekDay ) { mStartDate = mStartDate.addDays( -1 ); } bool primary = false; uint i; for( i = 0; i < (*cells).size(); ++i ) { QDate date = mStartDate.addDays( i ); (*cells)[i]->setDate( date ); #ifndef KORG_NOPLUGINS // add holiday, if present QString hstring(KOCore::self()->holiday(date)); (*cells)[i]->setHoliday( hstring ); #endif } QDate date = mStartDate.addDays( mWeekStartsMonday ? 3 : 4 ); for( i = 0; i < weekNum; ++i ) { int wno; // remember, according to ISO 8601, the first week of the year is the // first week that contains a thursday. Thus we must subtract off 4, // not just 1. int dayOfYear = date.dayOfYear(); if (dayOfYear % 7 != 0) wno = dayOfYear / 7 + 1; else wno =dayOfYear / 7; (*weekLabels)[i]->setWeekNum( wno ); date = date.addDays( 7 ); } updateView(); } void KOMonthView::showEvents(QPtrList<Event>) { qDebug("KOMonthView::selectEvents is not implemented yet. "); } void KOMonthView::changeEventDisplay(Event *, int) { // this should be re-written to be much more efficient, but this // quick-and-dirty-hack gets the job done for right now. updateView(); } void KOMonthView::updateView() { if ( !updatePossible ) return; //QTime ti; //ti.start(); clearSelection(); QPtrVector<MonthViewCell> *cells; if ( mShowWeekView ) { cells = &mCellsW; } else { cells = &mCells; } #if 1 int i; int timeSpan = (*cells).size()-1; if ( KOPrefs::instance()->mMonthViewWeek ) timeSpan = 6; for( i = 0; i < timeSpan + 1; ++i ) { (*cells)[i]->startUpdateCell(); } QPtrList<Event> events = calendar()->events(); Event *event; QDateTime dt; bool ok; QDate endDate = mStartDate.addDays( timeSpan ); for( event = events.first(); event; event = events.next() ) { // for event if ( event->doesRecur() ) { bool last; - qDebug("********************************************** "); - qDebug("Event summary: %s ", event->summary().latin1()); QDateTime incidenceStart = event->recurrence()->getPreviousDateTime( QDateTime( mStartDate ) , &last ); QDateTime incidenceEnd; int eventlen = event->dtStart().date().daysTo ( event->dtEnd().date() ); - qDebug("eventlen %d ", eventlen); bool invalid = false; while( true ) { if ( incidenceStart.isValid() ) { incidenceEnd = incidenceStart.addDays( eventlen ); int st = incidenceStart.date().daysTo( endDate ); if ( st >= 0 ) { // start before timeend int end = mStartDate.daysTo( incidenceEnd.date() ); if ( end >= 0 ) { // end after timestart --- got one! //normalize st = timeSpan - st; if ( st < 0 ) st = 0; if ( end > timeSpan ) end = timeSpan; int iii; //qDebug("found %s %d %d ",event->summary().latin1(), st, end ); for ( iii = st;iii<= end;++iii) (*cells)[iii]->insertEvent( event ); } } } else { if ( invalid ) break; invalid = true; - qDebug("invalid %s", event->summary().latin1()); + //qDebug("invalid %s", event->summary().latin1()); incidenceStart = QDateTime( mStartDate ).addSecs( -2 );; } if ( last ) break; bool ok; - qDebug("TRY next occurence %s ", incidenceStart.toString().latin1()); incidenceStart = event->getNextOccurence( incidenceStart.addSecs( 1 ) ,&ok ); - if ( ! ok ) { - qDebug("NOT OK "); + if ( ! ok ) break; - } - if ( incidenceStart.date() > endDate ) { - qDebug("incidenceStart.date() > endDate "); + if ( incidenceStart.date() > endDate ) break; } - qDebug("next occurence %s ", incidenceStart.toString().latin1()); - } } else { // no recur int st = event->dtStart().date().daysTo( endDate ); if ( st >= 0 ) { // start before timeend int end = mStartDate.daysTo( event->dtEnd().date() ); if ( end >= 0 ) { // end after timestart --- got one! //normalize st = timeSpan - st; if ( st < 0 ) st = 0; if ( end > timeSpan ) end = timeSpan; int iii; for ( iii = st;iii<= end;++iii) (*cells)[iii]->insertEvent( event ); } } } } // insert due todos QPtrList<Todo> todos = calendar()->todos( ); Todo *todo; for(todo = todos.first(); todo; todo = todos.next()) { //insertTodo( todo ); if ( todo->hasDueDate() ) { int day = mStartDate.daysTo( todo->dtDue().date() ); if ( day >= 0 && day < timeSpan + 1) { (*cells)[day]->insertTodo( todo ); } } } for( i = 0; i < timeSpan+1; ++i ) { (*cells)[i]->finishUpdateCell(); } processSelectionChange(); (*cells)[0]->setFocus(); #else // old code //qDebug("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ "); int i; for( i = 0; i < (*cells).count(); ++i ) { (*cells)[i]->updateCell(); } //qDebug("KOMonthView::updateView() "); processSelectionChange(); // qDebug("---------------------------------------------------------------------+ "); (*cells)[0]->setFocus(); #endif //qDebug("update time %d ", ti.elapsed()); } void KOMonthView::resizeEvent(QResizeEvent * e) { //qDebug("KOMonthView::resizeEvent %d %d -- %d %d ", e->size().width(), e->size().height(), e->oldSize().width(), e->oldSize().height()); computeLayout(); clPending = true; if ( mShowWeekView ) mCellsW[0]->setFocus(); else mCells[0]->setFocus(); } void KOMonthView::computeLayoutWeek() { static int lastWid = 0; static int lastHei = 0; int daysToShow; bool combinedSatSun = false; if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) { daysToShow = 6; combinedSatSun = true; } int tWid = topLevelWidget()->size().width(); int tHei = topLevelWidget()->size().height(); int wid = width();//e int hei = height()-1-mNavigatorBar->height(); if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei ) return; if ( lastWid == width() && lastHei == height() ) return; lastWid = width(); lastHei = height(); if ( wid < hei ) daysToShow = 2; else daysToShow = 3; mShowSatSunComp = true; combinedSatSun = true; //qDebug("KOMonthView::computeLayout() WWW ------------------------------------ "); QFontMetrics fm ( mWeekLabels[0]->font() ); int weeklabelwid = fm.width( "888" ); wid -= weeklabelwid; int colWid = wid / daysToShow; int lastCol = wid - ( colWid*6 ); int dayLabelHei = mDayLabelsW[0]->sizeHint().height(); int cellHei = (hei - (5- daysToShow )*dayLabelHei) /(5- daysToShow ); int colModulo = wid % daysToShow; int rowModulo = (hei- (5- daysToShow )*dayLabelHei) % daysToShow-1; //qDebug("rowmod %d ", rowModulo); int i; int x,y,w,h; x= 0; y= 0; w = colWid; h = dayLabelHei ; for ( i = 0; i < 7; i++) { if ( i && !( i % daysToShow) && i < 6) { y += hei/(5-daysToShow); x = 0; w = colWid; } if ( ((i) % daysToShow) >= daysToShow-colModulo ) { ++w; } if ( i >= 5 ) { mDayLabelsW[i]->setGeometry( x+weeklabelwid,y,w/2+w%2,h); x -= (w/2 ); } else mDayLabelsW[i]->setGeometry( x+weeklabelwid,y,w,h); x += w; } x= 0; y= dayLabelHei; w = colWid; h = cellHei; for ( i = 0; i < mCellsW.count(); ++i) { if ( i > 6 ) { mCellsW[i]->hide(); continue; } w = colWid; if ( ((i) % daysToShow) >= daysToShow-colModulo ) { ++w; } if ( i == (daysToShow-1-rowModulo)*7) ++h; if ( i >= 5 ) { if ( i ==5 ) { mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h/2 ); x -= w ;y += h/2; } else { if ( ((i-1) % daysToShow) >= daysToShow-colModulo ) { ++w; } mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 ); y -= h/2; } } else mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h ); x += w; if ( x + w/2 > wid ) { x = 0; y += h+dayLabelHei ; } } y= dayLabelHei; h = cellHei ; mWeekLabelsW[0]->setGeometry( 0,y,weeklabelwid,hei-dayLabelHei); mWeekLabelsW[1]->setGeometry( 0,0,weeklabelwid,dayLabelHei); // qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height()); //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height()); mShortDayLabelsW = mDayLabelsW[0]->width()-2 < mWidthLongDayLabel ; updateDayLabels(); //bool forceUpdate = !updatePossible; updatePossible = true; //mWeekLabels[mNumWeeks]->setText( i18n("M")); //if ( forceUpdate ) // updateView(); } void KOMonthView::computeLayout() { static int lastWid = 0; static int lastHei = 0; if ( mShowWeekView ){ computeLayoutWeek(); return; diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp index 8a175c9..6ee5499 100644 --- a/libkcal/recurrence.cpp +++ b/libkcal/recurrence.cpp @@ -787,698 +787,695 @@ void Recurrence::addYearlyNum(short _rNum) if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) { // Backwards compatibility for KDE < 3.1. // Dates were stored as day numbers, with a fiddle to take account of leap years. // Convert the day number to a month. if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366)) return; // invalid day number _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month(); } else if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12 || recurs == rYearlyDay && _rNum > 366) return; // invalid day number uint i = 0; for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) { if (_rNum == *it) return; // this day/month is already in the list - avoid duplication ++i; } int *tmpNum = new int; *tmpNum = _rNum; rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position if (mCompatVersion < 310 && mCompatDuration > 0) { // Backwards compatibility for KDE < 3.1. // rDuration was set to the number of time periods to recur. // Convert this to the number of occurrences. QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31); rDuration = INT_MAX; // ensure that recurCalc() does its job correctly rDuration = recurCalc(COUNT_TO_DATE, end); } if (mParent) mParent->updated(); } QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const { if (last) *last = false; int freq; switch (recurs) { case rMinutely: freq = rFreq * 60; break; case rHourly: freq = rFreq * 3600; break; case rDaily: case rWeekly: case rMonthlyPos: case rMonthlyDay: case rYearlyMonth: case rYearlyDay: case rYearlyPos: { QDate preDate = preDateTime.date(); if (!mFloats && mRecurStart.time() > preDateTime.time()) preDate = preDate.addDays(-1); return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time()); } default: return QDateTime(); } // It's a sub-daily recurrence if (preDateTime < mRecurStart) return mRecurStart; int count = mRecurStart.secsTo(preDateTime) / freq + 2; if (rDuration > 0) { if (count > rDuration) return QDateTime(); if (last && count == rDuration) *last = true; } QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); if (rDuration == 0) { if (endtime > rEndDateTime) return QDateTime(); if (last && endtime == rEndDateTime) *last = true; } return endtime; } QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const { if (last) *last = false; switch (recurs) { case rMinutely: case rHourly: return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date(); case rDaily: case rWeekly: case rMonthlyPos: case rMonthlyDay: case rYearlyMonth: case rYearlyDay: case rYearlyPos: qDebug("Recurrence::getNextDate: MAY BE BROKEN "); return getNextDateNoTime(preDate, last); default: return QDate(); } } QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const { if (last) *last = false; int freq; switch (recurs) { case rMinutely: freq = rFreq * 60; break; case rHourly: freq = rFreq * 3600; break; case rDaily: case rWeekly: case rMonthlyPos: case rMonthlyDay: case rYearlyMonth: case rYearlyDay: case rYearlyPos: { QDate afterDate = afterDateTime.date(); if (!mFloats && mRecurStart.time() < afterDateTime.time()) afterDate = afterDate.addDays(1); return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time()); } default: return QDateTime(); } // It's a sub-daily recurrence if (afterDateTime <= mRecurStart) return QDateTime(); int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1; if (rDuration > 0) { if (count > rDuration) count = rDuration; if (last && count == rDuration) *last = true; } QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); if (rDuration == 0) { if (endtime > rEndDateTime) endtime = rEndDateTime; if (last && endtime == rEndDateTime) *last = true; } return endtime; } QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const { if (last) *last = false; switch (recurs) { case rMinutely: case rHourly: return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date(); case rDaily: case rWeekly: case rMonthlyPos: case rMonthlyDay: case rYearlyMonth: case rYearlyDay: case rYearlyPos: return getPreviousDateNoTime(afterDate, last); default: return QDate(); } } /***************************** PROTECTED FUNCTIONS ***************************/ bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const { if ((qd >= mRecurStart.date()) && ((rDuration > 0) && (qd <= endDate()) || ((rDuration == 0) && (qd <= rEndDateTime.date())) || (rDuration == -1))) { // The date queried falls within the range of the event. if (secondFreq < 24*3600) return true; // the event recurs at least once each day - int after = mRecurStart.secsTo(QDateTime(qd)); + int after = mRecurStart.secsTo(QDateTime(qd)) - 1; if (after / secondFreq != (after + 24*3600) / secondFreq) return true; } return false; } bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const { if ((dt >= mRecurStart) && ((rDuration > 0) && (dt <= endDateTime()) || ((rDuration == 0) && (dt <= rEndDateTime)) || (rDuration == -1))) { // The time queried falls within the range of the event. if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0) return true; } return false; } bool Recurrence::recursDaily(const QDate &qd) const { QDate dStart = mRecurStart.date(); if ((dStart.daysTo(qd) % rFreq) == 0) { // The date is a day which recurs if (qd >= dStart && ((rDuration > 0 && qd <= endDate()) || (rDuration == 0 && qd <= rEndDateTime.date()) || rDuration == -1)) { // The date queried falls within the range of the event. return true; } } return false; } bool Recurrence::recursWeekly(const QDate &qd) const { QDate dStart = mRecurStart.date(); if ((dStart.daysTo(qd)/7) % rFreq == 0) { // The date is in a week which recurs if (qd >= dStart && ((rDuration > 0 && qd <= endDate()) || (rDuration == 0 && qd <= rEndDateTime.date()) || rDuration == -1)) { // The date queried falls within the range of the event. // check if the bits set match today. int i = qd.dayOfWeek()-1; if (rDays.testBit((uint) i)) return true; } } return false; } bool Recurrence::recursMonthly(const QDate &qd) const { QDate dStart = mRecurStart.date(); int year = qd.year(); int month = qd.month(); int day = qd.day(); // calculate how many months ahead this date is from the original // event's date int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month()); if ((monthsAhead % rFreq) == 0) { // The date is in a month which recurs if (qd >= dStart && ((rDuration > 0 && qd <= endDate()) || (rDuration == 0 && qd <= rEndDateTime.date()) || rDuration == -1)) { // The date queried falls within the range of the event. QValueList<int> days; int daysInMonth = qd.daysInMonth(); if (recurs == rMonthlyDay) getMonthlyDayDays(days, daysInMonth); else if (recurs == rMonthlyPos) getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek()); for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { if (*it == day) return true; } // no dates matched } } return false; } bool Recurrence::recursYearlyByMonth(const QDate &qd) const { QDate dStart = mRecurStart.date(); int startDay = dStart.day(); int qday = qd.day(); int qmonth = qd.month(); int qyear = qd.year(); bool match = (qday == startDay); if (!match && startDay == 29 && dStart.month() == 2) { // It's a recurrence on February 29th switch (mFeb29YearlyType) { case rFeb28: if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear)) match = true; break; case rMar1: if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) { qmonth = 2; match = true; } break; case rFeb29: break; } } if (match) { // The day of the month matches. Calculate how many years ahead // this date is from the original event's date. int yearsAhead = (qyear - dStart.year()); if (yearsAhead % rFreq == 0) { // The date is in a year which recurs if (qd >= dStart && ((rDuration > 0 && qd <= endDate()) || (rDuration == 0 && qd <= rEndDateTime.date()) || rDuration == -1)) { // The date queried falls within the range of the event. int i = qmonth; for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { if (i == *qlin.current()) return true; } } } } return false; } bool Recurrence::recursYearlyByPos(const QDate &qd) const { QDate dStart = mRecurStart.date(); int year = qd.year(); int month = qd.month(); int day = qd.day(); // calculate how many years ahead this date is from the original // event's date int yearsAhead = (year - dStart.year()); if (yearsAhead % rFreq == 0) { // The date is in a year which recurs if (qd >= dStart && ((rDuration > 0 && qd <= endDate()) || (rDuration == 0 && qd <= rEndDateTime.date()) || rDuration == -1)) { // The date queried falls within the range of the event. for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { if (month == *qlin.current()) { // The month recurs QValueList<int> days; getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek()); for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { if (*it == day) return true; } } } } } return false; } bool Recurrence::recursYearlyByDay(const QDate &qd) const { QDate dStart = mRecurStart.date(); // calculate how many years ahead this date is from the original // event's date int yearsAhead = (qd.year() - dStart.year()); if (yearsAhead % rFreq == 0) { // The date is in a year which recurs if (qd >= dStart && ((rDuration > 0 && qd <= endDate()) || (rDuration == 0 && qd <= rEndDateTime.date()) || rDuration == -1)) { // The date queried falls within the range of the event. int i = qd.dayOfYear(); for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { if (i == *qlin.current()) return true; } } } return false; } /* Get the date of the next recurrence, after the specified date. * If 'last' is non-null, '*last' is set to true if the next recurrence is the * last recurrence, else false. * Reply = date of next recurrence, or invalid date if none. */ QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const { if (last) *last = false; QDate dStart = mRecurStart.date(); if (preDate < dStart) return dStart; QDate earliestDate = preDate.addDays(1); QDate nextDate; switch (recurs) { case rDaily: nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq); break; case rWeekly: { - QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart + QDate start = dStart.addDays(-((dStart.dayOfWeek() - rWeekStart + 7)%7)); // start of week for dStart int earliestDayOfWeek = earliestDate.dayOfWeek(); int weeksAhead = start.daysTo(earliestDate) / 7; int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week weeksAhead -= notThisWeek; // latest week which recurred int weekday = 0; // First check for any remaining day this week, if this week is a recurring week if (!notThisWeek) weekday = getFirstDayInWeek(earliestDayOfWeek); // Check for a day in the next scheduled week - if (!weekday && earliestDayOfWeek > 1) + if (!weekday ) weekday = getFirstDayInWeek(rWeekStart) + rFreq*7; - if (weekday) nextDate = start.addDays(weeksAhead*7 + weekday - 1); break; } case rMonthlyDay: case rMonthlyPos: { int startYear = dStart.year(); int startMonth = dStart.month(); // 1..12 int earliestYear = earliestDate.year(); int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth; int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month monthsAhead -= notThisMonth; // latest month which recurred // Check for the first later day in the current month if (!notThisMonth) nextDate = getFirstDateInMonth(earliestDate); - if (!nextDate.isValid() && earliestDate.day() > 1) { + if (!nextDate.isValid() ) { // Check for a day in the next scheduled month int months = startMonth - 1 + monthsAhead + rFreq; nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1)); } break; } case rYearlyMonth: case rYearlyPos: case rYearlyDay: { int startYear = dStart.year(); int yearsAhead = earliestDate.year() - startYear; int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year yearsAhead -= notThisYear; // latest year which recurred // Check for the first later date in the current year if (!notThisYear) nextDate = getFirstDateInYear(earliestDate); // Check for a date in the next scheduled year if (!nextDate.isValid() && earliestDate.dayOfYear() > 1) nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1)); break; } case rNone: default: return QDate(); } if (rDuration >= 0 && nextDate.isValid()) { // Check that the date found is within the range of the recurrence QDate end = endDate(); if (nextDate > end) return QDate(); if (last && nextDate == end) *last = true; } return nextDate; } /* Get the date of the last previous recurrence, before the specified date. * Reply = date of previous recurrence, or invalid date if none. */ QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const { if (last) *last = false; QDate dStart = mRecurStart.date(); QDate latestDate = afterDate.addDays(-1); if (latestDate < dStart) return QDate(); QDate prevDate; switch (recurs) { case rDaily: prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq); break; case rWeekly: { - QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart + QDate start = dStart.addDays(-((dStart.dayOfWeek() - rWeekStart + 7)%7)); // start of week for dStart int latestDayOfWeek = latestDate.dayOfWeek(); int weeksAhead = start.daysTo(latestDate) / 7; int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week weeksAhead -= notThisWeek; // latest week which recurred int weekday = 0; // First check for any previous day this week, if this week is a recurring week if (!notThisWeek) weekday = getLastDayInWeek(latestDayOfWeek); // Check for a day in the previous scheduled week if (!weekday) { - int weekEnd = (rWeekStart + 5)%7 + 1; - if (latestDayOfWeek < weekEnd) { if (!notThisWeek) weeksAhead -= rFreq; + int weekEnd = (rWeekStart + 5)%7 + 1; weekday = getLastDayInWeek(weekEnd); } - } if (weekday) prevDate = start.addDays(weeksAhead*7 + weekday - 1); break; } case rMonthlyDay: case rMonthlyPos: { int startYear = dStart.year(); int startMonth = dStart.month(); // 1..12 int latestYear = latestDate.year(); int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth; int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month monthsAhead -= notThisMonth; // latest month which recurred // Check for the last earlier day in the current month if (!notThisMonth) prevDate = getLastDateInMonth(latestDate); if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) { // Check for a day in the previous scheduled month if (!notThisMonth) monthsAhead -= rFreq; int months = startMonth + monthsAhead; // get the month after the one that recurs prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1)); } break; } case rYearlyMonth: case rYearlyPos: case rYearlyDay: { int startYear = dStart.year(); int yearsAhead = latestDate.year() - startYear; int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year yearsAhead -= notThisYear; // latest year which recurred // Check for the first later date in the current year if (!notThisYear) prevDate = getLastDateInYear(latestDate); if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) { // Check for a date in the next scheduled year if (!notThisYear) yearsAhead -= rFreq; prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31)); } break; } case rNone: default: return QDate(); } if (prevDate.isValid()) { // Check that the date found is within the range of the recurrence if (prevDate < dStart) return QDate(); if (rDuration >= 0) { QDate end = endDate(); if (prevDate >= end) { if (last) *last = true; return end; } } } return prevDate; } void Recurrence::setDailySub(short type, int freq, int duration) { recurs = type; rFreq = freq; rDuration = duration; rMonthPositions.clear(); rMonthDays.clear(); rYearNums.clear(); if (type != rDaily) mFloats = false; // sub-daily types can't be floating if (mParent) mParent->updated(); } void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration) { recurs = type; if (mCompatVersion < 310 && type == rYearlyDay) { mCompatRecurs = rYearlyDay; recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month feb29type = rMar1; // retain the same day number in the year } mFeb29YearlyType = feb29type; rFreq = freq; rDuration = duration; if (type != rYearlyPos) rMonthPositions.clear(); rMonthDays.clear(); if (mParent) mParent->updated(); } int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const { QDate enddate = endtime.date(); switch (func) { case END_DATE_AND_COUNT: if (rDuration < 0) { endtime = QDateTime(); return 0; // infinite recurrence } if (rDuration == 0) { endtime = rEndDateTime; func = COUNT_TO_DATE; } break; case COUNT_TO_DATE: // Count recurrences up to and including the specified date/time. if (endtime < mRecurStart) return 0; if (rDuration == 0 && endtime > rEndDateTime) enddate = rEndDateTime.date(); else if (!mFloats && mRecurStart.time() > endtime.time()) enddate = enddate.addDays(-1); break; case NEXT_AFTER_DATE: // Find next recurrence AFTER endtime if (endtime < mRecurStart) { endtime = mRecurStart; return 1; } if (rDuration == 0 && endtime >= rEndDateTime) { endtime = QDateTime(); return 0; } if (!mFloats && mRecurStart.time() > endtime.time()) enddate = enddate.addDays(-1); break; default: endtime = QDateTime(); return 0; } int count = 0; // default = error bool timed = false; switch (recurs) { case rMinutely: timed = true; count = secondlyCalc(func, endtime, rFreq*60); break; case rHourly: timed = true; count = secondlyCalc(func, endtime, rFreq*3600); break; case rDaily: count = dailyCalc(func, enddate); break; case rWeekly: count = weeklyCalc(func, enddate); break; case rMonthlyPos: case rMonthlyDay: count = monthlyCalc(func, enddate); break; case rYearlyMonth: count = yearlyMonthCalc(func, enddate); break; case rYearlyPos: count = yearlyPosCalc(func, enddate); break; case rYearlyDay: count = yearlyDayCalc(func, enddate); break; default: break; } switch (func) { case END_DATE_AND_COUNT: case NEXT_AFTER_DATE: if (count == 0) endtime = QDateTime(); else if (!timed) { endtime.setDate(enddate); endtime.setTime(mRecurStart.time()); } break; case COUNT_TO_DATE: break; } return count; } int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const { QDateTime endtime(enddate, QTime(23,59,59)); switch (func) { case END_DATE_AND_COUNT: if (rDuration < 0) { @@ -3211,203 +3208,194 @@ QDate Recurrence::getFirstDateInMonth(const QDate &earliestDate) const return monthBegin.addDays(*id - 1); } break; } } return QDate(); } /* From the recurrence monthly day number list or monthly day of week/week of * month list, get the latest day in the specified month which is <= the * latestDate. */ QDate Recurrence::getLastDateInMonth(const QDate &latestDate) const { int latestDay = latestDate.day(); int daysInMonth = latestDate.daysInMonth(); switch (recurs) { case rMonthlyDay: { int maxday = -1; for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { int day = *it.current(); if (day < 0) day = daysInMonth + day + 1; if (day <= latestDay && day > maxday) maxday = day; } if (maxday > 0) return QDate(latestDate.year(), latestDate.month(), maxday); break; } case rMonthlyPos: case rYearlyPos: { QDate monthBegin(latestDate.addDays(1 - latestDay)); QValueList<int> dayList; getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek()); for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) { if (*id <= latestDay) return monthBegin.addDays(*id - 1); } break; } } return QDate(); } /* From the recurrence yearly month list or yearly day list, get the earliest * month or day in the specified year which is >= the earliestDate. * Note that rYearNums is sorted in numerical order. */ QDate Recurrence::getFirstDateInYear(const QDate &earliestDate) const { QPtrListIterator<int> it(rYearNums); switch (recurs) { case rYearlyMonth: { int day = recurStart().date().day(); int earliestYear = earliestDate.year(); int earliestMonth = earliestDate.month(); int earliestDay = earliestDate.day(); if (earliestDay > day) { // The earliest date is later in the month than the recurrence date, // so skip to the next month before starting to check if (++earliestMonth > 12) return QDate(); } for ( ; it.current(); ++it) { int month = *it.current(); if (month >= earliestMonth) { if (day <= 28 || QDate::isValid(earliestYear, month, day)) return QDate(earliestYear, month, day); if (day == 29 && month == 2) { // It's a recurrence on February 29th, in a non-leap year switch (mFeb29YearlyType) { case rMar1: return QDate(earliestYear, 3, 1); case rFeb28: if (earliestDay <= 28) return QDate(earliestYear, 2, 28); break; case rFeb29: break; } } } } break; } case rYearlyPos: { QValueList<int> dayList; int earliestYear = earliestDate.year(); int earliestMonth = earliestDate.month(); int earliestDay = earliestDate.day(); for ( ; it.current(); ++it) { int month = *it.current(); if (month >= earliestMonth) { QDate monthBegin(earliestYear, month, 1); getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek()); for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) { if (*id >= earliestDay) return monthBegin.addDays(*id - 1); } earliestDay = 1; } } break; } case rYearlyDay: { int earliestDay = earliestDate.dayOfYear(); for ( ; it.current(); ++it) { int day = *it.current(); if (day >= earliestDay && (day <= 365 || day <= earliestDate.daysInYear())) return earliestDate.addDays(day - earliestDay); } break; } } return QDate(); } /* From the recurrence yearly month list or yearly day list, get the latest * month or day in the specified year which is <= the latestDate. * Note that rYearNums is sorted in numerical order. */ QDate Recurrence::getLastDateInYear(const QDate &latestDate) const { QPtrListIterator<int> it(rYearNums); switch (recurs) { case rYearlyMonth: { int day = recurStart().date().day(); int latestYear = latestDate.year(); int latestMonth = latestDate.month(); if (latestDate.day() > day) { // The latest date is earlier in the month than the recurrence date, // so skip to the previous month before starting to check if (--latestMonth <= 0) return QDate(); } for (it.toLast(); it.current(); --it) { int month = *it.current(); if (month <= latestMonth) { if (day <= 28 || QDate::isValid(latestYear, month, day)) return QDate(latestYear, month, day); if (day == 29 && month == 2) { // It's a recurrence on February 29th, in a non-leap year switch (mFeb29YearlyType) { case rMar1: if (latestMonth >= 3) return QDate(latestYear, 3, 1); break; case rFeb28: return QDate(latestYear, 2, 28); case rFeb29: break; } } } } break; } case rYearlyPos: { QValueList<int> dayList; int latestYear = latestDate.year(); int latestMonth = latestDate.month(); int latestDay = latestDate.day(); for (it.toLast(); it.current(); --it) { int month = *it.current(); if (month <= latestMonth) { QDate monthBegin(latestYear, month, 1); getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek()); for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) { if (*id <= latestDay) return monthBegin.addDays(*id - 1); } latestDay = 31; } } break; } case rYearlyDay: { int latestDay = latestDate.dayOfYear(); for (it.toLast(); it.current(); --it) { int day = *it.current(); if (day <= latestDay) return latestDate.addDays(day - latestDay); } break; } } return QDate(); } void Recurrence::dump() const { - kdDebug() << "Recurrence::dump():" << endl; - - kdDebug() << " type: " << recurs << endl; - - kdDebug() << " rDays: " << endl; - int i; - for( i = 0; i < 7; ++i ) { - kdDebug() << " " << i << ": " - << ( rDays.testBit( i ) ? "true" : "false" ) << endl; - } + ; } |