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 );
}
예제 #2
0
/** 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;
}