-rw-r--r-- | libkcal/icalformatimpl.cpp | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp index eae41aa..fe7413f 100644 --- a/libkcal/icalformatimpl.cpp +++ b/libkcal/icalformatimpl.cpp @@ -1,755 +1,755 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 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. */ #include <qdatetime.h> #include <qstring.h> #include <qptrlist.h> #include <qfile.h> #include <kdebug.h> #include <klocale.h> #include <kglobal.h> extern "C" { #include <ical.h> #include <icalss.h> #include <icalparser.h> #include <icalrestriction.h> } #include "calendar.h" #include "journal.h" #include "icalformat.h" #include "icalformatimpl.h" #include "compat.h" #define _ICAL_VERSION "2.0" using namespace KCal; const int gSecondsPerMinute = 60; const int gSecondsPerHour = gSecondsPerMinute * 60; const int gSecondsPerDay = gSecondsPerHour * 24; const int gSecondsPerWeek = gSecondsPerDay * 7; ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) : mParent( parent ), mCalendarVersion( 0 ) { mCompat = new Compat; } ICalFormatImpl::~ICalFormatImpl() { delete mCompat; } class ToStringVisitor : public Incidence::Visitor { public: ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {} bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; } bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; } bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; } icalcomponent *component() { return mComponent; } private: ICalFormatImpl *mImpl; icalcomponent *mComponent; }; icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence) { ToStringVisitor v( this ); incidence->accept(v); return v.component(); } icalcomponent *ICalFormatImpl::writeTodo(Todo *todo) { QString tmpStr; QStringList tmpStrList; icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT); writeIncidence(vtodo,todo); // due date if (todo->hasDueDate()) { icaltimetype due; if (todo->doesFloat()) { due = writeICalDate(todo->dtDue().date()); } else { due = writeICalDateTime(todo->dtDue()); } icalcomponent_add_property(vtodo,icalproperty_new_due(due)); } // start time if (todo->hasStartDate()) { icaltimetype start; if (todo->doesFloat()) { // kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl; start = writeICalDate(todo->dtStart().date()); } else { // kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl; start = writeICalDateTime(todo->dtStart()); } icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start)); } // completion date if (todo->isCompleted()) { if (!todo->hasCompletedDate()) { // If todo was created by KOrganizer <2.2 it has no correct completion // date. Set it to now. todo->setCompleted(QDateTime::currentDateTime()); } icaltimetype completed = writeICalDateTime(todo->completed()); icalcomponent_add_property(vtodo,icalproperty_new_completed(completed)); } icalcomponent_add_property(vtodo, icalproperty_new_percentcomplete(todo->percentComplete())); return vtodo; } icalcomponent *ICalFormatImpl::writeEvent(Event *event) { kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid() << ")" << endl; QString tmpStr; QStringList tmpStrList; icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT); writeIncidence(vevent,event); // start time icaltimetype start; if (event->doesFloat()) { // kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; start = writeICalDate(event->dtStart().date()); } else { // kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; start = writeICalDateTime(event->dtStart()); } icalcomponent_add_property(vevent,icalproperty_new_dtstart(start)); if (event->hasEndDate()) { // end time icaltimetype end; if (event->doesFloat()) { // kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl; // +1 day because end date is non-inclusive. end = writeICalDate( event->dtEnd().date().addDays( 1 ) ); } else { // kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl; end = writeICalDateTime(event->dtEnd()); } icalcomponent_add_property(vevent,icalproperty_new_dtend(end)); } // TODO: attachments, resources #if 0 // attachments tmpStrList = anEvent->attachments(); for ( QStringList::Iterator it = tmpStrList.begin(); it != tmpStrList.end(); ++it ) addPropValue(vevent, VCAttachProp, (*it).utf8()); // resources tmpStrList = anEvent->resources(); tmpStr = tmpStrList.join(";"); if (!tmpStr.isEmpty()) addPropValue(vevent, VCResourcesProp, tmpStr.utf8()); #endif // Transparency switch( event->transparency() ) { case Event::Transparent: icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT)); break; case Event::Opaque: icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_OPAQUE)); break; } return vevent; } icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy, Scheduler::Method method) { icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT); writeIncidenceBase(vfreebusy,freebusy); icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart( writeICalDateTime(freebusy->dtStart()))); icalcomponent_add_property(vfreebusy, icalproperty_new_dtend( writeICalDateTime(freebusy->dtEnd()))); if (method == Scheduler::Request) { icalcomponent_add_property(vfreebusy,icalproperty_new_uid( freebusy->uid().utf8())); } //Loops through all the periods in the freebusy object QValueList<Period> list = freebusy->busyPeriods(); QValueList<Period>::Iterator it; icalperiodtype period; for (it = list.begin(); it!= list.end(); ++it) { period.start = writeICalDateTime((*it).start()); period.end = writeICalDateTime((*it).end()); icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) ); } return vfreebusy; } icalcomponent *ICalFormatImpl::writeJournal(Journal *journal) { icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT); writeIncidence(vjournal,journal); // start time if (journal->dtStart().isValid()) { icaltimetype start; if (journal->doesFloat()) { // kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; start = writeICalDate(journal->dtStart().date()); } else { // kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; start = writeICalDateTime(journal->dtStart()); } icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start)); } return vjournal; } void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence) { // pilot sync stuff // TODO: move this application-specific code to kpilot if (incidence->pilotId()) { incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId())); incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus())); } if ( !incidence->IDStr().isEmpty()) { incidence->setNonKDECustomProperty("X-KOPIEXTID",incidence->IDStr() ); } writeIncidenceBase(parent,incidence); if (incidence->cancelled()) { icalcomponent_add_property(parent,icalproperty_new_status(ICAL_STATUS_CANCELLED)); } // creation date icalcomponent_add_property(parent,icalproperty_new_created( writeICalDateTime(incidence->created()))); // unique id icalcomponent_add_property(parent,icalproperty_new_uid( incidence->uid().utf8())); // revision icalcomponent_add_property(parent,icalproperty_new_sequence( incidence->revision())); // last modification date icalcomponent_add_property(parent,icalproperty_new_lastmodified( writeICalDateTime(incidence->lastModified()))); // description if (!incidence->description().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_description( incidence->description().utf8())); } // summary if (!incidence->summary().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_summary( incidence->summary().utf8())); } // location if (!incidence->location().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_location( incidence->location().utf8())); } // TODO: // status // addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8()); // secrecy enum icalproperty_class classInt; switch (incidence->secrecy()) { case Incidence::SecrecyPublic: classInt = ICAL_CLASS_PUBLIC; break; case Incidence::SecrecyConfidential: classInt = ICAL_CLASS_CONFIDENTIAL; break; case Incidence::SecrecyPrivate: classInt =ICAL_CLASS_PRIVATE ; default: classInt =ICAL_CLASS_PRIVATE ; break; } icalcomponent_add_property(parent,icalproperty_new_class(classInt)); // priority icalcomponent_add_property(parent,icalproperty_new_priority( incidence->priority())); // categories QStringList categories = incidence->categories(); QStringList::Iterator it; for(it = categories.begin(); it != categories.end(); ++it ) { icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8())); } // TODO: Ensure correct concatenation of categories properties. /* // categories tmpStrList = incidence->getCategories(); tmpStr = ""; QString catStr; for ( QStringList::Iterator it = tmpStrList.begin(); it != tmpStrList.end(); ++it ) { catStr = *it; if (catStr[0] == ' ') tmpStr += catStr.mid(1); else tmpStr += catStr; // this must be a ';' character as the vCalendar specification requires! // vcc.y has been hacked to translate the ';' to a ',' when the vcal is // read in. tmpStr += ";"; } if (!tmpStr.isEmpty()) { tmpStr.truncate(tmpStr.length()-1); icalcomponent_add_property(parent,icalproperty_new_categories( writeText(incidence->getCategories().join(";")))); } */ // related event - if (incidence->relatedTo()) { + if (!incidence->relatedToUid().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_relatedto( - incidence->relatedTo()->uid().utf8())); + incidence->relatedToUid().utf8())); } // recurrence rule stuff Recurrence *recur = incidence->recurrence(); if (recur->doesRecur()) { icalcomponent_add_property(parent,writeRecurrenceRule(recur)); } // recurrence excpetion dates DateList dateList = incidence->exDates(); DateList::ConstIterator exIt; for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) { icalcomponent_add_property(parent,icalproperty_new_exdate( writeICalDate(*exIt))); } // attachments QPtrList<Attachment> attachments = incidence->attachments(); for (Attachment *at = attachments.first(); at; at = attachments.next()) icalcomponent_add_property(parent,writeAttachment(at)); // alarms QPtrList<Alarm> alarms = incidence->alarms(); Alarm* alarm; for (alarm = alarms.first(); alarm; alarm = alarms.next()) { if (alarm->enabled()) { kdDebug(5800) << "Write alarm for " << incidence->summary() << endl; icalcomponent_add_component(parent,writeAlarm(alarm)); } } if( incidence->hasRecurrenceID() ) { icalcomponent_add_property(parent, icalproperty_new_recurrenceid( writeICalDateTime( incidence->recurrenceID()))); } // duration // turned off as it always is set to PTS0 (and must not occur together with DTEND if (incidence->hasDuration()) { icaldurationtype duration; duration = writeICalDuration(incidence->duration()); icalcomponent_add_property(parent,icalproperty_new_duration(duration)); } } void ICalFormatImpl::writeIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) { icalcomponent_add_property(parent,icalproperty_new_dtstamp( writeICalDateTime(QDateTime::currentDateTime()))); // organizer stuff icalcomponent_add_property(parent,icalproperty_new_organizer( ("MAILTO:" + incidenceBase->organizer()).utf8())); // attendees if (incidenceBase->attendeeCount() != 0) { QPtrList<Attendee> al = incidenceBase->attendees(); QPtrListIterator<Attendee> ai(al); for (; ai.current(); ++ai) { icalcomponent_add_property(parent,writeAttendee(ai.current())); } } // custom properties writeCustomProperties(parent, incidenceBase); } void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties) { QMap<QCString, QString> custom = properties->customProperties(); for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { icalproperty *p = icalproperty_new_x(c.data().utf8()); icalproperty_set_x_name(p,c.key()); icalcomponent_add_property(parent,p); } } icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee) { icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8()); if (!attendee->name().isEmpty()) { icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8())); } icalproperty_add_parameter(p,icalparameter_new_rsvp( attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE )); icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION; switch (attendee->status()) { default: case Attendee::NeedsAction: status = ICAL_PARTSTAT_NEEDSACTION; break; case Attendee::Accepted: status = ICAL_PARTSTAT_ACCEPTED; break; case Attendee::Declined: status = ICAL_PARTSTAT_DECLINED; break; case Attendee::Tentative: status = ICAL_PARTSTAT_TENTATIVE; break; case Attendee::Delegated: status = ICAL_PARTSTAT_DELEGATED; break; case Attendee::Completed: status = ICAL_PARTSTAT_COMPLETED; break; case Attendee::InProcess: status = ICAL_PARTSTAT_INPROCESS; break; } icalproperty_add_parameter(p,icalparameter_new_partstat(status)); icalparameter_role role = ICAL_ROLE_REQPARTICIPANT; switch (attendee->role()) { case Attendee::Chair: role = ICAL_ROLE_CHAIR; break; default: case Attendee::ReqParticipant: role = ICAL_ROLE_REQPARTICIPANT; break; case Attendee::OptParticipant: role = ICAL_ROLE_OPTPARTICIPANT; break; case Attendee::NonParticipant: role = ICAL_ROLE_NONPARTICIPANT; break; } icalproperty_add_parameter(p,icalparameter_new_role(role)); if (!attendee->uid().isEmpty()) { icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8()); icalparameter_set_xname(icalparameter_uid,"X-UID"); icalproperty_add_parameter(p,icalparameter_uid); } return p; } icalproperty *ICalFormatImpl::writeAttachment(Attachment *att) { #if 0 icalattachtype* attach = icalattachtype_new(); if (att->isURI()) icalattachtype_set_url(attach, att->uri().utf8().data()); else icalattachtype_set_base64(attach, att->data(), 0); #endif icalattach *attach; if (att->isURI()) attach = icalattach_new_from_url( att->uri().utf8().data()); else attach = icalattach_new_from_data ( (unsigned char *)att->data(), 0, 0); icalproperty *p = icalproperty_new_attach(attach); if (!att->mimeType().isEmpty()) icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data())); if (att->isBinary()) { icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY)); icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64)); } return p; } icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur) { // kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl; icalrecurrencetype r; icalrecurrencetype_clear(&r); int index = 0; int index2 = 0; QPtrList<Recurrence::rMonthPos> tmpPositions; QPtrList<int> tmpDays; int *tmpDay; Recurrence::rMonthPos *tmpPos; bool datetime = false; int day; int i; switch(recur->doesRecur()) { case Recurrence::rMinutely: r.freq = ICAL_MINUTELY_RECURRENCE; datetime = true; break; case Recurrence::rHourly: r.freq = ICAL_HOURLY_RECURRENCE; datetime = true; break; case Recurrence::rDaily: r.freq = ICAL_DAILY_RECURRENCE; break; case Recurrence::rWeekly: r.freq = ICAL_WEEKLY_RECURRENCE; r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1); for (i = 0; i < 7; i++) { if (recur->days().testBit(i)) { day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 r.by_day[index++] = icalrecurrencetype_day_day_of_week(day); } } // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; case Recurrence::rMonthlyPos: r.freq = ICAL_MONTHLY_RECURRENCE; tmpPositions = recur->monthPositions(); for (tmpPos = tmpPositions.first(); tmpPos; tmpPos = tmpPositions.next()) { for (i = 0; i < 7; i++) { if (tmpPos->rDays.testBit(i)) { day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 day += tmpPos->rPos*8; if (tmpPos->negative) day = -day; r.by_day[index++] = day; } } } // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; case Recurrence::rMonthlyDay: r.freq = ICAL_MONTHLY_RECURRENCE; tmpDays = recur->monthDays(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8);//*tmpDay); } // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; case Recurrence::rYearlyMonth: case Recurrence::rYearlyPos: r.freq = ICAL_YEARLY_RECURRENCE; tmpDays = recur->yearNums(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_month[index++] = *tmpDay; } // r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX; if (recur->doesRecur() == Recurrence::rYearlyPos) { tmpPositions = recur->monthPositions(); for (tmpPos = tmpPositions.first(); tmpPos; tmpPos = tmpPositions.next()) { for (i = 0; i < 7; i++) { if (tmpPos->rDays.testBit(i)) { day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 day += tmpPos->rPos*8; if (tmpPos->negative) day = -day; r.by_day[index2++] = day; } } } // r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX; } break; case Recurrence::rYearlyDay: r.freq = ICAL_YEARLY_RECURRENCE; tmpDays = recur->yearNums(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_year_day[index++] = *tmpDay; } // r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; default: r.freq = ICAL_NO_RECURRENCE; kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl; break; } r.interval = recur->frequency(); if (recur->duration() > 0) { r.count = recur->duration(); } else if (recur->duration() == -1) { r.count = 0; } else { if (datetime) r.until = writeICalDateTime(recur->endDateTime()); else r.until = writeICalDate(recur->endDate()); } // Debug output #if 0 const char *str = icalrecurrencetype_as_string(&r); if (str) { kdDebug(5800) << " String: " << str << endl; } else { kdDebug(5800) << " No String" << endl; } #endif return icalproperty_new_rrule(r); } icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm) { icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT); icalproperty_action action; icalattach *attach = 0; switch (alarm->type()) { case Alarm::Procedure: action = ICAL_ACTION_PROCEDURE; attach = icalattach_new_from_url( QFile::encodeName(alarm->programFile()).data() ); icalcomponent_add_property(a,icalproperty_new_attach(attach)); if (!alarm->programArguments().isEmpty()) { icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8())); } break; case Alarm::Audio: action = ICAL_ACTION_AUDIO; if (!alarm->audioFile().isEmpty()) { attach = icalattach_new_from_url(QFile::encodeName( alarm->audioFile() ).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); } break; case Alarm::Email: { action = ICAL_ACTION_EMAIL; QValueList<Person> addresses = alarm->mailAddresses(); for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) { icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8()); if (!(*ad).name().isEmpty()) { icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8())); } icalcomponent_add_property(a,p); } icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8())); icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); QStringList attachments = alarm->mailAttachments(); if (attachments.count() > 0) { for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) { attach = icalattach_new_from_url(QFile::encodeName( *at ).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); } } break; } case Alarm::Display: action = ICAL_ACTION_DISPLAY; icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); break; case Alarm::Invalid: default: kdDebug(5800) << "Unknown type of alarm" << endl; action = ICAL_ACTION_NONE; break; } icalcomponent_add_property(a,icalproperty_new_action(action)); // Trigger time icaltriggertype trigger; if ( alarm->hasTime() ) { trigger.time = writeICalDateTime(alarm->time()); trigger.duration = icaldurationtype_null_duration(); } else { trigger.time = icaltime_null_time(); Duration offset; if ( alarm->hasStartOffset() ) offset = alarm->startOffset(); else offset = alarm->endOffset(); trigger.duration = icaldurationtype_from_int( offset.asSeconds() ); } icalproperty *p = icalproperty_new_trigger(trigger); if ( alarm->hasEndOffset() ) icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END)); @@ -1655,511 +1655,515 @@ void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence) } 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.is_neg = (seconds<0)?1:0; if (seconds<0) seconds = -seconds; d.weeks = seconds / gSecondsPerWeek; seconds %= gSecondsPerWeek; d.days = seconds / gSecondsPerDay; seconds %= gSecondsPerDay; d.hours = seconds / gSecondsPerHour; seconds %= gSecondsPerHour; d.minutes = seconds / gSecondsPerMinute; seconds %= gSecondsPerMinute; d.seconds = seconds; 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); if (!cal->todo(todo->uid())) cal->addTodo(todo); c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT); } // Iterate through all events c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT); while (c) { // kdDebug(5800) << "----Event found" << endl; Event *event = readEvent(c); if (!cal->event(event->uid())) cal->addEvent(event); c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT); } // Iterate through all journals c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT); while (c) { // kdDebug(5800) << "----Journal found" << endl; Journal *journal = readJournal(c); if (!cal->journal(journal->uid())) cal->addJournal(journal); c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT); } #if 0 initPropIterator(&i, vcal); // go through all the vobjects in the vcal while (moreIteration(&i)) { curVO = nextVObject(&i); /************************************************************************/ // now, check to see that the object is an event or todo. if (strcmp(vObjectName(curVO), VCEventProp) == 0) { if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) { char *s; s = fakeCString(vObjectUStringZValue(curVOProp)); // check to see if event was deleted by the kpilot conduit if (atoi(s) == Event::SYNCDEL) { deleteStr(s); goto SKIP; } deleteStr(s); } // this code checks to see if we are trying to read in an event // that we already find to be in the calendar. If we find this // to be the case, we skip the event. if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) { char *s = fakeCString(vObjectUStringZValue(curVOProp)); QString tmpStr(s); deleteStr(s); if (cal->event(tmpStr)) { goto SKIP; } if (cal->todo(tmpStr)) { goto SKIP; } } if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) && (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) { kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl; goto SKIP; } anEvent = VEventToEvent(curVO); // we now use addEvent instead of insertEvent so that the // signal/slot get connected. if (anEvent) cal->addEvent(anEvent); else { // some sort of error must have occurred while in translation. goto SKIP; } } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) { anEvent = VTodoToEvent(curVO); cal->addTodo(anEvent); } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) || (strcmp(vObjectName(curVO), VCProdIdProp) == 0) || (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) { // do nothing, we know these properties and we want to skip them. // we have either already processed them or are ignoring them. ; } else { ; } SKIP: ; } // while #endif // Post-Process list of events with relations, put Event objects in relation Event *ev; for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) { - ev->setRelatedTo(cal->event(ev->relatedToUid())); + Incidence * inc = cal->event(ev->relatedToUid()); + if ( inc ) + ev->setRelatedTo( inc ); } Todo *todo; for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) { - todo->setRelatedTo(cal->todo(todo->relatedToUid())); + Incidence * inc = cal->todo(todo->relatedToUid()); + if ( inc ) + todo->setRelatedTo( inc ); } return true; } QString ICalFormatImpl::extractErrorProperty(icalcomponent *c) { // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " // << icalcomponent_as_ical_string(c) << endl; QString errorMessage; icalproperty *error; error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY); while(error) { errorMessage += icalproperty_get_xlicerror(error); errorMessage += "\n"; error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY); } // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl; return errorMessage; } void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r) { int i; if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Day: "; while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Month Day: "; while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Year Day: "; while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Month: "; while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Set Pos: "; while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } } icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence, Scheduler::Method method) { icalcomponent *message = createCalendarComponent(); icalproperty_method icalmethod = ICAL_METHOD_NONE; switch (method) { case Scheduler::Publish: icalmethod = ICAL_METHOD_PUBLISH; break; case Scheduler::Request: icalmethod = ICAL_METHOD_REQUEST; break; case Scheduler::Refresh: icalmethod = ICAL_METHOD_REFRESH; break; case Scheduler::Cancel: icalmethod = ICAL_METHOD_CANCEL; break; case Scheduler::Add: icalmethod = ICAL_METHOD_ADD; break; case Scheduler::Reply: icalmethod = ICAL_METHOD_REPLY; break; case Scheduler::Counter: icalmethod = ICAL_METHOD_COUNTER; break; case Scheduler::Declinecounter: icalmethod = ICAL_METHOD_DECLINECOUNTER; break; default: return message; } icalcomponent_add_property(message,icalproperty_new_method(icalmethod)); // TODO: check, if dynamic cast is required if(incidence->type() == "Todo") { Todo *todo = static_cast<Todo *>(incidence); icalcomponent_add_component(message,writeTodo(todo)); } if(incidence->type() == "Event") { Event *event = static_cast<Event *>(incidence); icalcomponent_add_component(message,writeEvent(event)); } if(incidence->type() == "FreeBusy") { FreeBusy *freebusy = static_cast<FreeBusy *>(incidence); icalcomponent_add_component(message,writeFreeBusy(freebusy, method)); } return message; } |