コード例 #1
0
ファイル: compat.cpp プロジェクト: pvuorela/kcalcore
void CompatPre31::fixRecurrence( const Incidence::Ptr &incidence )
{
  CompatPre32::fixRecurrence( incidence );

  Recurrence *recur = incidence->recurrence();
  RecurrenceRule *r = 0;
  if ( recur ) {
    r = recur->defaultRRule();
  }
  if ( recur && r ) {
    int duration = r->duration();
    if ( duration > 0 ) {
      // Backwards compatibility for KDE < 3.1.
      // rDuration was set to the number of time periods to recur,
      // with week start always on a Monday.
      // Convert this to the number of occurrences.
      r->setDuration( -1 );
      QDate end( r->startDt().date() );
      bool doNothing = false;
      // # of periods:
      int tmp = ( duration - 1 ) * r->frequency();
      switch ( r->recurrenceType() ) {
      case RecurrenceRule::rWeekly:
      {
        end = end.addDays( tmp * 7 + 7 - end.dayOfWeek() );
        break;
      }
      case RecurrenceRule::rMonthly:
      {
        int month = end.month() - 1 + tmp;
        end.setDate( end.year() + month / 12, month % 12 + 1, 31 );
        break;
      }
      case RecurrenceRule::rYearly:
      {
        end.setDate( end.year() + tmp, 12, 31 );
        break;
      }
      default:
        doNothing = true;
        break;
      }
      if ( !doNothing ) {
        duration = r->durationTo(
          KDateTime( end, QTime( 0, 0, 0 ), incidence->dtStart().timeSpec() ) );
        r->setDuration( duration );
      }
    }

    /* addYearlyNum */
    // Dates were stored as day numbers, with a fiddle to take account of
    // leap years. Convert the day number to a month.
    QList<int> days = r->byYearDays();
    if ( !days.isEmpty() ) {
      QList<int> months = r->byMonths();
      for ( int i = 0; i < months.size(); ++i ) {
        int newmonth =
          QDate( r->startDt().date().year(), 1, 1 ).addDays( months.at( i ) - 1 ).month();
        if ( !months.contains( newmonth ) ) {
          months.append( newmonth );
        }
      }

      r->setByMonths( months );
      days.clear();
      r->setByYearDays( days );
    }
  }
}
コード例 #2
0
ファイル: karecurrence.cpp プロジェクト: serghei/kde3-kdepim
/******************************************************************************
* Must be called after presetting with a KCal::Recurrence, to convert the
* recurrence to KARecurrence types:
* - Convert hourly recurrences to minutely.
* - Remove all but the first day in yearly date recurrences.
* - Check for yearly recurrences falling on February 29th and adjust them as
*   necessary. A 29th of the month rule can be combined with either a 60th day
*   of the year rule or a last day of February rule.
*/
void KARecurrence::fix()
{
    mCachedType = -1;
    mFeb29Type = FEB29_FEB29;
    int convert = 0;
    int days[2] = { 0, 0 };
    RecurrenceRule *rrules[2];
    RecurrenceRule::List rrulelist = rRules();
    RecurrenceRule::List::ConstIterator rr = rrulelist.begin();
    for(int i = 0;  i < 2  &&  rr != rrulelist.end();  ++i, ++rr)
    {
        RecurrenceRule *rrule = *rr;
        rrules[i] = rrule;
        bool stop = true;
        int rtype = recurrenceType(rrule);
        switch(rtype)
        {
            case rHourly:
                // Convert an hourly recurrence to a minutely one
                rrule->setRecurrenceType(RecurrenceRule::rMinutely);
                rrule->setFrequency(rrule->frequency() * 60);
            // fall through to rMinutely
            case rMinutely:
            case rDaily:
            case rWeekly:
            case rMonthlyDay:
            case rMonthlyPos:
            case rYearlyPos:
                if(!convert)
                    ++rr;    // remove all rules except the first
                break;
            case rOther:
                if(dailyType(rrule))
                {
                    // it's a daily rule with BYDAYS
                    if(!convert)
                        ++rr;    // remove all rules except the first
                }
                break;
            case rYearlyDay:
            {
                // Ensure that the yearly day number is 60 (i.e. Feb 29th/Mar 1st)
                if(convert)
                {
                    // This is the second rule.
                    // Ensure that it can be combined with the first one.
                    if(days[0] != 29
                            ||  rrule->frequency() != rrules[0]->frequency()
                            ||  rrule->startDt()   != rrules[0]->startDt())
                        break;
                }
                QValueList<int> ds = rrule->byYearDays();
                if(!ds.isEmpty()  &&  ds.first() == 60)
                {
                    ++convert;    // this rule needs to be converted
                    days[i] = 60;
                    stop = false;
                    break;
                }
                break;     // not day 60, so remove this rule
            }
            case rYearlyMonth:
            {
                QValueList<int> ds = rrule->byMonthDays();
                if(!ds.isEmpty())
                {
                    int day = ds.first();
                    if(convert)
                    {
                        // This is the second rule.
                        // Ensure that it can be combined with the first one.
                        if(day == days[0]  ||  day == -1 && days[0] == 60
                                ||  rrule->frequency() != rrules[0]->frequency()
                                ||  rrule->startDt()   != rrules[0]->startDt())
                            break;
                    }
                    if(ds.count() > 1)
                    {
                        ds.clear();   // remove all but the first day
                        ds.append(day);
                        rrule->setByMonthDays(ds);
                    }
                    if(day == -1)
                    {
                        // Last day of the month - only combine if it's February
                        QValueList<int> months = rrule->byMonths();
                        if(months.count() != 1  ||  months.first() != 2)
                            day = 0;
                    }
                    if(day == 29  ||  day == -1)
                    {
                        ++convert;    // this rule may need to be converted
                        days[i] = day;
                        stop = false;
                        break;
                    }
                }
                if(!convert)
                    ++rr;
                break;
            }
            default:
                break;
        }
        if(stop)
            break;
    }

    // Remove surplus rules
    for(;  rr != rrulelist.end();  ++rr)
    {
        removeRRule(*rr);
        delete *rr;
    }

    QDate end;
    int count;
    QValueList<int> months;
    if(convert == 2)
    {
        // There are two yearly recurrence rules to combine into a February 29th recurrence.
        // Combine the two recurrence rules into a single rYearlyMonth rule falling on Feb 29th.
        // Find the duration of the two RRULEs combined, using the shorter of the two if they differ.
        if(days[0] != 29)
        {
            // Swap the two rules so that the 29th rule is the first
            RecurrenceRule *rr = rrules[0];
            rrules[0] = rrules[1];    // the 29th rule
            rrules[1] = rr;
            int d = days[0];
            days[0] = days[1];
            days[1] = d;        // the non-29th day
        }
        // If February is included in the 29th rule, remove it to avoid duplication
        months = rrules[0]->byMonths();
        if(months.remove(2))
            rrules[0]->setByMonths(months);

        count = combineDurations(rrules[0], rrules[1], end);
        mFeb29Type = (days[1] == 60) ? FEB29_MAR1 : FEB29_FEB28;
    }
    else if(convert == 1  &&  days[0] == 60)
    {
        // There is a single 60th day of the year rule.
        // Convert it to a February 29th recurrence.
        count = duration();
        if(!count)
            end = endDate();
        mFeb29Type = FEB29_MAR1;
    }
    else
        return;

    // Create the new February 29th recurrence
    setNewRecurrenceType(RecurrenceRule::rYearly, frequency());
    RecurrenceRule *rrule = defaultRRule();
    months.append(2);
    rrule->setByMonths(months);
    QValueList<int> ds;
    ds.append(29);
    rrule->setByMonthDays(ds);
    if(count)
        setDuration(count);
    else
        setEndDate(end);
}