summaryrefslogtreecommitdiffabout
path: root/libkcal
Side-by-side diff
Diffstat (limited to 'libkcal') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/icalformatimpl.cpp20
-rw-r--r--libkcal/recurrence.cpp17
-rw-r--r--libkcal/recurrence.h6
3 files changed, 30 insertions, 13 deletions
diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp
index 32a1337..964ffe3 100644
--- a/libkcal/icalformatimpl.cpp
+++ b/libkcal/icalformatimpl.cpp
@@ -1011,937 +1011,941 @@ FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy)
break;
default:
kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
<< endl;
break;
}
p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY);
}
return freebusy;
}
Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal)
{
Journal *journal = new Journal;
readIncidence(vjournal,journal);
return journal;
}
Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee)
{
icalparameter *p = 0;
QString email = QString::fromUtf8(icalproperty_get_attendee(attendee));
QString name;
QString uid = QString::null;
p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER);
if (p) {
name = QString::fromUtf8(icalparameter_get_cn(p));
} else {
}
bool rsvp=false;
p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER);
if (p) {
icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p);
if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true;
}
Attendee::PartStat status = Attendee::NeedsAction;
p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER);
if (p) {
icalparameter_partstat partStatParameter = icalparameter_get_partstat(p);
switch(partStatParameter) {
default:
case ICAL_PARTSTAT_NEEDSACTION:
status = Attendee::NeedsAction;
break;
case ICAL_PARTSTAT_ACCEPTED:
status = Attendee::Accepted;
break;
case ICAL_PARTSTAT_DECLINED:
status = Attendee::Declined;
break;
case ICAL_PARTSTAT_TENTATIVE:
status = Attendee::Tentative;
break;
case ICAL_PARTSTAT_DELEGATED:
status = Attendee::Delegated;
break;
case ICAL_PARTSTAT_COMPLETED:
status = Attendee::Completed;
break;
case ICAL_PARTSTAT_INPROCESS:
status = Attendee::InProcess;
break;
}
}
Attendee::Role role = Attendee::ReqParticipant;
p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER);
if (p) {
icalparameter_role roleParameter = icalparameter_get_role(p);
switch(roleParameter) {
case ICAL_ROLE_CHAIR:
role = Attendee::Chair;
break;
default:
case ICAL_ROLE_REQPARTICIPANT:
role = Attendee::ReqParticipant;
break;
case ICAL_ROLE_OPTPARTICIPANT:
role = Attendee::OptParticipant;
break;
case ICAL_ROLE_NONPARTICIPANT:
role = Attendee::NonParticipant;
break;
}
}
p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER);
uid = icalparameter_get_xvalue(p);
// This should be added, but there seems to be a libical bug here.
/*while (p) {
// if (icalparameter_get_xname(p) == "X-UID") {
uid = icalparameter_get_xvalue(p);
p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER);
} */
return new Attendee( name, email, rsvp, status, role, uid );
}
Attachment *ICalFormatImpl::readAttachment(icalproperty *attach)
{
icalattach *a = icalproperty_get_attach(attach);
icalparameter_value v = ICAL_VALUE_NONE;
icalparameter_encoding e = ICAL_ENCODING_NONE;
Attachment *attachment = 0;
/*
icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER);
if (vp)
v = icalparameter_get_value(vp);
icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER);
if (ep)
e = icalparameter_get_encoding(ep);
*/
int isurl = icalattach_get_is_url (a);
if (isurl == 0)
attachment = new Attachment((const char*)icalattach_get_data(a));
else {
attachment = new Attachment(QString(icalattach_get_url(a)));
}
icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER);
if (p)
attachment->setMimeType(QString(icalparameter_get_fmttype(p)));
return attachment;
}
#include <qtextcodec.h>
void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence)
{
readIncidenceBase(parent,incidence);
icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
bool readrec = false;
const char *text;
int intvalue;
icaltimetype icaltime;
icaldurationtype icalduration;
struct icalrecurrencetype rectype;
QStringList categories;
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_CREATED_PROPERTY:
icaltime = icalproperty_get_created(p);
incidence->setCreated(readICalDateTime(icaltime));
break;
case ICAL_SEQUENCE_PROPERTY: // sequence
intvalue = icalproperty_get_sequence(p);
incidence->setRevision(intvalue);
break;
case ICAL_LASTMODIFIED_PROPERTY: // last modification date
icaltime = icalproperty_get_lastmodified(p);
incidence->setLastModified(readICalDateTime(icaltime));
break;
case ICAL_DTSTART_PROPERTY: // start date and time
icaltime = icalproperty_get_dtstart(p);
if (icaltime.is_date) {
incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
incidence->setFloats(true);
} else {
incidence->setDtStart(readICalDateTime(icaltime));
}
break;
case ICAL_DURATION_PROPERTY: // start date and time
icalduration = icalproperty_get_duration(p);
incidence->setDuration(readICalDuration(icalduration));
break;
case ICAL_DESCRIPTION_PROPERTY: // description
text = icalproperty_get_description(p);
incidence->setDescription(QString::fromUtf8(text));
break;
case ICAL_SUMMARY_PROPERTY: // summary
{
text = icalproperty_get_summary(p);
incidence->setSummary(QString::fromUtf8(text));
}
break;
case ICAL_STATUS_PROPERTY: // summary
{
if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) )
incidence->setCancelled( true );
}
break;
case ICAL_LOCATION_PROPERTY: // location
text = icalproperty_get_location(p);
incidence->setLocation(QString::fromUtf8(text));
break;
#if 0
// status
if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) {
incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
else
incidence->setStatus("NEEDS ACTION");
#endif
case ICAL_PRIORITY_PROPERTY: // priority
intvalue = icalproperty_get_priority(p);
incidence->setPriority(intvalue);
break;
case ICAL_CATEGORIES_PROPERTY: // categories
text = icalproperty_get_categories(p);
categories.append(QString::fromUtf8(text));
break;
//*******************************************
case ICAL_RRULE_PROPERTY:
// we do need (maybe )start datetime of incidence for recurrence
// such that we can read recurrence only after we read incidence completely
readrec = true;
rectype = icalproperty_get_rrule(p);
break;
case ICAL_EXDATE_PROPERTY:
icaltime = icalproperty_get_exdate(p);
incidence->addExDate(readICalDate(icaltime));
break;
case ICAL_CLASS_PROPERTY: {
int inttext = icalproperty_get_class(p);
if (inttext == ICAL_CLASS_PUBLIC ) {
incidence->setSecrecy(Incidence::SecrecyPublic);
} else if (inttext == ICAL_CLASS_CONFIDENTIAL ) {
incidence->setSecrecy(Incidence::SecrecyConfidential);
} else {
incidence->setSecrecy(Incidence::SecrecyPrivate);
}
}
break;
case ICAL_ATTACH_PROPERTY: // attachments
incidence->addAttachment(readAttachment(p));
break;
default:
// kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
// << endl;
break;
}
p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
}
if ( readrec ) {
readRecurrenceRule(rectype,incidence);
}
// kpilot stuff
// TODO: move this application-specific code to kpilot
QString kp = incidence->nonKDECustomProperty("X-PILOTID");
if (!kp.isNull()) {
incidence->setPilotId(kp.toInt());
}
kp = incidence->nonKDECustomProperty("X-PILOTSTAT");
if (!kp.isNull()) {
incidence->setSyncStatus(kp.toInt());
}
kp = incidence->nonKDECustomProperty("X-ZAURUSID");
if (!kp.isNull()) {
incidence->setZaurusId(kp.toInt());
}
kp = incidence->nonKDECustomProperty("X-ZAURUSUID");
if (!kp.isNull()) {
incidence->setZaurusUid(kp.toInt());
}
kp = incidence->nonKDECustomProperty("X-ZAURUSSTAT");
if (!kp.isNull()) {
incidence->setZaurusStat(kp.toInt());
}
// Cancel backwards compatibility mode for subsequent changes by the application
incidence->recurrence()->setCompatVersion();
// add categories
incidence->setCategories(categories);
// iterate through all alarms
for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT);
alarm;
alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) {
readAlarm(alarm,incidence);
}
}
void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
{
icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_UID_PROPERTY: // unique id
incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p)));
break;
case ICAL_ORGANIZER_PROPERTY: // organizer
incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p)));
break;
case ICAL_ATTENDEE_PROPERTY: // attendee
incidenceBase->addAttendee(readAttendee(p));
break;
default:
break;
}
p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
}
// custom properties
readCustomProperties(parent, incidenceBase);
}
void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties)
{
QMap<QCString, QString> customProperties;
icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
while (p) {
QString value = QString::fromUtf8(icalproperty_get_x(p));
customProperties[icalproperty_get_x_name(p)] = value;
//qDebug("ICalFormatImpl::readCustomProperties %s %s",value.latin1(), icalproperty_get_x_name(p) );
p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
}
properties->setCustomProperties(customProperties);
}
void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence)
{
// kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
Recurrence *recur = incidence->recurrence();
recur->setCompatVersion(mCalendarVersion);
recur->unsetRecurs();
struct icalrecurrencetype r = rrule;
dumpIcalRecurrence(r);
readRecurrence( r, recur, incidence);
}
void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence)
{
int wkst;
int index = 0;
short day = 0;
QBitArray qba(7);
int frequ = r.freq;
int interv = r.interval;
// preprocessing for odd recurrence definitions
if ( r.freq == ICAL_MONTHLY_RECURRENCE ) {
if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
interv = 12;
}
}
if ( r.freq == ICAL_YEARLY_RECURRENCE ) {
if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
frequ = ICAL_MONTHLY_RECURRENCE;
- interv = 12;
+ interv = 12* r.interval;
}
}
switch (frequ) {
case ICAL_MINUTELY_RECURRENCE:
if (!icaltime_is_null_time(r.until)) {
recur->setMinutely(interv,readICalDateTime(r.until));
} else {
if (r.count == 0)
recur->setMinutely(interv,-1);
else
recur->setMinutely(interv,r.count);
}
break;
case ICAL_HOURLY_RECURRENCE:
if (!icaltime_is_null_time(r.until)) {
recur->setHourly(interv,readICalDateTime(r.until));
} else {
if (r.count == 0)
recur->setHourly(interv,-1);
else
recur->setHourly(interv,r.count);
}
break;
case ICAL_DAILY_RECURRENCE:
if (!icaltime_is_null_time(r.until)) {
recur->setDaily(interv,readICalDate(r.until));
} else {
if (r.count == 0)
recur->setDaily(interv,-1);
else
recur->setDaily(interv,r.count);
}
break;
case ICAL_WEEKLY_RECURRENCE:
// kdDebug(5800) << "WEEKLY_RECURRENCE" << endl;
wkst = (r.week_start + 5)%7 + 1;
if (!icaltime_is_null_time(r.until)) {
recur->setWeekly(interv,qba,readICalDate(r.until),wkst);
} else {
if (r.count == 0)
recur->setWeekly(interv,qba,-1,wkst);
else
recur->setWeekly(interv,qba,r.count,wkst);
}
if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) {
int wday = incidence->dtStart().date().dayOfWeek ()-1;
//qDebug("weekly error found ");
qba.setBit(wday);
} else {
while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << " " << day << endl;
qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
}
}
break;
case ICAL_MONTHLY_RECURRENCE:
if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
if (!icaltime_is_null_time(r.until)) {
recur->setMonthly(Recurrence::rMonthlyPos,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setMonthly(Recurrence::rMonthlyPos,interv,-1);
else
recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count);
}
bool useSetPos = false;
short pos = 0;
while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << "----a " << index << ": " << day << endl;
pos = icalrecurrencetype_day_position(day);
if (pos) {
day = icalrecurrencetype_day_day_of_week(day);
QBitArray ba(7); // don't wipe qba
ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
recur->addMonthlyPos(pos,ba);
} else {
qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
useSetPos = true;
}
}
if (useSetPos) {
if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addMonthlyPos(r.by_set_pos[0],qba);
}
}
} else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
if (!icaltime_is_null_time(r.until)) {
recur->setMonthly(Recurrence::rMonthlyDay,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setMonthly(Recurrence::rMonthlyDay,interv,-1);
else
recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count);
}
while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << "----b " << day << endl;
recur->addMonthlyDay(day);
}
}
break;
case ICAL_YEARLY_RECURRENCE:
if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
+ qDebug(" YEARLY DAY OF YEAR");
if (!icaltime_is_null_time(r.until)) {
recur->setYearly(Recurrence::rYearlyDay,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setYearly(Recurrence::rYearlyDay,interv,-1);
else
recur->setYearly(Recurrence::rYearlyDay,interv,r.count);
}
while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addYearlyNum(day);
}
} else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) {
if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
+ qDebug("YEARLY POS NOT SUPPORTED BY GUI");
if (!icaltime_is_null_time(r.until)) {
recur->setYearly(Recurrence::rYearlyPos,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setYearly(Recurrence::rYearlyPos,interv,-1);
else
recur->setYearly(Recurrence::rYearlyPos,interv,r.count);
}
bool useSetPos = false;
short pos = 0;
while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
// kdDebug(5800) << "----a " << index << ": " << day << endl;
pos = icalrecurrencetype_day_position(day);
if (pos) {
day = icalrecurrencetype_day_day_of_week(day);
QBitArray ba(7); // don't wipe qba
ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
recur->addYearlyMonthPos(pos,ba);
} else {
qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
useSetPos = true;
}
}
if (useSetPos) {
if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
recur->addYearlyMonthPos(r.by_set_pos[0],qba);
}
}
} else {
+ qDebug("YEARLY MONTH ");
if (!icaltime_is_null_time(r.until)) {
recur->setYearly(Recurrence::rYearlyMonth,interv,
readICalDate(r.until));
} else {
if (r.count == 0)
recur->setYearly(Recurrence::rYearlyMonth,interv,-1);
else
recur->setYearly(Recurrence::rYearlyMonth,interv,r.count);
}
- }
- if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
- index = 0;
- while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
- recur->addYearlyNum(day);
+ if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
+ index = 0;
+ while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
+ recur->addYearlyNum(day);
+ }
+ } else {
+ recur->addYearlyNum(incidence->dtStart().date().month());
}
- } else {
- recur->addYearlyNum(incidence->dtStart().date().month());
}
+
}
break;
default:
;
break;
}
}
void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence)
{
//kdDebug(5800) << "Read alarm for " << incidence->summary() << endl;
Alarm* ialarm = incidence->newAlarm();
ialarm->setRepeatCount(0);
ialarm->setEnabled(true);
// Determine the alarm's action type
icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY);
if ( !p ) {
return;
}
icalproperty_action action = icalproperty_get_action(p);
Alarm::Type type = Alarm::Display;
switch ( action ) {
case ICAL_ACTION_DISPLAY: type = Alarm::Display; break;
case ICAL_ACTION_AUDIO: type = Alarm::Audio; break;
case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break;
case ICAL_ACTION_EMAIL: type = Alarm::Email; break;
default:
;
return;
}
ialarm->setType(type);
p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY);
while (p) {
icalproperty_kind kind = icalproperty_isa(p);
switch (kind) {
case ICAL_TRIGGER_PROPERTY: {
icaltriggertype trigger = icalproperty_get_trigger(p);
if (icaltime_is_null_time(trigger.time)) {
if (icaldurationtype_is_null_duration(trigger.duration)) {
kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl;
} else {
Duration duration = icaldurationtype_as_int( trigger.duration );
icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER);
if (param && icalparameter_get_related(param) == ICAL_RELATED_END)
ialarm->setEndOffset(duration);
else
ialarm->setStartOffset(duration);
}
} else {
ialarm->setTime(readICalDateTime(trigger.time));
}
break;
}
case ICAL_DURATION_PROPERTY: {
icaldurationtype duration = icalproperty_get_duration(p);
ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60);
break;
}
case ICAL_REPEAT_PROPERTY:
ialarm->setRepeatCount(icalproperty_get_repeat(p));
break;
// Only in DISPLAY and EMAIL and PROCEDURE alarms
case ICAL_DESCRIPTION_PROPERTY: {
QString description = QString::fromUtf8(icalproperty_get_description(p));
switch ( action ) {
case ICAL_ACTION_DISPLAY:
ialarm->setText( description );
break;
case ICAL_ACTION_PROCEDURE:
ialarm->setProgramArguments( description );
break;
case ICAL_ACTION_EMAIL:
ialarm->setMailText( description );
break;
default:
break;
}
break;
}
// Only in EMAIL alarm
case ICAL_SUMMARY_PROPERTY:
ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p)));
break;
// Only in EMAIL alarm
case ICAL_ATTENDEE_PROPERTY: {
QString email = QString::fromUtf8(icalproperty_get_attendee(p));
QString name;
icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER);
if (param) {
name = QString::fromUtf8(icalparameter_get_cn(param));
}
ialarm->addMailAddress(Person(name, email));
break;
}
// Only in AUDIO and EMAIL and PROCEDURE alarms
case ICAL_ATTACH_PROPERTY: {
icalattach *attach = icalproperty_get_attach(p);
QString url = QFile::decodeName(icalattach_get_url(attach));
switch ( action ) {
case ICAL_ACTION_AUDIO:
ialarm->setAudioFile( url );
break;
case ICAL_ACTION_PROCEDURE:
ialarm->setProgramFile( url );
break;
case ICAL_ACTION_EMAIL:
ialarm->addMailAttachment( url );
break;
default:
break;
}
break;
}
default:
break;
}
p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY);
}
// custom properties
readCustomProperties(alarm, ialarm);
// TODO: check for consistency of alarm properties
}
icaltimetype ICalFormatImpl::writeICalDate(const QDate &date)
{
icaltimetype t;
t.year = date.year();
t.month = date.month();
t.day = date.day();
t.hour = 0;
t.minute = 0;
t.second = 0;
t.is_date = 1;
t.is_utc = 0;
t.zone = 0;
return t;
}
icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt )
{
icaltimetype t;
t.is_date = 0;
t.zone = 0;
QDateTime datetime;
if ( mParent->utc() ) {
int offset = KGlobal::locale()->localTimeOffset( dt );
datetime = dt.addSecs ( -offset*60);
t.is_utc = 1;
}
else {
datetime = dt;
t.is_utc = 0;
}
t.year = datetime.date().year();
t.month = datetime.date().month();
t.day = datetime.date().day();
t.hour = datetime.time().hour();
t.minute = datetime.time().minute();
t.second = datetime.time().second();
//qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
// if ( mParent->utc() ) {
// datetime = KGlobal::locale()->localTime( dt );
// qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
// if (mParent->timeZoneId().isEmpty())
// t = icaltime_as_utc(t, 0);
// else
// t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit());
// }
return t;
}
QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t)
{
QDateTime dt (QDate(t.year,t.month,t.day),
QTime(t.hour,t.minute,t.second) );
if (t.is_utc) {
int offset = KGlobal::locale()->localTimeOffset( dt );
dt = dt.addSecs ( offset*60);
}
return dt;
}
QDate ICalFormatImpl::readICalDate(icaltimetype t)
{
return QDate(t.year,t.month,t.day);
}
icaldurationtype ICalFormatImpl::writeICalDuration(int seconds)
{
icaldurationtype d;
d.weeks = seconds % gSecondsPerWeek;
seconds -= d.weeks * gSecondsPerWeek;
d.days = seconds % gSecondsPerDay;
seconds -= d.days * gSecondsPerDay;
d.hours = seconds % gSecondsPerHour;
seconds -= d.hours * gSecondsPerHour;
d.minutes = seconds % gSecondsPerMinute;
seconds -= d.minutes * gSecondsPerMinute;
d.seconds = seconds;
d.is_neg = 0;
return d;
}
int ICalFormatImpl::readICalDuration(icaldurationtype d)
{
int result = 0;
result += d.weeks * gSecondsPerWeek;
result += d.days * gSecondsPerDay;
result += d.hours * gSecondsPerHour;
result += d.minutes * gSecondsPerMinute;
result += d.seconds;
if (d.is_neg) result *= -1;
return result;
}
icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal)
{
icalcomponent *calendar;
// Root component
calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
icalproperty *p;
// Product Identifier
p = icalproperty_new_prodid(CalFormat::productId().utf8());
icalcomponent_add_property(calendar,p);
// TODO: Add time zone
// iCalendar version (2.0)
p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION));
icalcomponent_add_property(calendar,p);
// Custom properties
if( cal != 0 )
writeCustomProperties(calendar, cal);
return calendar;
}
// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
// and break it down from its tree-like format into the dictionary format
// that is used internally in the ICalFormatImpl.
bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar)
{
// this function will populate the caldict dictionary and other event
// lists. It turns vevents into Events and then inserts them.
if (!calendar) return false;
// TODO: check for METHOD
#if 0
if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) {
char *methodType = 0;
methodType = fakeCString(vObjectUStringZValue(curVO));
if (mEnableDialogs)
KMessageBox::information(mTopWidget,
i18n("This calendar is an iTIP transaction of type \"%1\".")
.arg(methodType),
i18n("%1: iTIP Transaction").arg(CalFormat::application()));
delete methodType;
}
#endif
icalproperty *p;
p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY);
if (!p) {
// TODO: does no PRODID really matter?
// mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
// return false;
mLoadedProductId = "";
mCalendarVersion = 0;
} else {
mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p));
mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId);
delete mCompat;
mCompat = CompatFactory::createCompat( mLoadedProductId );
}
// TODO: check for unknown PRODID
#if 0
if (!mCalendarVersion
&& CalFormat::productId() != mLoadedProductId) {
// warn the user that we might have trouble reading non-known calendar.
if (mEnableDialogs)
KMessageBox::information(mTopWidget,
i18n("This vCalendar file was not created by KOrganizer "
"or any other product we support. Loading anyway..."),
i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application()));
}
#endif
p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY);
if (!p) {
mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
return false;
} else {
const char *version = icalproperty_get_version(p);
if (strcmp(version,"1.0") == 0) {
mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1,
i18n("Expected iCalendar format")));
return false;
} else if (strcmp(version,"2.0") != 0) {
mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
return false;
}
}
// TODO: check for calendar format version
#if 0
// warn the user we might have trouble reading this unknown version.
if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
if (strcmp(_VCAL_VERSION, s) != 0)
if (mEnableDialogs)
KMessageBox::sorry(mTopWidget,
i18n("This vCalendar file has version %1.\n"
"We only support %2.")
.arg(s).arg(_VCAL_VERSION),
i18n("%1: Unknown vCalendar Version").arg(CalFormat::application()));
deleteStr(s);
}
#endif
// custom properties
readCustomProperties(calendar, cal);
// TODO: set time zone
#if 0
// set the time zone
if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
cal->setTimeZone(s);
deleteStr(s);
}
#endif
// Store all events with a relatedTo property in a list for post-processing
mEventsRelate.clear();
mTodosRelate.clear();
// TODO: make sure that only actually added ecvens go to this lists.
icalcomponent *c;
// Iterate through all todos
c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT);
while (c) {
// kdDebug(5800) << "----Todo found" << endl;
Todo *todo = readTodo(c);
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp
index 5fc5d1f..dd74e10 100644
--- a/libkcal/recurrence.cpp
+++ b/libkcal/recurrence.cpp
@@ -273,840 +273,853 @@ QDate Recurrence::endDate() const
case rDaily:
return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
case rWeekly:
count = weeklyCalc(END_DATE_AND_COUNT, end);
break;
case rMonthlyPos:
case rMonthlyDay:
count = monthlyCalc(END_DATE_AND_COUNT, end);
break;
case rYearlyMonth:
count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
break;
case rYearlyDay:
count = yearlyDayCalc(END_DATE_AND_COUNT, end);
break;
case rYearlyPos:
count = yearlyPosCalc(END_DATE_AND_COUNT, end);
break;
default:
// catch-all. Should never get here.
kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
break;
}
}
if (!count)
return QDate(); // error - there is no recurrence
return end;
}
QDateTime Recurrence::endDateTime() const
{
int count = 0;
QDate end;
if (recurs != rNone) {
if (rDuration < 0)
return QDateTime(); // infinite recurrence
if (rDuration == 0)
return rEndDateTime;
// The end date is determined by the recurrence count
QDate dStart = mRecurStart.date();
switch (recurs)
{
case rMinutely:
return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60);
case rHourly:
return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600);
case rDaily:
return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
case rWeekly:
count = weeklyCalc(END_DATE_AND_COUNT, end);
break;
case rMonthlyPos:
case rMonthlyDay:
count = monthlyCalc(END_DATE_AND_COUNT, end);
break;
case rYearlyMonth:
count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
break;
case rYearlyDay:
count = yearlyDayCalc(END_DATE_AND_COUNT, end);
break;
case rYearlyPos:
count = yearlyPosCalc(END_DATE_AND_COUNT, end);
break;
default:
// catch-all. Should never get here.
kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
break;
}
}
if (!count)
return QDateTime(); // error - there is no recurrence
return QDateTime(end, mRecurStart.time());
}
int Recurrence::durationTo(const QDate &date) const
{
QDate d = date;
return recurCalc(COUNT_TO_DATE, d);
}
int Recurrence::durationTo(const QDateTime &datetime) const
{
QDateTime dt = datetime;
return recurCalc(COUNT_TO_DATE, dt);
}
void Recurrence::unsetRecurs()
{
if (mRecurReadOnly) return;
recurs = rNone;
rMonthPositions.clear();
rMonthDays.clear();
rYearNums.clear();
}
void Recurrence::setRecurStart(const QDateTime &start)
{
mRecurStart = start;
mFloats = false;
switch (recurs)
{
case rMinutely:
case rHourly:
break;
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos:
default:
rEndDateTime.setTime(start.time());
break;
}
}
void Recurrence::setRecurStart(const QDate &start)
{
mRecurStart.setDate(start);
mRecurStart.setTime(QTime(0,0,0));
switch (recurs)
{
case rMinutely:
case rHourly:
break;
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos:
default:
mFloats = true;
break;
}
}
void Recurrence::setFloats(bool f)
{
switch (recurs)
{
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos:
break;
case rMinutely:
case rHourly:
default:
return; // can't set sub-daily to floating
}
mFloats = f;
if (f) {
mRecurStart.setTime(QTime(0,0,0));
rEndDateTime.setTime(QTime(0,0,0));
}
}
int Recurrence::frequency() const
{
return rFreq;
}
int Recurrence::duration() const
{
return rDuration;
}
void Recurrence::setDuration(int _rDuration)
{
if (mRecurReadOnly) return;
if (_rDuration > 0) {
rDuration = _rDuration;
// Compatibility mode is only needed when reading the calendar in ICalFormatImpl,
// so explicitly setting the duration means no backwards compatibility is needed.
mCompatDuration = 0;
}
}
QString Recurrence::endDateStr(bool shortfmt) const
{
return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt);
}
const QBitArray &Recurrence::days() const
{
return rDays;
}
const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const
{
return rMonthPositions;
}
const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const
{
return rMonthPositions;
}
const QPtrList<int> &Recurrence::monthDays() const
{
return rMonthDays;
}
void Recurrence::setMinutely(int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
setDailySub(rMinutely, _rFreq, _rDuration);
}
void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime)
{
if (mRecurReadOnly) return;
rEndDateTime = _rEndDateTime;
setDailySub(rMinutely, _rFreq, 0);
}
void Recurrence::setHourly(int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
setDailySub(rHourly, _rFreq, _rDuration);
}
void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime)
{
if (mRecurReadOnly) return;
rEndDateTime = _rEndDateTime;
setDailySub(rHourly, _rFreq, 0);
}
void Recurrence::setDaily(int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
setDailySub(rDaily, _rFreq, _rDuration);
}
void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate)
{
if (mRecurReadOnly) return;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
setDailySub(rDaily, _rFreq, 0);
}
void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
int _rDuration, int _rWeekStart)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
recurs = rWeekly;
rFreq = _rFreq;
rDays = _rDays;
rWeekStart = _rWeekStart;
rDuration = _rDuration;
if (mCompatVersion < 310 && _rDuration > 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.
mCompatDuration = _rDuration;
int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek());
QDate end(mRecurStart.date().addDays(weeks * rFreq));
rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly
rDuration = weeklyCalc(COUNT_TO_DATE, end);
} else {
mCompatDuration = 0;
}
rMonthPositions.clear();
rMonthDays.clear();
if (mParent) mParent->updated();
}
void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
const QDate &_rEndDate, int _rWeekStart)
{
if (mRecurReadOnly) return;
recurs = rWeekly;
rFreq = _rFreq;
rDays = _rDays;
rWeekStart = _rWeekStart;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
rDuration = 0; // set to 0 because there is an end date
mCompatDuration = 0;
rMonthPositions.clear();
rMonthDays.clear();
rYearNums.clear();
if (mParent) mParent->updated();
}
void Recurrence::setMonthly(short type, int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
recurs = type;
rFreq = _rFreq;
rDuration = _rDuration;
if (mCompatVersion < 310)
mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
rYearNums.clear();
if (mParent) mParent->updated();
}
void Recurrence::setMonthly(short type, int _rFreq,
const QDate &_rEndDate)
{
if (mRecurReadOnly) return;
recurs = type;
rFreq = _rFreq;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
rDuration = 0; // set to 0 because there is an end date
mCompatDuration = 0;
rYearNums.clear();
if (mParent) mParent->updated();
}
void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays)
{
if (recurs == rMonthlyPos)
addMonthlyPos_(_rPos, _rDays);
}
void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays)
{
if (mRecurReadOnly
|| _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number
return;
for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) {
int itPos = it->negative ? -it->rPos : it->rPos;
if (_rPos == itPos) {
// This week is already in the list.
// Combine the specified days with those in the list.
it->rDays |= _rDays;
if (mParent) mParent->updated();
return;
}
}
// Add the new position to the list
rMonthPos *tmpPos = new rMonthPos;
if (_rPos > 0) {
tmpPos->rPos = _rPos;
tmpPos->negative = false;
} else {
tmpPos->rPos = -_rPos; // take abs()
tmpPos->negative = true;
}
tmpPos->rDays = _rDays;
tmpPos->rDays.detach();
rMonthPositions.append(tmpPos);
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.
int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
int month = mRecurStart.date().month() - 1 + monthsAhead;
QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
rDuration = recurCalc(COUNT_TO_DATE, end);
}
if (mParent) mParent->updated();
}
void Recurrence::addMonthlyDay(short _rDay)
{
- if (mRecurReadOnly || recurs != rMonthlyDay
+ if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth)
|| _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number
return;
for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) {
if (_rDay == *it)
return; // this day is already in the list - avoid duplication
}
int *tmpDay = new int;
*tmpDay = _rDay;
rMonthDays.append(tmpDay);
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.
int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
int month = mRecurStart.date().month() - 1 + monthsAhead;
QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
rDuration = recurCalc(COUNT_TO_DATE, end);
}
if (mParent) mParent->updated();
}
void Recurrence::setYearly(int type, int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
if (mCompatVersion < 310)
mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration);
}
void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate)
{
if (mRecurReadOnly) return;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
mCompatDuration = 0;
setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0);
}
void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
if (mCompatVersion < 310)
mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
setYearly_(rYearlyMonth, type, _rFreq, _rDuration);
}
void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate)
{
if (mRecurReadOnly) return;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
mCompatDuration = 0;
setYearly_(rYearlyMonth, type, _rFreq, 0);
}
void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays)
{
if (recurs == rYearlyPos)
addMonthlyPos_(_rPos, _rDays);
}
const QPtrList<int> &Recurrence::yearNums() const
{
return rYearNums;
}
-
+void Recurrence::addYearlyMonth(short _rPos )
+{
+ if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number
+ return;
+ rMonthPos *tmpPos = new rMonthPos;
+ if ( _rPos > 0) {
+ tmpPos->rPos = _rPos;
+ tmpPos->negative = false;
+ } else {
+ tmpPos->rPos = -_rPos; // take abs()
+ tmpPos->negative = true;
+ }
+ rMonthPositions.append(tmpPos);
+}
void Recurrence::addYearlyNum(short _rNum)
{
if (mRecurReadOnly
|| (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos)
|| _rNum <= 0) // invalid day/month number
return;
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:
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));
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;
}
}
diff --git a/libkcal/recurrence.h b/libkcal/recurrence.h
index a0f6d84..b13d14f 100644
--- a/libkcal/recurrence.h
+++ b/libkcal/recurrence.h
@@ -1,401 +1,401 @@
/*
This file is part of libkcal.
Copyright (c) 1998 Preston Brown
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
Copyright (c) 2002 David Jarvie <software@astrojar.org.uk>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef KCAL_RECURRENCE_H
#define KCAL_RECURRENCE_H
#include <qstring.h>
#include <qbitarray.h>
#include <qptrlist.h>
namespace KCal {
class Incidence;
/**
This class represents a recurrence rule for a calendar incidence.
*/
class Recurrence
{
public:
/** enumeration for describing how an event recurs, if at all. */
enum { rNone = 0, rMinutely = 0x001, rHourly = 0x0002, rDaily = 0x0003,
rWeekly = 0x0004, rMonthlyPos = 0x0005, rMonthlyDay = 0x0006,
rYearlyMonth = 0x0007, rYearlyDay = 0x0008, rYearlyPos = 0x0009 };
/** Enumeration for specifying what date yearly recurrences of February 29th occur
* in non-leap years. */
enum Feb29Type {
rMar1, // recur on March 1st (default)
rFeb28, // recur on February 28th
rFeb29 // only recur on February 29th, i.e. don't recur in non-leap years
};
/** structure for Recurs rMonthlyPos */
struct rMonthPos {
QBitArray rDays;
short rPos;
bool negative;
};
Recurrence(Incidence *parent, int compatVersion = 0);
Recurrence(const Recurrence&, Incidence *parent);
~Recurrence();
bool operator==( const Recurrence& ) const;
bool operator!=( const Recurrence& r ) const { return !operator==(r); }
Incidence *parent() { return mParent; }
/** Return the start of the recurrence */
QDateTime recurStart() const { return mRecurStart; }
/** Returns the number of exception dates for the recurrence */
int recurExDatesCount() const { return mRecurExDatesCount; }
/** Set start of recurrence, as a date and time. */
void setRecurStart(const QDateTime &start);
/** Set start of recurrence, as a date with no time.
* Recurrence types which are sub-daily (e.g. rHourly) always have a time;
* the time is set to 00:00:00 in these cases. */
void setRecurStart(const QDate &start);
/** Set whether the recurrence has no time, just a date.
* Recurrence types which are sub-daily (e.g. rHourly) always have a time
* and cannot be set to float.
* N.B. This property is derived by default from the parent incidence,
* or according to whether a time is specified in setRecurStart(). */
void setFloats(bool f);
/**
Returns whether the recurrence has no time, just a date.
*/
bool doesFloat() const {
return mFloats;
}
/** Set if recurrence is read-only or can be changed. */
void setRecurReadOnly(bool readOnly) { mRecurReadOnly = readOnly; }
bool recurReadOnly() const
{
return mRecurReadOnly;
}
/** Set number of exception dates. */
void setRecurExDatesCount(int count) { if (count >= 0) mRecurExDatesCount = count; }
/** Set the calendar file version for backwards compatibility.
* @var version is the KOrganizer/libkcal version, e.g. 220 for KDE 2.2.0.
* Specify version = 0 to cancel compatibility mode.
*/
void setCompatVersion(int version = 0);
/** Returns the event's recurrence status. See the enumeration at the top
* of this file for possible values. */
ushort doesRecur() const;
/** Returns true if the date specified is one on which the event will
* recur. */
bool recursOnPure(const QDate &qd) const;
/** Returns true if the date/time specified is one at which the event will
* recur. Times are rounded down to the nearest minute to determine the result. */
bool recursAtPure(const QDateTime &) const;
/** Turns off recurrence for the event. */
void unsetRecurs();
/** Returns the date of the next recurrence, after the specified date.
* @var preDate the date after which to find the recurrence.
* @var last if 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 getNextDate(const QDate& preDate, bool* last = 0) const;
/** Returns the date and time of the next recurrence, after the specified date/time.
* If the recurrence has no time, the next date after the specified date is returned.
* @var preDate the date/time after which to find the recurrence.
* @var last if non-null, *last is set to true if the next recurrence is the
* last recurrence, else false.
* Reply = date/time of next recurrence, or invalid date if none.
*/
QDateTime getNextDateTime(const QDateTime& preDateTime, bool* last = 0) const;
/** Returns the date of the last previous recurrence, before the specified date.
* @var afterDate the date before which to find the recurrence.
* @var last if non-null, *last is set to true if the previous recurrence is the
* last recurrence, else false.
* Reply = date of previous recurrence, or invalid date if none.
*/
QDate getPreviousDate(const QDate& afterDate, bool* last = 0) const;
/** Returns the date and time of the last previous recurrence, before the specified date/time.
* If a time later than 00:00:00 is specified and the recurrence has no time, 00:00:00 on
* the specified date is returned if that date recurs.
* @var afterDate the date/time before which to find the recurrence.
* @var last if non-null, *last is set to true if the previous recurrence is the
* last recurrence, else false.
* Reply = date/time of previous recurrence, or invalid date if none.
*/
QDateTime getPreviousDateTime(const QDateTime& afterDateTime, bool* last = 0) const;
/** Returns frequency of recurrence, in terms of the recurrence time period type. */
int frequency() const;
/** Returns the total number of recurrences, including the initial occurrence. */
int duration() const;
/** Sets the total number of times the event is to occur, including both the
* first and last. */
void setDuration(int duration);
/** Returns the number of recurrences up to and including the date specified. */
int durationTo(const QDate &) const;
/** Returns the number of recurrences up to and including the date/time specified. */
int durationTo(const QDateTime &) const;
/** Returns the date of the last recurrence.
* An invalid date is returned if the recurrence has no end.
* Note: for some recurrence types, endDate() can involve significant calculation.
*/
QDate endDate() const;
/** Returns the date and time of the last recurrence.
* An invalid date is returned if the recurrence has no end.
* Note: for some recurrence types, endDateTime() can involve significant calculation.
*/
QDateTime endDateTime() const;
/** Returns a string representing the recurrence end date in the format
according to the user's locale settings. */
QString endDateStr(bool shortfmt=true) const;
/** Sets an event to recur minutely.
* @var _rFreq the frequency to recur, e.g. 2 is every other minute
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
*/
void setMinutely(int _rFreq, int duration);
/** Sets an event to recur minutely.
* @var _rFreq the frequency to recur, e.g. 2 is every other minute
* @var endDateTime the ending date/time after which to stop recurring
*/
void setMinutely(int _rFreq, const QDateTime &endDateTime);
/** Sets an event to recur hourly.
* @var _rFreq the frequency to recur, e.g. 2 is every other hour
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
*/
void setHourly(int _rFreq, int duration);
/** Sets an event to recur hourly.
* @var _rFreq the frequency to recur, e.g. 2 is every other hour
* @var endDateTime the ending date/time after which to stop recurring
*/
void setHourly(int _rFreq, const QDateTime &endDateTime);
/** Sets an event to recur daily.
* @var _rFreq the frequency to recur, e.g. 2 is every other day
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
*/
void setDaily(int _rFreq, int duration);
/** Sets an event to recur daily.
* @var _rFreq the frequency to recur, e.g. 2 is every other day
* @var endDate the ending date after which to stop recurring
*/
void setDaily(int _rFreq, const QDate &endDate);
/** Sets an event to recur weekly.
* @var _rFreq the frequency to recur, e.g. every other week etc.
* @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday).
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
* @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday).
*/
void setWeekly(int _rFreq, const QBitArray &_rDays, int duration, int weekStart = 1);
/** Sets an event to recur weekly.
* @var _rFreq the frequency to recur, e.g. every other week etc.
* @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday).
* @var endDate the date on which to stop recurring.
* @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday).
*/
void setWeekly(int _rFreq, const QBitArray &_rDays, const QDate &endDate, int weekStart = 1);
/** Returns the first day of the week. Monday=1 .. Sunday=7. */
int weekStart() const { return rWeekStart; }
/** Returns week day mask (bit 0 = Monday). */
const QBitArray &days() const;
/** Sets an event to recur monthly.
* @var type rMonthlyPos or rMonthlyDay
* @var _rFreq the frequency to recur, e.g. 3 for every third month.
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
*/
void setMonthly(short type, int _rFreq, int duration);
/** same as above, but with ending date not number of recurrences */
void setMonthly(short type, int _rFreq, const QDate &endDate);
/** Adds a position to the recursMonthlyPos recurrence rule, if it is
* set.
* @var _rPos the position in the month for the recurrence, with valid
* values being 1-5 (5 weeks max in a month).
* @var _rDays the days for the position to recur on (bit 0 = Monday).
* Example: _rPos = 2, and bits 0 and 2 are set in _rDays:
* the rule is to repeat every 2nd Monday and Wednesday in the month.
*/
void addMonthlyPos(short _rPos, const QBitArray &_rDays);
/** Adds a position the the recursMonthlyDay list.
* @var _rDay the date in the month to recur.
*/
void addMonthlyDay(short _rDay);
/** Returns list of day positions in months. */
const QPtrList<rMonthPos> &monthPositions() const;
/** Returns list of day numbers of a month. */
const QPtrList<int> &monthDays() const;
/** Sets an event to recur yearly.
* @var type rYearlyMonth, rYearlyPos or rYearlyDay
* @var freq the frequency to recur, e.g. 3 for every third year.
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
*/
void setYearly(int type, int freq, int duration);
/** Sets an event to recur yearly ending at \a endDate. */
void setYearly(int type, int freq, const QDate &endDate);
/** Sets an event to recur yearly on specified dates.
* The dates must be specified by calling addYearlyNum().
* @var type the way recurrences of February 29th are to be handled in non-leap years.
* @var freq the frequency to recur, e.g. 3 for every third year.
* @var duration the number of times the event is to occur, or -1 to recur indefinitely.
*/
void setYearlyByDate(Feb29Type type, int freq, int duration);
/** Sets an event to recur yearly ending at \a endDate. */
void setYearlyByDate(Feb29Type type, int freq, const QDate &endDate);
/** Adds position of day or month in year.
* N.B. for recursYearlyPos, addYearlyMonthPos() must also be called
* to add positions within the month. */
void addYearlyNum(short _rNum);
/** Adds a position to the recursYearlyPos recurrence rule, if it is set.
* N.B. addYearlyNum() must also be called to add recurrence months.
* Parameters are the same as for addMonthlyPos().
*/
void addYearlyMonthPos(short _rPos, const QBitArray &_rDays);
/** Returns positions of days or months in year. */
const QPtrList<int> &yearNums() const;
/** Returns list of day positions in months, for a recursYearlyPos recurrence rule. */
const QPtrList<rMonthPos> &yearMonthPositions() const;
/** Returns how yearly recurrences of February 29th are handled. */
Feb29Type feb29YearlyType() const { return mFeb29YearlyType; }
/** Sets the default method for handling yearly recurrences of February 29th. */
static void setFeb29YearlyTypeDefault(Feb29Type t) { mFeb29YearlyDefaultType = t; }
/** Returns the default method for handling yearly recurrences of February 29th. */
static Feb29Type setFeb29YearlyTypeDefault() { return mFeb29YearlyDefaultType; }
-
+ void addYearlyMonth(short _rPos ); // added LR
/**
Debug output.
*/
void dump() const;
QString recurrenceText() const;
+ bool getYearlyMonthMonths(int day, QValueList<int>&,
+ QValueList<int> &leaplist) const;
protected:
enum PeriodFunc { END_DATE_AND_COUNT, COUNT_TO_DATE, NEXT_AFTER_DATE };
struct MonthlyData; friend struct MonthlyData;
struct YearlyMonthData; friend struct YearlyMonthData;
struct YearlyPosData; friend struct YearlyPosData;
struct YearlyDayData; friend struct YearlyDayData;
bool recursSecondly(const QDate &, int secondFreq) const;
bool recursMinutelyAt(const QDateTime &dt, int minuteFreq) const;
bool recursDaily(const QDate &) const;
bool recursWeekly(const QDate &) const;
bool recursMonthly(const QDate &) const;
bool recursYearlyByMonth(const QDate &) const;
bool recursYearlyByPos(const QDate &) const;
bool recursYearlyByDay(const QDate &) const;
QDate getNextDateNoTime(const QDate& preDate, bool* last) const;
QDate getPreviousDateNoTime(const QDate& afterDate, bool* last) const;
void addMonthlyPos_(short _rPos, const QBitArray &_rDays);
void setDailySub(short type, int freq, int duration);
void setYearly_(short type, Feb29Type, int freq, int duration);
int recurCalc(PeriodFunc, QDate &enddate) const;
int recurCalc(PeriodFunc, QDateTime &endtime) const;
int secondlyCalc(PeriodFunc, QDateTime& endtime, int freq) const;
int dailyCalc(PeriodFunc, QDate &enddate) const;
int weeklyCalc(PeriodFunc, QDate &enddate) const;
int weeklyCalcEndDate(QDate& enddate, int daysPerWeek) const;
int weeklyCalcToDate(const QDate& enddate, int daysPerWeek) const;
int weeklyCalcNextAfter(QDate& enddate, int daysPerWeek) const;
int monthlyCalc(PeriodFunc, QDate &enddate) const;
int monthlyCalcEndDate(QDate& enddate, MonthlyData&) const;
int monthlyCalcToDate(const QDate& enddate, MonthlyData&) const;
int monthlyCalcNextAfter(QDate& enddate, MonthlyData&) const;
int yearlyMonthCalc(PeriodFunc, QDate &enddate) const;
int yearlyMonthCalcEndDate(QDate& enddate, YearlyMonthData&) const;
int yearlyMonthCalcToDate(const QDate& enddate, YearlyMonthData&) const;
int yearlyMonthCalcNextAfter(QDate& enddate, YearlyMonthData&) const;
int yearlyPosCalc(PeriodFunc, QDate &enddate) const;
int yearlyPosCalcEndDate(QDate& enddate, YearlyPosData&) const;
int yearlyPosCalcToDate(const QDate& enddate, YearlyPosData&) const;
int yearlyPosCalcNextAfter(QDate& enddate, YearlyPosData&) const;
int yearlyDayCalc(PeriodFunc, QDate &enddate) const;
int yearlyDayCalcEndDate(QDate& enddate, YearlyDayData&) const;
int yearlyDayCalcToDate(const QDate& enddate, YearlyDayData&) const;
int yearlyDayCalcNextAfter(QDate& enddate, YearlyDayData&) const;
int countMonthlyPosDays() const;
void getMonthlyPosDays(QValueList<int>&, int daysInMonth,
int startDayOfWeek) const;
bool getMonthlyDayDays(QValueList<int>&, int daysInMonth) const;
- bool getYearlyMonthMonths(int day, QValueList<int>&,
- QValueList<int> &leaplist) const;
int getFirstDayInWeek(int startDay, bool useWeekStart = true) const;
int getLastDayInWeek(int endDay, bool useWeekStart = true) const;
QDate getFirstDateInMonth(const QDate& earliestDate) const;
QDate getLastDateInMonth(const QDate& latestDate) const;
QDate getFirstDateInYear(const QDate& earliestDate) const;
QDate getLastDateInYear(const QDate& latestDate) const;
private:
// Prohibit copying
Recurrence(const Recurrence&);
Recurrence &operator=(const Recurrence&);
short recurs; // should be one of the enums.
int rWeekStart; // day which starts the week, Monday=1 .. Sunday=7
QBitArray rDays; // array of days during week it recurs
QPtrList<rMonthPos> rMonthPositions; // list of positions during a month
// on which an event recurs
QPtrList<int> rMonthDays; // list of days during a month on
// which the event recurs
QPtrList<int> rYearNums; // either months/days to recur on for rYearly,
// sorted in numerical order
int rFreq; // frequency of period
// one of the following must be specified
int rDuration; // num times to recur (inc. first occurrence), -1 = infinite
QDateTime rEndDateTime; // date/time at which to end recurrence
QDateTime mRecurStart; // date/time of first recurrence
bool mFloats; // the recurrence has no time, just a date
bool mRecurReadOnly;
int mRecurExDatesCount; // number of recurrences (in addition to rDuration) which are excluded
Feb29Type mFeb29YearlyType; // how to handle yearly recurrences of February 29th
static Feb29Type mFeb29YearlyDefaultType; // default value for mFeb29YearlyType
// Backwards compatibility for KDE < 3.1.
int mCompatVersion; // calendar file version for backwards compatibility
short mCompatRecurs; // original 'recurs' in old calendar format, or rNone
int mCompatDuration; // original 'rDuration' in old calendar format, or 0
Incidence *mParent;
};
}
#endif