void KCalResourceSlox::parseRecurrence( const QDomNode &node, Event *event ) { QString type; int dailyValue = -1; KDateTime end; int weeklyValue = -1; QBitArray days( 7 ); // days, starting with monday bool daysSet = false; int monthlyValueDay = -1; int monthlyValueMonth = -1; int yearlyValueDay = -1; int yearlyMonth = -1; int monthly2Recurrency = 0; int monthly2Day = 0; int monthly2ValueMonth = -1; int yearly2Recurrency = 0; int yearly2Day = 0; int yearly2Month = -1; DateList deleteExceptions; QDomNode n; for( n = node.firstChild(); !n.isNull(); n = n.nextSibling() ) { QDomElement e = n.toElement(); QString tag = e.tagName(); QString text = decodeText( e.text() ); kDebug() << tag << ":" << text; if ( tag == fieldName( RecurrenceType ) ) { type = text; } else if ( tag == "daily_value" ) { dailyValue = text.toInt(); } else if ( tag == fieldName( RecurrenceEnd ) ) { end = WebdavHandler::sloxToKDateTime( text ); } else if ( tag == "weekly_value" ) { weeklyValue = text.toInt(); } else if ( tag.left( 11 ) == "weekly_day_" ) { int day = tag.mid( 11, 1 ).toInt(); int index; if ( day == 1 ) index = 0; else index = day - 2; days.setBit( index ); } else if ( tag == "monthly_value_day" ) { monthlyValueDay = text.toInt(); } else if ( tag == "monthly_value_month" ) { monthlyValueMonth = text.toInt(); } else if ( tag == "yearly_value_day" ) { yearlyValueDay = text.toInt(); } else if ( tag == "yearly_month" ) { yearlyMonth = text.toInt(); } else if ( tag == "monthly2_recurrency" ) { monthly2Recurrency = text.toInt(); } else if ( tag == "monthly2_day" ) { monthly2Day = text.toInt(); } else if ( tag == "monthly2_value_month" ) { monthly2ValueMonth = text.toInt(); } else if ( tag == "yearly2_reccurency" ) { // this is not a typo, this is what SLOX really sends! yearly2Recurrency = text.toInt(); } else if ( tag == "yearly2_day" ) { yearly2Day = text.toInt(); } else if ( tag == "yearly2_month" ) { yearly2Month = text.toInt() + 1; // OX recurrence fields } else if ( tag == "interval" ) { dailyValue = text.toInt(); weeklyValue = text.toInt(); monthlyValueMonth = text.toInt(); monthly2ValueMonth = text.toInt(); } else if ( tag == "days" ) { int tmp = text.toInt(); // OX encodes days binary: 1=Su, 2=Mo, 4=Tu, ... for ( int i = 0; i < 7; ++i ) { if ( tmp & (1 << i) ) days.setBit( (i + 6) % 7 ); } daysSet = true; } else if ( tag == "day_in_month" ) { monthlyValueDay = text.toInt(); monthly2Recurrency = text.toInt(); yearlyValueDay = text.toInt(); yearly2Recurrency = text.toInt(); } else if ( tag == "month" ) { yearlyMonth = text.toInt() + 1; // starts at 0 yearly2Month = text.toInt() + 1; } else if ( tag == fieldName( RecurrenceDelEx ) ) { QStringList exdates = text.split( "," ); QStringList::ConstIterator it; for ( it = exdates.constBegin(); it != exdates.constEnd(); ++it ) deleteExceptions.append( WebdavHandler::sloxToKDateTime( *it ).date() ); } } if ( daysSet && type == "monthly" ) type = "monthly2"; // HACK: OX doesn't cleanly distinguish between monthly and monthly2 if ( daysSet && type == "yearly" ) type = "yearly2"; Recurrence *r = event->recurrence(); if ( type == "daily" ) { r->setDaily( dailyValue ); } else if ( type == "weekly" ) { r->setWeekly( weeklyValue, days ); } else if ( type == "monthly" ) { r->setMonthly( monthlyValueMonth ); r->addMonthlyDate( monthlyValueDay ); } else if ( type == "yearly" ) { r->setYearly( 1 ); r->addYearlyDate( yearlyValueDay ); r->addYearlyMonth( yearlyMonth ); } else if ( type == "monthly2" ) { r->setMonthly( monthly2ValueMonth ); QBitArray _days( 7 ); if ( daysSet ) _days = days; else _days.setBit( event->dtStart().date().dayOfWeek() ); r->addMonthlyPos( monthly2Recurrency, _days ); } else if ( type == "yearly2" ) { r->setYearly( 1 ); r->addYearlyMonth( yearly2Month ); QBitArray _days( 7 ); if ( daysSet ) _days = days; else _days.setBit( ( yearly2Day + 5 ) % 7 ); r->addYearlyPos( yearly2Recurrency, _days ); } r->setEndDate( end.date() ); r->setExDates( deleteExceptions ); }
/** Dissociate a single occurrence or all future occurrences from a recurring sequence. The new incidence is returned, but not automatically inserted into the calendar, which is left to the calling application */ Incidence *Calendar::dissociateOccurrence(Incidence *incidence, QDate date, bool single) { if(!incidence || !incidence->doesRecur()) return 0; Incidence *newInc = incidence->clone(); newInc->recreate(); newInc->setRelatedTo(incidence); Recurrence *recur = newInc->recurrence(); if(single) { recur->clear(); } else { // Adjust the recurrence for the future incidences. In particular // adjust the "end after n occurrences" rules! "No end date" and "end by ..." // don't need to be modified. int duration = recur->duration(); if(duration > 0) { int doneduration = recur->durationTo(date.addDays(-1)); if(doneduration >= duration) { kdDebug(5850) << "The dissociated event already occurred more often " << "than it was supposed to ever occur. ERROR!" << endl; recur->clear(); } else { recur->setDuration(duration - doneduration); } } } // Adjust the date of the incidence if(incidence->type() == "Event") { Event *ev = static_cast<Event *>(newInc); QDateTime start(ev->dtStart()); int daysTo = start.date().daysTo(date); ev->setDtStart(start.addDays(daysTo)); ev->setDtEnd(ev->dtEnd().addDays(daysTo)); } else if(incidence->type() == "Todo") { Todo *td = static_cast<Todo *>(newInc); bool haveOffset = false; int daysTo = 0; if(td->hasDueDate()) { QDateTime due(td->dtDue()); daysTo = due.date().daysTo(date); td->setDtDue(due.addDays(daysTo), true); haveOffset = true; } if(td->hasStartDate()) { QDateTime start(td->dtStart()); if(!haveOffset) daysTo = start.date().daysTo(date); td->setDtStart(start.addDays(daysTo)); haveOffset = true; } } recur = incidence->recurrence(); if(recur) { if(single) { recur->addExDate(date); } else { // Make sure the recurrence of the past events ends // at the corresponding day recur->setEndDate(date.addDays(-1)); } } return newInc; }