libkcal

icalformatimpl.cpp

00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00005     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to
00019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020     Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include <tqdatetime.h>
00024 #include <tqstring.h>
00025 #include <tqptrlist.h>
00026 #include <tqfile.h>
00027 #include <cstdlib>
00028 
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 #include <kmdcodec.h>
00032 
00033 extern "C" {
00034   #include <libical/ical.h>
00035   #include <libical/icalparser.h>
00036   #include <libical/icalrestriction.h>
00037 }
00038 
00039 #include "calendar.h"
00040 #include "journal.h"
00041 #include "icalformat.h"
00042 #include "icalformatimpl.h"
00043 #include "compat.h"
00044 
00045 #include "config.h"
00046 
00047 #define _ICAL_VERSION "2.0"
00048 
00049 using namespace KCal;
00050 
00051 /* Static helpers */
00052 static TQDateTime ICalDate2TQDate(const icaltimetype& t)
00053 {
00054   // Outlook sends dates starting from 1601-01-01, but TQDate()
00055   // can only handle dates starting 1752-09-14.
00056   const int year = (t.year>=1754) ? t.year : 1754;
00057   return TQDateTime(TQDate(year,t.month,t.day), TQTime(t.hour,t.minute,t.second));
00058 }
00059 
00060 /*
00061 static void _dumpIcaltime( const icaltimetype& t)
00062 {
00063   kdDebug(5800) << "--- Y: " << t.year << " M: " << t.month << " D: " << t.day
00064       << endl;
00065   kdDebug(5800) << "--- H: " << t.hour << " M: " << t.minute << " S: " << t.second
00066       << endl;
00067   kdDebug(5800) << "--- isUtc: " << icaltime_is_utc( t )<< endl;
00068   kdDebug(5800) << "--- zoneId: " << icaltimezone_get_tzid( const_cast<icaltimezone*>( t.zone ) )<< endl;
00069 }
00070 */
00071 
00072 static TQString quoteForParam( const TQString &text )
00073 {
00074   TQString tmp = text;
00075   tmp.remove( '"' );
00076   if ( tmp.contains( ';' ) || tmp.contains( ':' ) || tmp.contains( ',' ) )
00077     return tmp; // libical quotes in this case already, see icalparameter_as_ical_string()
00078   return TQString::fromLatin1( "\"" ) + tmp + TQString::fromLatin1( "\"" );
00079 }
00080 
00081 const int gSecondsPerMinute = 60;
00082 const int gSecondsPerHour   = gSecondsPerMinute * 60;
00083 const int gSecondsPerDay    = gSecondsPerHour   * 24;
00084 const int gSecondsPerWeek   = gSecondsPerDay    * 7;
00085 
00086 ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) :
00087   mParent( parent ), mCompat( new Compat )
00088 {
00089 }
00090 
00091 ICalFormatImpl::~ICalFormatImpl()
00092 {
00093   delete mCompat;
00094 }
00095 
00096 class ICalFormatImpl::ToComponentVisitor : public IncidenceBase::Visitor
00097 {
00098   public:
00099     ToComponentVisitor( ICalFormatImpl *impl, Scheduler::Method m ) : mImpl( impl ), mComponent( 0 ), mMethod( m ) {}
00100 
00101     bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; }
00102     bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; }
00103     bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; }
00104     bool visit( FreeBusy *fb ) { mComponent = mImpl->writeFreeBusy( fb, mMethod ); return true; }
00105 
00106     icalcomponent *component() { return mComponent; }
00107 
00108   private:
00109     ICalFormatImpl *mImpl;
00110     icalcomponent *mComponent;
00111     Scheduler::Method mMethod;
00112 };
00113 
00114 icalcomponent *ICalFormatImpl::writeIncidence( IncidenceBase *incidence, Scheduler::Method method )
00115 {
00116   ToComponentVisitor v( this, method );
00117   if ( incidence->accept(v) )
00118     return v.component();
00119   else return 0;
00120 }
00121 
00122 icalcomponent *ICalFormatImpl::writeTodo(Todo *todo)
00123 {
00124   TQString tmpStr;
00125   TQStringList tmpStrList;
00126 
00127   icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
00128 
00129   writeIncidence(vtodo,todo);
00130 
00131   // due date
00132   if (todo->hasDueDate()) {
00133     icaltimetype due;
00134     if (todo->doesFloat()) {
00135       due = writeICalDate(todo->dtDue(true).date());
00136     } else {
00137       due = writeICalDateTime(todo->dtDue(true));
00138     }
00139     icalcomponent_add_property(vtodo,icalproperty_new_due(due));
00140   }
00141 
00142   // start time
00143   if ( todo->hasStartDate() || todo->doesRecur() ) {
00144     icaltimetype start;
00145     if (todo->doesFloat()) {
00146 //      kdDebug(5800) << " Incidence " << todo->summary() << " floats." << endl;
00147       start = writeICalDate(todo->dtStart(true).date());
00148     } else {
00149 //      kdDebug(5800) << " incidence " << todo->summary() << " has time." << endl;
00150       start = writeICalDateTime(todo->dtStart(true));
00151     }
00152     icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start));
00153   }
00154 
00155   // completion date
00156   if (todo->isCompleted()) {
00157     if (!todo->hasCompletedDate()) {
00158       // If todo was created by KOrganizer <2.2 it has no correct completion
00159       // date. Set it to now.
00160       todo->setCompleted(TQDateTime::currentDateTime());
00161     }
00162     icaltimetype completed = writeICalDateTime(todo->completed());
00163     icalcomponent_add_property(vtodo,icalproperty_new_completed(completed));
00164   }
00165 
00166   icalcomponent_add_property(vtodo,
00167       icalproperty_new_percentcomplete(todo->percentComplete()));
00168 
00169   if( todo->doesRecur() ) {
00170     icalcomponent_add_property(vtodo,
00171         icalproperty_new_recurrenceid( writeICalDateTime( todo->dtDue())));
00172   }
00173 
00174   return vtodo;
00175 }
00176 
00177 icalcomponent *ICalFormatImpl::writeEvent(Event *event)
00178 {
00179 #if 0
00180   kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid()
00181                 << ")" << endl;
00182 #endif
00183 
00184   TQString tmpStr;
00185   TQStringList tmpStrList;
00186 
00187   icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
00188 
00189   writeIncidence(vevent,event);
00190 
00191   // start time
00192   icaltimetype start;
00193   if (event->doesFloat()) {
00194 //    kdDebug(5800) << " Incidence " << event->summary() << " floats." << endl;
00195     start = writeICalDate(event->dtStart().date());
00196   } else {
00197 //    kdDebug(5800) << " incidence " << event->summary() << " has time." << endl;
00198     start = writeICalDateTime(event->dtStart());
00199   }
00200   icalcomponent_add_property(vevent,icalproperty_new_dtstart(start));
00201 
00202   if (event->hasEndDate()) {
00203     // End time.
00204     // RFC2445 says that if DTEND is present, it has to be greater than DTSTART.
00205     icaltimetype end;
00206     if (event->doesFloat()) {
00207 //      kdDebug(5800) << " Event " << event->summary() << " floats." << endl;
00208       // +1 day because end date is non-inclusive.
00209       end = writeICalDate( event->dtEnd().date().addDays( 1 ) );
00210       icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
00211     } else {
00212 //      kdDebug(5800) << " Event " << event->summary() << " has time." << endl;
00213       if (event->dtEnd() != event->dtStart()) {
00214         end = writeICalDateTime(event->dtEnd());
00215         icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
00216       }
00217     }
00218   }
00219 
00220 // TODO: resources
00221 #if 0
00222   // resources
00223   tmpStrList = anEvent->resources();
00224   tmpStr = tmpStrList.join(";");
00225   if (!tmpStr.isEmpty())
00226     addPropValue(vevent, VCResourcesProp, tmpStr.utf8());
00227 
00228 #endif
00229 
00230   // Transparency
00231   switch( event->transparency() ) {
00232   case Event::Transparent:
00233     icalcomponent_add_property(
00234       vevent,
00235       icalproperty_new_transp( ICAL_TRANSP_TRANSPARENT ) );
00236     break;
00237   case Event::Opaque:
00238     icalcomponent_add_property(
00239       vevent,
00240       icalproperty_new_transp( ICAL_TRANSP_OPAQUE ) );
00241     break;
00242   }
00243 
00244   return vevent;
00245 }
00246 
00247 icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy,
00248                                              Scheduler::Method method)
00249 {
00250   kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: "
00251     << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: "
00252     << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl;
00253 
00254   icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
00255 
00256   writeIncidenceBase(vfreebusy,freebusy);
00257 
00258   icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart(
00259       writeICalDateTime(freebusy->dtStart())));
00260 
00261   icalcomponent_add_property(vfreebusy, icalproperty_new_dtend(
00262       writeICalDateTime(freebusy->dtEnd())));
00263 
00264   if (method == Scheduler::Request) {
00265     icalcomponent_add_property(vfreebusy,icalproperty_new_uid(
00266        freebusy->uid().utf8()));
00267   }
00268 
00269   //Loops through all the periods in the freebusy object
00270   TQValueList<Period> list = freebusy->busyPeriods();
00271   TQValueList<Period>::Iterator it;
00272   icalperiodtype period = icalperiodtype_null_period();
00273   for (it = list.begin(); it!= list.end(); ++it) {
00274     period.start = writeICalDateTime((*it).start());
00275     if ( (*it).hasDuration() ) {
00276       period.duration = writeICalDuration( (*it).duration().asSeconds() );
00277     } else {
00278       period.end = writeICalDateTime((*it).end());
00279     }
00280     icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) );
00281   }
00282 
00283   return vfreebusy;
00284 }
00285 
00286 icalcomponent *ICalFormatImpl::writeJournal(Journal *journal)
00287 {
00288   icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
00289 
00290   writeIncidence(vjournal,journal);
00291 
00292   // start time
00293   if (journal->dtStart().isValid()) {
00294     icaltimetype start;
00295     if (journal->doesFloat()) {
00296 //      kdDebug(5800) << " Incidence " << event->summary() << " floats." << endl;
00297       start = writeICalDate(journal->dtStart().date());
00298     } else {
00299 //      kdDebug(5800) << " incidence " << event->summary() << " has time." << endl;
00300       start = writeICalDateTime(journal->dtStart());
00301     }
00302     icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start));
00303   }
00304 
00305   return vjournal;
00306 }
00307 
00308 void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence)
00309 {
00310   // pilot sync stuff
00311 // TODO: move this application-specific code to kpilot
00312   if (incidence->pilotId()) {
00313     // NOTE: we can't do setNonKDECustomProperty here because this changes
00314     // data and triggers an updated() event...
00315     // incidence->setNonKDECustomProperty("X-PILOTSTAT", TQString::number(incidence->syncStatus()));
00316     // incidence->setNonKDECustomProperty("X-PILOTID", TQString::number(incidence->pilotId()));
00317 
00318     icalproperty *p = 0;
00319     p = icalproperty_new_x(TQString::number(incidence->syncStatus()).utf8());
00320     icalproperty_set_x_name(p,"X-PILOTSTAT");
00321     icalcomponent_add_property(parent,p);
00322 
00323     p = icalproperty_new_x(TQString::number(incidence->pilotId()).utf8());
00324     icalproperty_set_x_name(p,"X-PILOTID");
00325     icalcomponent_add_property(parent,p);
00326   }
00327 
00328   TQString modifiedUid;
00329   if ( incidence->hasRecurrenceID() ) {
00330     // Recurring incidences are special; they must match their parent's UID
00331     // Each child has the parent set as the first item in the list
00332     // So, get and set the UID...
00333     IncidenceList il = incidence->childIncidences();
00334     IncidenceListIterator it;
00335     it = il.begin();
00336     modifiedUid = (*it);
00337   }
00338   else {
00339     modifiedUid = incidence->uid();
00340   }
00341 
00342   if ( incidence->schedulingID() != modifiedUid )
00343     // We need to store the UID in here. The rawSchedulingID will
00344     // go into the iCal UID component
00345     incidence->setCustomProperty( "LIBKCAL", "ID", modifiedUid );
00346   else
00347     incidence->removeCustomProperty( "LIBKCAL", "ID" );
00348 
00349   writeIncidenceBase(parent,incidence);
00350 
00351   // creation date
00352   icalcomponent_add_property(parent,icalproperty_new_created(
00353       writeICalDateTime(incidence->created())));
00354 
00355   // unique id
00356   // If the scheduling ID is different from the real UID, the real
00357   // one is stored on X-REALID above
00358   if ( incidence->hasRecurrenceID() ) {
00359     // Recurring incidences are special; they must match their parent's UID
00360     icalcomponent_add_property(parent,icalproperty_new_uid(modifiedUid.utf8()));
00361   }
00362   else {
00363     if ( !incidence->schedulingID().isEmpty() ) {
00364       icalcomponent_add_property(parent,icalproperty_new_uid(
00365           incidence->schedulingID().utf8()));
00366     }
00367   }
00368 
00369   // revision
00370   if ( incidence->revision() > 0 ) { // 0 is default, so don't write that out
00371     icalcomponent_add_property(parent,icalproperty_new_sequence(
00372         incidence->revision()));
00373   }
00374 
00375   // last modification date
00376   if ( incidence->lastModified().isValid() ) {
00377    icalcomponent_add_property(parent,icalproperty_new_lastmodified(
00378        writeICalDateTime(incidence->lastModified())));
00379   }
00380 
00381   // description
00382   if (!incidence->description().isEmpty()) {
00383     icalcomponent_add_property(parent,icalproperty_new_description(
00384         incidence->description().utf8()));
00385   }
00386 
00387   // summary
00388   if (!incidence->summary().isEmpty()) {
00389     icalcomponent_add_property(parent,icalproperty_new_summary(
00390         incidence->summary().utf8()));
00391   }
00392 
00393   // location
00394   if (!incidence->location().isEmpty()) {
00395     icalcomponent_add_property(parent,icalproperty_new_location(
00396         incidence->location().utf8()));
00397   }
00398 
00399   // status
00400   icalproperty_status status = ICAL_STATUS_NONE;
00401   switch (incidence->status()) {
00402     case Incidence::StatusTentative:    status = ICAL_STATUS_TENTATIVE;  break;
00403     case Incidence::StatusConfirmed:    status = ICAL_STATUS_CONFIRMED;  break;
00404     case Incidence::StatusCompleted:    status = ICAL_STATUS_COMPLETED;  break;
00405     case Incidence::StatusNeedsAction:  status = ICAL_STATUS_NEEDSACTION;  break;
00406     case Incidence::StatusCanceled:     status = ICAL_STATUS_CANCELLED;  break;
00407     case Incidence::StatusInProcess:    status = ICAL_STATUS_INPROCESS;  break;
00408     case Incidence::StatusDraft:        status = ICAL_STATUS_DRAFT;  break;
00409     case Incidence::StatusFinal:        status = ICAL_STATUS_FINAL;  break;
00410     case Incidence::StatusX: {
00411       icalproperty* p = icalproperty_new_status(ICAL_STATUS_X);
00412       icalvalue_set_x(icalproperty_get_value(p), incidence->statusStr().utf8());
00413       icalcomponent_add_property(parent, p);
00414       break;
00415     }
00416     case Incidence::StatusNone:
00417     default:
00418       break;
00419   }
00420   if (status != ICAL_STATUS_NONE)
00421     icalcomponent_add_property(parent, icalproperty_new_status(status));
00422 
00423   // secrecy
00424   icalproperty_class secClass;
00425   switch (incidence->secrecy()) {
00426     case Incidence::SecrecyPublic:
00427       secClass = ICAL_CLASS_PUBLIC;
00428       break;
00429     case Incidence::SecrecyConfidential:
00430       secClass = ICAL_CLASS_CONFIDENTIAL;
00431       break;
00432     case Incidence::SecrecyPrivate:
00433     default:
00434       secClass = ICAL_CLASS_PRIVATE;
00435       break;
00436   }
00437   if ( secClass != ICAL_CLASS_PUBLIC ) {
00438     icalcomponent_add_property(parent,icalproperty_new_class(secClass));
00439   }
00440 
00441   // priority
00442   if ( incidence->priority() > 0 ) { // 0 is undefined priority
00443     icalcomponent_add_property(parent,icalproperty_new_priority(
00444         incidence->priority()));
00445   }
00446 
00447   // categories
00448   TQStringList categories = incidence->categories();
00449   TQStringList::Iterator it;
00450   for(it = categories.begin(); it != categories.end(); ++it ) {
00451     icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8()));
00452   }
00453 
00454   // related event
00455   if ( !incidence->relatedToUid().isEmpty() ) {
00456     icalcomponent_add_property(parent,icalproperty_new_relatedto(
00457         incidence->relatedToUid().utf8()));
00458   }
00459 
00460   // recurrenceid
00461   if ( incidence->hasRecurrenceID() ) {
00462     icalcomponent_add_property(parent, icalproperty_new_recurrenceid( writeICalDateTime( incidence->recurrenceID() ) ));
00463   }
00464 
00465 //   kdDebug(5800) << "Write recurrence for '" << incidence->summary() << "' (" << incidence->uid()
00466 //             << ")" << endl;
00467 
00468   RecurrenceRule::List rrules( incidence->recurrence()->rRules() );
00469   RecurrenceRule::List::ConstIterator rit;
00470   for ( rit = rrules.begin(); rit != rrules.end(); ++rit ) {
00471     icalcomponent_add_property( parent, icalproperty_new_rrule(
00472                                 writeRecurrenceRule( (*rit) ) ) );
00473   }
00474 
00475   RecurrenceRule::List exrules( incidence->recurrence()->exRules() );
00476   RecurrenceRule::List::ConstIterator exit;
00477   for ( exit = exrules.begin(); exit != exrules.end(); ++exit ) {
00478     icalcomponent_add_property( parent, icalproperty_new_rrule(
00479                                 writeRecurrenceRule( (*exit) ) ) );
00480   }
00481 
00482   DateList dateList = incidence->recurrence()->exDates();
00483   DateList::ConstIterator exIt;
00484   for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) {
00485     icalcomponent_add_property(parent,icalproperty_new_exdate(
00486         writeICalDate(*exIt)));
00487   }
00488   DateTimeList dateTimeList = incidence->recurrence()->exDateTimes();
00489   DateTimeList::ConstIterator extIt;
00490   for(extIt = dateTimeList.begin(); extIt != dateTimeList.end(); ++extIt) {
00491     icalcomponent_add_property(parent,icalproperty_new_exdate(
00492         writeICalDateTime(*extIt)));
00493   }
00494 
00495 
00496   dateList = incidence->recurrence()->rDates();
00497   DateList::ConstIterator rdIt;
00498   for( rdIt = dateList.begin(); rdIt != dateList.end(); ++rdIt) {
00499      icalcomponent_add_property( parent, icalproperty_new_rdate(
00500          writeICalDatePeriod(*rdIt) ) );
00501   }
00502   dateTimeList = incidence->recurrence()->rDateTimes();
00503   DateTimeList::ConstIterator rdtIt;
00504   for( rdtIt = dateTimeList.begin(); rdtIt != dateTimeList.end(); ++rdtIt) {
00505      icalcomponent_add_property( parent, icalproperty_new_rdate(
00506          writeICalDateTimePeriod(*rdtIt) ) );
00507   }
00508 
00509   // attachments
00510   Attachment::List attachments = incidence->attachments();
00511   Attachment::List::ConstIterator atIt;
00512   for ( atIt = attachments.begin(); atIt != attachments.end(); ++atIt ) {
00513     icalcomponent_add_property( parent, writeAttachment( *atIt ) );
00514   }
00515 
00516   // alarms
00517   Alarm::List::ConstIterator alarmIt;
00518   for ( alarmIt = incidence->alarms().begin();
00519         alarmIt != incidence->alarms().end(); ++alarmIt ) {
00520     if ( (*alarmIt)->enabled() ) {
00521 //      kdDebug(5800) << "Write alarm for " << incidence->summary() << endl;
00522       icalcomponent_add_component( parent, writeAlarm( *alarmIt ) );
00523     }
00524   }
00525 
00526   // duration
00527   if (incidence->hasDuration()) {
00528     icaldurationtype duration;
00529     duration = writeICalDuration( incidence->duration() );
00530     icalcomponent_add_property(parent,icalproperty_new_duration(duration));
00531   }
00532 }
00533 
00534 void ICalFormatImpl::writeIncidenceBase( icalcomponent *parent,
00535                                          IncidenceBase * incidenceBase )
00536 {
00537   icalcomponent_add_property( parent, icalproperty_new_dtstamp(
00538       writeICalDateTime( TQDateTime::currentDateTime() ) ) );
00539 
00540   // organizer stuff
00541   if ( !incidenceBase->organizer().isEmpty() ) {
00542     icalcomponent_add_property( parent, writeOrganizer( incidenceBase->organizer() ) );
00543   }
00544 
00545   // attendees
00546   if ( incidenceBase->attendeeCount() > 0 ) {
00547     Attendee::List::ConstIterator it;
00548     for( it = incidenceBase->attendees().begin();
00549          it != incidenceBase->attendees().end(); ++it ) {
00550       icalcomponent_add_property( parent, writeAttendee( *it ) );
00551     }
00552   }
00553 
00554   // comments
00555   TQStringList comments = incidenceBase->comments();
00556   for (TQStringList::Iterator it=comments.begin(); it!=comments.end(); ++it) {
00557     icalcomponent_add_property(parent, icalproperty_new_comment((*it).utf8()));
00558   }
00559 
00560   // custom properties
00561   writeCustomProperties( parent, incidenceBase );
00562 }
00563 
00564 void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties)
00565 {
00566   TQMap<TQCString, TQString> custom = properties->customProperties();
00567   for (TQMap<TQCString, TQString>::Iterator c = custom.begin();  c != custom.end();  ++c) {
00568     icalproperty *p = icalproperty_new_x(c.data().utf8());
00569     icalproperty_set_x_name(p,c.key());
00570     icalcomponent_add_property(parent,p);
00571   }
00572 }
00573 
00574 icalproperty *ICalFormatImpl::writeOrganizer( const Person &organizer )
00575 {
00576   icalproperty *p = icalproperty_new_organizer("MAILTO:" + organizer.email().utf8());
00577 
00578   if (!organizer.name().isEmpty()) {
00579     icalproperty_add_parameter( p, icalparameter_new_cn(quoteForParam(organizer.name()).utf8()) );
00580   }
00581   // TODO: Write dir, sent-by and language
00582 
00583   return p;
00584 }
00585 
00586 
00587 icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee)
00588 {
00589   icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8());
00590 
00591   if (!attendee->name().isEmpty()) {
00592     icalproperty_add_parameter(p,icalparameter_new_cn(quoteForParam(attendee->name()).utf8()));
00593   }
00594 
00595 
00596   icalproperty_add_parameter(p,icalparameter_new_rsvp(
00597           attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE ));
00598 
00599   icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
00600   switch (attendee->status()) {
00601     default:
00602     case Attendee::NeedsAction:
00603       status = ICAL_PARTSTAT_NEEDSACTION;
00604       break;
00605     case Attendee::Accepted:
00606       status = ICAL_PARTSTAT_ACCEPTED;
00607       break;
00608     case Attendee::Declined:
00609       status = ICAL_PARTSTAT_DECLINED;
00610       break;
00611     case Attendee::Tentative:
00612       status = ICAL_PARTSTAT_TENTATIVE;
00613       break;
00614     case Attendee::Delegated:
00615       status = ICAL_PARTSTAT_DELEGATED;
00616       break;
00617     case Attendee::Completed:
00618       status = ICAL_PARTSTAT_COMPLETED;
00619       break;
00620     case Attendee::InProcess:
00621       status = ICAL_PARTSTAT_INPROCESS;
00622       break;
00623   }
00624   icalproperty_add_parameter(p,icalparameter_new_partstat(status));
00625 
00626   icalparameter_role role = ICAL_ROLE_REQPARTICIPANT;
00627   switch (attendee->role()) {
00628     case Attendee::Chair:
00629       role = ICAL_ROLE_CHAIR;
00630       break;
00631     default:
00632     case Attendee::ReqParticipant:
00633       role = ICAL_ROLE_REQPARTICIPANT;
00634       break;
00635     case Attendee::OptParticipant:
00636       role = ICAL_ROLE_OPTPARTICIPANT;
00637       break;
00638     case Attendee::NonParticipant:
00639       role = ICAL_ROLE_NONPARTICIPANT;
00640       break;
00641   }
00642   icalproperty_add_parameter(p,icalparameter_new_role(role));
00643 
00644   if (!attendee->uid().isEmpty()) {
00645     icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8());
00646     icalparameter_set_xname(icalparameter_uid,"X-UID");
00647     icalproperty_add_parameter(p,icalparameter_uid);
00648   }
00649 
00650   if ( !attendee->delegate().isEmpty() ) {
00651     icalparameter* icalparameter_delegate = icalparameter_new_delegatedto( attendee->delegate().utf8() );
00652     icalproperty_add_parameter( p, icalparameter_delegate );
00653   }
00654 
00655   if ( !attendee->delegator().isEmpty() ) {
00656     icalparameter* icalparameter_delegator = icalparameter_new_delegatedfrom( attendee->delegator().utf8() );
00657     icalproperty_add_parameter( p, icalparameter_delegator );
00658   }
00659 
00660   return p;
00661 }
00662 
00663 icalproperty *ICalFormatImpl::writeAttachment( Attachment *att )
00664 {
00665   icalattach *attach;
00666   if ( att->isUri() ) {
00667     attach = icalattach_new_from_url( att->uri().utf8().data() );
00668   } else {
00669 #ifdef USE_LIBICAL_0_46
00670     attach = icalattach_new_from_data ( (const char *)att->data(), 0, 0 );
00671 #else
00672     attach = icalattach_new_from_data ( (unsigned char *)att->data(), 0, 0 );
00673 #endif
00674   }
00675   icalproperty *p = icalproperty_new_attach( attach );
00676 
00677   if ( !att->mimeType().isEmpty() ) {
00678     icalproperty_add_parameter( p,
00679         icalparameter_new_fmttype( att->mimeType().utf8().data() ) );
00680   }
00681 
00682   if ( att->isBinary() ) {
00683     icalproperty_add_parameter( p,
00684         icalparameter_new_value( ICAL_VALUE_BINARY ) );
00685     icalproperty_add_parameter( p,
00686         icalparameter_new_encoding( ICAL_ENCODING_BASE64 ) );
00687   }
00688 
00689   if ( att->showInline() ) {
00690     icalparameter* icalparameter_inline = icalparameter_new_x( "inline" );
00691     icalparameter_set_xname( icalparameter_inline, "X-CONTENT-DISPOSITION" );
00692     icalproperty_add_parameter( p, icalparameter_inline );
00693   }
00694 
00695   if ( !att->label().isEmpty() ) {
00696     icalparameter* icalparameter_label = icalparameter_new_x( att->label().utf8() );
00697     icalparameter_set_xname( icalparameter_label, "X-LABEL" );
00698     icalproperty_add_parameter( p, icalparameter_label );
00699   }
00700 
00701   return p;
00702 }
00703 
00704 icalrecurrencetype ICalFormatImpl::writeRecurrenceRule( RecurrenceRule *recur )
00705 {
00706 //  kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl;
00707 
00708   icalrecurrencetype r;
00709   icalrecurrencetype_clear(&r);
00710 
00711   switch( recur->recurrenceType() ) {
00712     case RecurrenceRule::rSecondly:
00713       r.freq = ICAL_SECONDLY_RECURRENCE;
00714       break;
00715     case RecurrenceRule::rMinutely:
00716       r.freq = ICAL_MINUTELY_RECURRENCE;
00717       break;
00718     case RecurrenceRule::rHourly:
00719       r.freq = ICAL_HOURLY_RECURRENCE;
00720       break;
00721     case RecurrenceRule::rDaily:
00722       r.freq = ICAL_DAILY_RECURRENCE;
00723       break;
00724     case RecurrenceRule::rWeekly:
00725       r.freq = ICAL_WEEKLY_RECURRENCE;
00726       break;
00727     case RecurrenceRule::rMonthly:
00728       r.freq = ICAL_MONTHLY_RECURRENCE;
00729       break;
00730     case RecurrenceRule::rYearly:
00731       r.freq = ICAL_YEARLY_RECURRENCE;
00732       break;
00733     default:
00734       r.freq = ICAL_NO_RECURRENCE;
00735       kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl;
00736       break;
00737   }
00738 
00739   int index = 0;
00740   TQValueList<int> bys;
00741   TQValueList<int>::ConstIterator it;
00742 
00743   // Now write out the BY* parts:
00744   bys = recur->bySeconds();
00745   index = 0;
00746   for ( it = bys.begin(); it != bys.end(); ++it ) {
00747     r.by_second[index++] = *it;
00748   }
00749 
00750   bys = recur->byMinutes();
00751   index = 0;
00752   for ( it = bys.begin(); it != bys.end(); ++it ) {
00753     r.by_minute[index++] = *it;
00754   }
00755 
00756   bys = recur->byHours();
00757   index = 0;
00758   for ( it = bys.begin(); it != bys.end(); ++it ) {
00759     r.by_hour[index++] = *it;
00760   }
00761 
00762   bys = recur->byMonthDays();
00763   index = 0;
00764   for ( it = bys.begin(); it != bys.end(); ++it ) {
00765     r.by_month_day[index++] = icalrecurrencetype_day_position( (*it) * 8 );
00766   }
00767 
00768   bys = recur->byYearDays();
00769   index = 0;
00770   for ( it = bys.begin(); it != bys.end(); ++it ) {
00771     r.by_year_day[index++] = *it;
00772   }
00773 
00774   bys = recur->byWeekNumbers();
00775   index = 0;
00776   for ( it = bys.begin(); it != bys.end(); ++it ) {
00777      r.by_week_no[index++] = *it;
00778   }
00779 
00780   bys = recur->byMonths();
00781   index = 0;
00782   for ( it = bys.begin(); it != bys.end(); ++it ) {
00783     r.by_month[index++] = *it;
00784   }
00785 
00786   bys = recur->bySetPos();
00787   index = 0;
00788   for ( it = bys.begin(); it != bys.end(); ++it ) {
00789      r.by_set_pos[index++] = *it;
00790   }
00791 
00792 
00793   TQValueList<RecurrenceRule::WDayPos> byd = recur->byDays();
00794   int day;
00795   index = 0;
00796   for ( TQValueList<RecurrenceRule::WDayPos>::ConstIterator dit = byd.begin();
00797         dit != byd.end(); ++dit ) {
00798     day = (*dit).day() % 7 + 1;     // convert from Monday=1 to Sunday=1
00799     if ( (*dit).pos() < 0 ) {
00800       day += (-(*dit).pos())*8;
00801       day = -day;
00802     } else {
00803       day += (*dit).pos()*8;
00804     }
00805     r.by_day[index++] = day;
00806   }
00807 
00808   r.week_start = static_cast<icalrecurrencetype_weekday>(
00809                                              recur->weekStart()%7 + 1);
00810 
00811   if ( recur->frequency() > 1 ) {
00812     // Dont' write out INTERVAL=1, because that's the default anyway
00813     r.interval = recur->frequency();
00814   }
00815 
00816   if ( recur->duration() > 0 ) {
00817     r.count = recur->duration();
00818   } else if ( recur->duration() == -1 ) {
00819     r.count = 0;
00820   } else {
00821     if ( recur->doesFloat() )
00822       r.until = writeICalDate(recur->endDt().date());
00823     else
00824       r.until = writeICalDateTime(recur->endDt());
00825   }
00826 
00827 // Debug output
00828 #if 0
00829   const char *str = icalrecurrencetype_as_string(&r);
00830   if (str) {
00831     kdDebug(5800) << " String: " << str << endl;
00832   } else {
00833     kdDebug(5800) << " No String" << endl;
00834   }
00835 #endif
00836 
00837   return r;
00838 }
00839 
00840 
00841 icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm)
00842 {
00843 // kdDebug(5800) << " ICalFormatImpl::writeAlarm" << endl;
00844   icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT);
00845 
00846   icalproperty_action action;
00847   icalattach *attach = 0;
00848 
00849   switch (alarm->type()) {
00850     case Alarm::Procedure:
00851       action = ICAL_ACTION_PROCEDURE;
00852       attach = icalattach_new_from_url(TQFile::encodeName(alarm->programFile()).data());
00853       icalcomponent_add_property(a,icalproperty_new_attach(attach));
00854       if (!alarm->programArguments().isEmpty()) {
00855         icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8()));
00856       }
00857       break;
00858     case Alarm::Audio:
00859       action = ICAL_ACTION_AUDIO;
00860 // kdDebug(5800) << " It's an audio action, file: " << alarm->audioFile() << endl;
00861       if (!alarm->audioFile().isEmpty()) {
00862         attach = icalattach_new_from_url(TQFile::encodeName( alarm->audioFile() ).data());
00863         icalcomponent_add_property(a,icalproperty_new_attach(attach));
00864       }
00865       break;
00866     case Alarm::Email: {
00867       action = ICAL_ACTION_EMAIL;
00868       TQValueList<Person> addresses = alarm->mailAddresses();
00869       for (TQValueList<Person>::Iterator ad = addresses.begin();  ad != addresses.end();  ++ad) {
00870         icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8());
00871         if (!(*ad).name().isEmpty()) {
00872           icalproperty_add_parameter(p,icalparameter_new_cn(quoteForParam((*ad).name()).utf8()));
00873         }
00874         icalcomponent_add_property(a,p);
00875       }
00876       icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8()));
00877       icalcomponent_add_property(a,icalproperty_new_description(alarm->mailText().utf8()));
00878       TQStringList attachments = alarm->mailAttachments();
00879       if (attachments.count() > 0) {
00880         for (TQStringList::Iterator at = attachments.begin();  at != attachments.end();  ++at) {
00881           attach = icalattach_new_from_url(TQFile::encodeName( *at ).data());
00882           icalcomponent_add_property(a,icalproperty_new_attach(attach));
00883         }
00884       }
00885       break;
00886     }
00887     case Alarm::Display:
00888       action = ICAL_ACTION_DISPLAY;
00889       icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
00890       break;
00891     case Alarm::Invalid:
00892     default:
00893       kdDebug(5800) << "Unknown type of alarm" << endl;
00894       action = ICAL_ACTION_NONE;
00895       break;
00896   }
00897   icalcomponent_add_property(a,icalproperty_new_action(action));
00898 
00899   // Trigger time
00900   icaltriggertype trigger;
00901   if ( alarm->hasTime() ) {
00902     trigger.time = writeICalDateTime(alarm->time());
00903     trigger.duration = icaldurationtype_null_duration();
00904   } else {
00905     trigger.time = icaltime_null_time();
00906     Duration offset;
00907     if ( alarm->hasStartOffset() )
00908       offset = alarm->startOffset();
00909     else
00910       offset = alarm->endOffset();
00911     trigger.duration = writeICalDuration( offset.asSeconds() );
00912   }
00913   icalproperty *p = icalproperty_new_trigger(trigger);
00914   if ( alarm->hasEndOffset() )
00915     icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END));
00916   icalcomponent_add_property(a,p);
00917 
00918   // Repeat count and duration
00919   if (alarm->repeatCount()) {
00920     icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount()));
00921     icalcomponent_add_property(a,icalproperty_new_duration(
00922                                  writeICalDuration(alarm->snoozeTime().value())));
00923   }
00924 
00925   // Custom properties
00926   TQMap<TQCString, TQString> custom = alarm->customProperties();
00927   for (TQMap<TQCString, TQString>::Iterator c = custom.begin();  c != custom.end();  ++c) {
00928     icalproperty *p = icalproperty_new_x(c.data().utf8());
00929     icalproperty_set_x_name(p,c.key());
00930     icalcomponent_add_property(a,p);
00931   }
00932 
00933   return a;
00934 }
00935 
00936 Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo)
00937 {
00938   Todo *todo = new Todo;
00939 
00940   readIncidence(vtodo, 0, todo); // FIXME timezone
00941 
00942   icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY);
00943 
00944 //  int intvalue;
00945   icaltimetype icaltime;
00946 
00947   TQStringList categories;
00948 
00949   while (p) {
00950     icalproperty_kind kind = icalproperty_isa(p);
00951     switch (kind) {
00952 
00953       case ICAL_DUE_PROPERTY:  // due date
00954         icaltime = icalproperty_get_due(p);
00955         if (icaltime.is_date) {
00956           todo->setDtDue(TQDateTime(readICalDate(icaltime),TQTime(0,0,0)),true);
00957         } else {
00958           todo->setDtDue(readICalDateTime(p, icaltime),true);
00959           todo->setFloats(false);
00960         }
00961         todo->setHasDueDate(true);
00962         break;
00963 
00964       case ICAL_COMPLETED_PROPERTY:  // completion date
00965         icaltime = icalproperty_get_completed(p);
00966         todo->setCompleted(readICalDateTime(p, icaltime));
00967         break;
00968 
00969       case ICAL_PERCENTCOMPLETE_PROPERTY:  // Percent completed
00970         todo->setPercentComplete(icalproperty_get_percentcomplete(p));
00971         break;
00972 
00973       case ICAL_RELATEDTO_PROPERTY:  // related todo (parent)
00974         todo->setRelatedToUid(TQString::fromUtf8(icalproperty_get_relatedto(p)));
00975         mTodosRelate.append(todo);
00976         break;
00977 
00978       case ICAL_DTSTART_PROPERTY: {
00979         // Flag that todo has start date. Value is read in by readIncidence().
00980         if ( todo->comments().grep("NoStartDate").count() )
00981           todo->setHasStartDate( false );
00982         else
00983           todo->setHasStartDate( true );
00984         break;
00985       }
00986 
00987       case ICAL_RECURRENCEID_PROPERTY:
00988         icaltime = icalproperty_get_recurrenceid(p);
00989         todo->setDtRecurrence( readICalDateTime(p, icaltime) );
00990         break;
00991 
00992       default:
00993 //        kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind
00994 //                  << endl;
00995         break;
00996     }
00997 
00998     p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY);
00999   }
01000 
01001   if (mCompat) mCompat->fixEmptySummary( todo );
01002 
01003   return todo;
01004 }
01005 
01006 Event *ICalFormatImpl::readEvent( icalcomponent *vevent, icalcomponent *vtimezone )
01007 {
01008   Event *event = new Event;
01009 
01010   // FIXME where is this freed?
01011   icaltimezone *tz = icaltimezone_new();
01012   if ( !icaltimezone_set_component( tz, vtimezone ) ) {
01013     icaltimezone_free( tz, 1 );
01014     tz = 0;
01015   }
01016 
01017   readIncidence( vevent, tz, event);
01018 
01019   icalproperty *p = icalcomponent_get_first_property( vevent, ICAL_ANY_PROPERTY );
01020 
01021   // int intvalue;
01022   icaltimetype icaltime;
01023 
01024   TQStringList categories;
01025   icalproperty_transp transparency;
01026 
01027   bool dtEndProcessed = false;
01028 
01029   while ( p ) {
01030     icalproperty_kind kind = icalproperty_isa( p );
01031     switch ( kind ) {
01032 
01033       case ICAL_DTEND_PROPERTY:  // start date and time
01034         icaltime = icalproperty_get_dtend( p );
01035         if ( icaltime.is_date ) {
01036           // End date is non-inclusive
01037           TQDate endDate = readICalDate( icaltime ).addDays( -1 );
01038           if ( mCompat ) {
01039             mCompat->fixFloatingEnd( endDate );
01040           }
01041 
01042           if ( endDate < event->dtStart().date() ) {
01043             endDate = event->dtStart().date();
01044           }
01045           event->setDtEnd( TQDateTime( endDate, TQTime( 0, 0, 0 ) ) );
01046         } else {
01047           event->setDtEnd(readICalDateTime(p, icaltime, tz));
01048           event->setFloats( false );
01049         }
01050         dtEndProcessed = true;
01051         break;
01052 
01053       case ICAL_RELATEDTO_PROPERTY:  // related event (parent)
01054         event->setRelatedToUid( TQString::fromUtf8( icalproperty_get_relatedto( p ) ) );
01055         mEventsRelate.append( event );
01056         break;
01057 
01058       case ICAL_TRANSP_PROPERTY:  // Transparency
01059         transparency = icalproperty_get_transp( p );
01060         if ( transparency == ICAL_TRANSP_TRANSPARENT ) {
01061           event->setTransparency( Event::Transparent );
01062         } else {
01063           event->setTransparency( Event::Opaque );
01064         }
01065         break;
01066 
01067       default:
01068         //  kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind
01069         //                << endl;
01070         break;
01071     }
01072 
01073     p = icalcomponent_get_next_property( vevent, ICAL_ANY_PROPERTY );
01074   }
01075 
01076   // according to rfc2445 the dtend shouldn't be written when it equals
01077   // start date. so assign one equal to start date.
01078   if ( !dtEndProcessed && !event->hasDuration() ) {
01079     event->setDtEnd( event->dtStart() );
01080   }
01081 
01082   const TQString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT");
01083   if ( !msade.isEmpty() ) {
01084     const bool floats = ( msade == TQString::fromLatin1("TRUE") );
01085     event->setFloats(floats);
01086   }
01087 
01088   if ( mCompat ) {
01089     mCompat->fixEmptySummary( event );
01090   }
01091 
01092   return event;
01093 }
01094 
01095 FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy)
01096 {
01097   FreeBusy *freebusy = new FreeBusy;
01098 
01099   readIncidenceBase(vfreebusy, freebusy);
01100 
01101   icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY);
01102 
01103   icaltimetype icaltime;
01104   PeriodList periods;
01105 
01106   while (p) {
01107     icalproperty_kind kind = icalproperty_isa(p);
01108     switch (kind) {
01109 
01110       case ICAL_DTSTART_PROPERTY:  // start date and time
01111         icaltime = icalproperty_get_dtstart(p);
01112         freebusy->setDtStart(readICalDateTime(p, icaltime));
01113         break;
01114 
01115       case ICAL_DTEND_PROPERTY:  // end Date and Time
01116         icaltime = icalproperty_get_dtend(p);
01117         freebusy->setDtEnd(readICalDateTime(p, icaltime));
01118         break;
01119 
01120       case ICAL_FREEBUSY_PROPERTY:  //Any FreeBusy Times
01121       {
01122         icalperiodtype icalperiod = icalproperty_get_freebusy(p);
01123         TQDateTime period_start = readICalDateTime(p, icalperiod.start);
01124         Period period;
01125         if ( !icaltime_is_null_time(icalperiod.end) ) {
01126           TQDateTime period_end = readICalDateTime(p, icalperiod.end);
01127           period = Period(period_start, period_end);
01128         } else {
01129           Duration duration = readICalDuration( icalperiod.duration );
01130           period = Period(period_start, duration);
01131         }
01132         icalparameter *param = icalproperty_get_first_parameter( p, ICAL_X_PARAMETER );
01133         while ( param ) {
01134           if ( strncmp( icalparameter_get_xname( param ), "X-SUMMARY", 9 ) == 0 ) {
01135             period.setSummary( TQString::fromUtf8(
01136                                  KCodecs::base64Decode( TQCString( icalparameter_get_xvalue( param ) ) ) ) );
01137           }
01138           if ( strncmp( icalparameter_get_xname( param ), "X-LOCATION", 10 ) == 0 ) {
01139             period.setLocation( TQString::fromUtf8(
01140                                   KCodecs::base64Decode( TQCString( icalparameter_get_xvalue( param ) ) ) ) );
01141           }
01142           param = icalproperty_get_next_parameter( p, ICAL_X_PARAMETER );
01143         }
01144         periods.append( period );
01145         break;
01146       }
01147 
01148       default:
01149 //        kdDebug(5800) << "ICalFormatImpl::readFreeBusy(): Unknown property: "
01150 //                      << kind << endl;
01151       break;
01152     }
01153     p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY);
01154   }
01155   freebusy->addPeriods( periods );
01156 
01157   return freebusy;
01158 }
01159 
01160 Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal)
01161 {
01162   Journal *journal = new Journal;
01163 
01164   readIncidence(vjournal, 0, journal); // FIXME tz?
01165 
01166   return journal;
01167 }
01168 
01169 Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee)
01170 {
01171   icalparameter *p = 0;
01172 
01173   TQString email = TQString::fromUtf8(icalproperty_get_attendee(attendee));
01174   if ( email.startsWith( "mailto:", false ) ) {
01175     email = email.mid( 7 );
01176   }
01177 
01178   TQString name;
01179   TQString uid = TQString();
01180   p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER);
01181   if (p) {
01182     name = TQString::fromUtf8(icalparameter_get_cn(p));
01183   } else {
01184   }
01185 
01186   bool rsvp=false;
01187   p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER);
01188   if (p) {
01189     icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p);
01190     if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true;
01191   }
01192 
01193   Attendee::PartStat status = Attendee::NeedsAction;
01194   p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER);
01195   if (p) {
01196     icalparameter_partstat partStatParameter = icalparameter_get_partstat(p);
01197     switch(partStatParameter) {
01198       default:
01199       case ICAL_PARTSTAT_NEEDSACTION:
01200         status = Attendee::NeedsAction;
01201         break;
01202       case ICAL_PARTSTAT_ACCEPTED:
01203         status = Attendee::Accepted;
01204         break;
01205       case ICAL_PARTSTAT_DECLINED:
01206         status = Attendee::Declined;
01207         break;
01208       case ICAL_PARTSTAT_TENTATIVE:
01209         status = Attendee::Tentative;
01210         break;
01211       case ICAL_PARTSTAT_DELEGATED:
01212         status = Attendee::Delegated;
01213         break;
01214       case ICAL_PARTSTAT_COMPLETED:
01215         status = Attendee::Completed;
01216         break;
01217       case ICAL_PARTSTAT_INPROCESS:
01218         status = Attendee::InProcess;
01219         break;
01220     }
01221   }
01222 
01223   Attendee::Role role = Attendee::ReqParticipant;
01224   p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER);
01225   if (p) {
01226     icalparameter_role roleParameter = icalparameter_get_role(p);
01227     switch(roleParameter) {
01228       case ICAL_ROLE_CHAIR:
01229         role = Attendee::Chair;
01230         break;
01231       default:
01232       case ICAL_ROLE_REQPARTICIPANT:
01233         role = Attendee::ReqParticipant;
01234         break;
01235       case ICAL_ROLE_OPTPARTICIPANT:
01236         role = Attendee::OptParticipant;
01237         break;
01238       case ICAL_ROLE_NONPARTICIPANT:
01239         role = Attendee::NonParticipant;
01240         break;
01241     }
01242   }
01243 
01244   p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER);
01245   uid = icalparameter_get_xvalue(p);
01246   // This should be added, but there seems to be a libical bug here.
01247   // TODO: does this work now in libical-0.24 or greater?
01248   /*while (p) {
01249    // if (icalparameter_get_xname(p) == "X-UID") {
01250     uid = icalparameter_get_xvalue(p);
01251     p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER);
01252   } */
01253 
01254   Attendee *a = new Attendee( name, email, rsvp, status, role, uid );
01255 
01256   p = icalproperty_get_first_parameter( attendee, ICAL_DELEGATEDTO_PARAMETER );
01257   if ( p )
01258     a->setDelegate( icalparameter_get_delegatedto( p ) );
01259 
01260   p = icalproperty_get_first_parameter( attendee, ICAL_DELEGATEDFROM_PARAMETER );
01261   if ( p )
01262     a->setDelegator( icalparameter_get_delegatedfrom( p ) );
01263 
01264   return a;
01265 }
01266 
01267 Person ICalFormatImpl::readOrganizer( icalproperty *organizer )
01268 {
01269   TQString email = TQString::fromUtf8(icalproperty_get_organizer(organizer));
01270   if ( email.startsWith( "mailto:", false ) ) {
01271     email = email.mid( 7 );
01272   }
01273   TQString cn;
01274 
01275   icalparameter *p = icalproperty_get_first_parameter(
01276              organizer, ICAL_CN_PARAMETER );
01277 
01278   if ( p ) {
01279     cn = TQString::fromUtf8( icalparameter_get_cn( p ) );
01280   }
01281   Person org( cn, email );
01282   // TODO: Treat sent-by, dir and language here, too
01283   return org;
01284 }
01285 
01286 Attachment *ICalFormatImpl::readAttachment(icalproperty *attach)
01287 {
01288   Attachment *attachment = 0;
01289 
01290   const char *p;
01291   icalvalue *value = icalproperty_get_value( attach );
01292 
01293   switch( icalvalue_isa( value ) ) {
01294   case ICAL_ATTACH_VALUE:
01295   {
01296     icalattach *a = icalproperty_get_attach( attach );
01297     if ( !icalattach_get_is_url( a ) ) {
01298       p = (const char *)icalattach_get_data( a );
01299       if ( p ) {
01300         attachment = new Attachment( p );
01301       }
01302     } else {
01303       p = icalattach_get_url( a );
01304       if ( p ) {
01305         attachment = new Attachment( TQString::fromUtf8( p ) );
01306       }
01307     }
01308     break;
01309   }
01310   case ICAL_BINARY_VALUE:
01311   {
01312     icalattach *a = icalproperty_get_attach( attach );
01313     p = (const char *)icalattach_get_data( a );
01314     if ( p ) {
01315       attachment = new Attachment( p );
01316     }
01317     break;
01318   }
01319   case ICAL_URI_VALUE:
01320     p = icalvalue_get_uri( value );
01321     attachment = new Attachment( TQString::fromUtf8( p ) );
01322     break;
01323   default:
01324     break;
01325   }
01326 
01327  if ( attachment ) {
01328     icalparameter *p =
01329       icalproperty_get_first_parameter( attach, ICAL_FMTTYPE_PARAMETER );
01330     if ( p ) {
01331       attachment->setMimeType( TQString( icalparameter_get_fmttype( p ) ) );
01332     }
01333 
01334     p = icalproperty_get_first_parameter( attach, ICAL_X_PARAMETER );
01335     while ( p ) {
01336       TQString xname = TQString( icalparameter_get_xname( p ) ).upper();
01337       TQString xvalue = TQString::fromUtf8( icalparameter_get_xvalue( p ) );
01338       if ( xname == "X-CONTENT-DISPOSITION" ) {
01339         attachment->setShowInline( xvalue.lower() == "inline" );
01340       }
01341       if ( xname == "X-LABEL" ) {
01342         attachment->setLabel( xvalue );
01343       }
01344       p = icalproperty_get_next_parameter( attach, ICAL_X_PARAMETER );
01345     }
01346 
01347     p = icalproperty_get_first_parameter( attach, ICAL_X_PARAMETER );
01348     while ( p ) {
01349       if ( strncmp( icalparameter_get_xname( p ), "X-LABEL", 7 ) == 0 ) {
01350         attachment->setLabel( TQString::fromUtf8( icalparameter_get_xvalue( p ) ) );
01351       }
01352       p = icalproperty_get_next_parameter( attach, ICAL_X_PARAMETER );
01353     }
01354   }
01355 
01356   return attachment;
01357 }
01358 
01359 void ICalFormatImpl::readIncidence(icalcomponent *parent, icaltimezone *tz, Incidence *incidence)
01360 {
01361   readIncidenceBase(parent,incidence);
01362 
01363   icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
01364 
01365   const char *text;
01366   int intvalue, inttext;
01367   icaltimetype icaltime;
01368   icaldurationtype icalduration;
01369 
01370   TQStringList categories;
01371 
01372   while (p) {
01373     icalproperty_kind kind = icalproperty_isa(p);
01374     switch (kind) {
01375 
01376       case ICAL_CREATED_PROPERTY:
01377         icaltime = icalproperty_get_created(p);
01378         incidence->setCreated(readICalDateTime(p, icaltime, tz));
01379         break;
01380 
01381       case ICAL_SEQUENCE_PROPERTY:  // sequence
01382         intvalue = icalproperty_get_sequence(p);
01383         incidence->setRevision(intvalue);
01384         break;
01385 
01386       case ICAL_LASTMODIFIED_PROPERTY:  // last modification date
01387         icaltime = icalproperty_get_lastmodified(p);
01388         incidence->setLastModified(readICalDateTime(p, icaltime, tz));
01389         break;
01390 
01391       case ICAL_DTSTART_PROPERTY:  // start date and time
01392         icaltime = icalproperty_get_dtstart(p);
01393         if (icaltime.is_date) {
01394           incidence->setDtStart(TQDateTime(readICalDate(icaltime),TQTime(0,0,0)));
01395           incidence->setFloats( true );
01396         } else {
01397           incidence->setDtStart(readICalDateTime(p, icaltime, tz));
01398           incidence->setFloats( false );
01399         }
01400         break;
01401 
01402       case ICAL_DURATION_PROPERTY:  // start date and time
01403         icalduration = icalproperty_get_duration(p);
01404         incidence->setDuration(readICalDuration(icalduration));
01405         break;
01406 
01407       case ICAL_DESCRIPTION_PROPERTY:  // description
01408         text = icalproperty_get_description(p);
01409         incidence->setDescription(TQString::fromUtf8(text));
01410         break;
01411 
01412       case ICAL_SUMMARY_PROPERTY:  // summary
01413         text = icalproperty_get_summary(p);
01414         incidence->setSummary(TQString::fromUtf8(text));
01415         break;
01416 
01417       case ICAL_LOCATION_PROPERTY:  // location
01418         text = icalproperty_get_location(p);
01419         incidence->setLocation(TQString::fromUtf8(text));
01420         break;
01421 
01422       case ICAL_STATUS_PROPERTY: {  // status
01423         Incidence::Status stat;
01424         switch (icalproperty_get_status(p)) {
01425           case ICAL_STATUS_TENTATIVE:   stat = Incidence::StatusTentative; break;
01426           case ICAL_STATUS_CONFIRMED:   stat = Incidence::StatusConfirmed; break;
01427           case ICAL_STATUS_COMPLETED:   stat = Incidence::StatusCompleted; break;
01428           case ICAL_STATUS_NEEDSACTION: stat = Incidence::StatusNeedsAction; break;
01429           case ICAL_STATUS_CANCELLED:   stat = Incidence::StatusCanceled; break;
01430           case ICAL_STATUS_INPROCESS:   stat = Incidence::StatusInProcess; break;
01431           case ICAL_STATUS_DRAFT:       stat = Incidence::StatusDraft; break;
01432           case ICAL_STATUS_FINAL:       stat = Incidence::StatusFinal; break;
01433           case ICAL_STATUS_X:
01434             incidence->setCustomStatus(TQString::fromUtf8(icalvalue_get_x(icalproperty_get_value(p))));
01435             stat = Incidence::StatusX;
01436             break;
01437           case ICAL_STATUS_NONE:
01438           default:                      stat = Incidence::StatusNone; break;
01439         }
01440         if (stat != Incidence::StatusX)
01441           incidence->setStatus(stat);
01442         break;
01443       }
01444 
01445       case ICAL_PRIORITY_PROPERTY:  // priority
01446         intvalue = icalproperty_get_priority( p );
01447         if ( mCompat )
01448           intvalue = mCompat->fixPriority( intvalue );
01449         incidence->setPriority( intvalue );
01450         break;
01451 
01452       case ICAL_CATEGORIES_PROPERTY:  // categories
01453         text = icalproperty_get_categories(p);
01454         categories.append(TQString::fromUtf8(text));
01455         break;
01456 
01457       case ICAL_RECURRENCEID_PROPERTY:  // recurrenceID
01458         icaltime = icalproperty_get_recurrenceid(p);
01459         incidence->setRecurrenceID( readICalDateTime( p, icaltime ) );
01460         incidence->setHasRecurrenceID( true );
01461         break;
01462 
01463       case ICAL_RRULE_PROPERTY:
01464         readRecurrenceRule( p, incidence );
01465         break;
01466 
01467 //       case ICAL_CONTACT_PROPERTY:
01468 //         incidenceBase->addContact(
01469 //           TQString::fromUtf8( icalproperty_get_contact( p ) ) );
01470 //         break;
01471 
01472       case ICAL_RDATE_PROPERTY: {
01473         icaldatetimeperiodtype rd = icalproperty_get_rdate( p );
01474         if ( icaltime_is_valid_time( rd.time ) ) {
01475           if ( icaltime_is_date( rd.time ) ) {
01476             incidence->recurrence()->addRDate( readICalDate( rd.time ) );
01477           } else {
01478             incidence->recurrence()->addRDateTime( readICalDateTime(p, rd.time, tz ) );
01479           }
01480         } else {
01481           // TODO: RDates as period are not yet implemented!
01482         }
01483         break; }
01484 
01485       case ICAL_EXRULE_PROPERTY:
01486         readExceptionRule( p, incidence );
01487         break;
01488 
01489       case ICAL_EXDATE_PROPERTY:
01490         icaltime = icalproperty_get_exdate(p);
01491         if ( icaltime_is_date(icaltime) ) {
01492           incidence->recurrence()->addExDate( readICalDate(icaltime) );
01493         } else {
01494           incidence->recurrence()->addExDateTime( readICalDateTime(p, icaltime, tz) );
01495         }
01496         break;
01497 
01498       case ICAL_CLASS_PROPERTY:
01499         inttext = icalproperty_get_class(p);
01500         if (inttext == ICAL_CLASS_PUBLIC ) {
01501           incidence->setSecrecy(Incidence::SecrecyPublic);
01502         } else if (inttext == ICAL_CLASS_CONFIDENTIAL ) {
01503           incidence->setSecrecy(Incidence::SecrecyConfidential);
01504         } else {
01505           incidence->setSecrecy(Incidence::SecrecyPrivate);
01506         }
01507         break;
01508 
01509       case ICAL_ATTACH_PROPERTY:  // attachments
01510         incidence->addAttachment(readAttachment(p));
01511         break;
01512 
01513       default:
01514 //        kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
01515 //                  << endl;
01516         break;
01517     }
01518 
01519     p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
01520   }
01521 
01522   // Set the scheduling ID
01523   const TQString uid = incidence->customProperty( "LIBKCAL", "ID" );
01524   if ( !uid.isNull() ) {
01525     // The UID stored in incidencebase is actually the scheduling ID
01526     // It has to be stored in the iCal UID component for compatibility
01527     // with other iCal applications
01528     incidence->setSchedulingID( incidence->uid() );
01529     incidence->setUid( uid );
01530   }
01531 
01532   // Now that recurrence and exception stuff is completely set up,
01533   // do any backwards compatibility adjustments.
01534   if ( incidence->doesRecur() && mCompat )
01535       mCompat->fixRecurrence( incidence );
01536 
01537   // add categories
01538   incidence->setCategories(categories);
01539 
01540   // iterate through all alarms
01541   for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT);
01542        alarm;
01543        alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) {
01544     readAlarm(alarm,incidence);
01545   }
01546   // Fix incorrect alarm settings by other applications (like outloook 9)
01547   if ( mCompat ) mCompat->fixAlarms( incidence );
01548 
01549 }
01550 
01551 void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
01552 {
01553   icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
01554 
01555   bool uidProcessed = false;
01556 
01557   while ( p ) {
01558     icalproperty_kind kind = icalproperty_isa( p );
01559     switch (kind) {
01560 
01561       case ICAL_UID_PROPERTY:  // unique id
01562         uidProcessed = true;
01563         incidenceBase->setUid( TQString::fromUtf8(icalproperty_get_uid( p ) ) );
01564         break;
01565 
01566       case ICAL_ORGANIZER_PROPERTY:  // organizer
01567         incidenceBase->setOrganizer( readOrganizer( p ) );
01568         break;
01569 
01570       case ICAL_ATTENDEE_PROPERTY:  // attendee
01571         incidenceBase->addAttendee( readAttendee( p ) );
01572         break;
01573 
01574       case ICAL_COMMENT_PROPERTY:
01575         incidenceBase->addComment(
01576             TQString::fromUtf8( icalproperty_get_comment( p ) ) );
01577         break;
01578 
01579       default:
01580         break;
01581     }
01582 
01583     p = icalcomponent_get_next_property( parent, ICAL_ANY_PROPERTY );
01584   }
01585 
01586   if ( !uidProcessed ) {
01587     kdWarning() << "The incidence didn't have any UID! Report a bug "
01588                 << "to the application that generated this file."
01589                 << endl;
01590 
01591     // Our in-memory incidence has a random uid generated in Event's ctor.
01592     // Make it empty so it matches what's in the file:
01593     incidenceBase->setUid( TQString() );
01594 
01595     // Otherwise, next time we read the file, this function will return
01596     // an event with another random uid and we will have two events in the calendar.
01597   }
01598 
01599   // kpilot stuff
01600   // TODO: move this application-specific code to kpilot
01601   // need to get X-PILOT* attributes out, set correct properties, and get
01602   // rid of them...
01603   // Pointer fun, as per libical documentation
01604   // (documented in UsingLibical.txt)
01605   icalproperty *next =0;
01606 
01607   for ( p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
01608        p != 0;
01609        p = next )
01610   {
01611 
01612     next = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
01613 
01614     TQString value = TQString::fromUtf8(icalproperty_get_x(p));
01615     TQString name = icalproperty_get_x_name(p);
01616 
01617     if (name == "X-PILOTID" && !value.isEmpty()) {
01618       incidenceBase->setPilotId(value.toInt());
01619       icalcomponent_remove_property(parent,p);
01620     } else if (name == "X-PILOTSTAT" && !value.isEmpty()) {
01621       incidenceBase->setSyncStatus(value.toInt());
01622       icalcomponent_remove_property(parent,p);
01623     }
01624   }
01625 
01626   // custom properties
01627   readCustomProperties(parent, incidenceBase);
01628 }
01629 
01630 void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties)
01631 {
01632   TQMap<TQCString, TQString> customProperties;
01633   TQString lastProperty;
01634 
01635   icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
01636 
01637   while (p) {
01638 
01639     TQString value = TQString::fromUtf8(icalproperty_get_x(p));
01640     const char *name = icalproperty_get_x_name(p);
01641     if ( lastProperty != name ) {
01642       customProperties[name] = value;
01643     } else {
01644       customProperties[name] = customProperties[name].append( "," ).append( value );
01645     }
01646     // kdDebug(5800) << "Set custom property [" << name << '=' << value << ']' << endl;
01647     p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
01648     lastProperty = name;
01649   }
01650 
01651   properties->setCustomProperties(customProperties);
01652 }
01653 
01654 
01655 
01656 void ICalFormatImpl::readRecurrenceRule(icalproperty *rrule,Incidence *incidence )
01657 {
01658 //  kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
01659 
01660   Recurrence *recur = incidence->recurrence();
01661 
01662   struct icalrecurrencetype r = icalproperty_get_rrule(rrule);
01663 //   dumpIcalRecurrence(r);
01664 
01665   RecurrenceRule *recurrule = new RecurrenceRule( /*incidence*/ );
01666   recurrule->setStartDt( incidence->dtStart() );
01667   readRecurrence( r, recurrule );
01668   recur->addRRule( recurrule );
01669 }
01670 
01671 void ICalFormatImpl::readExceptionRule( icalproperty *rrule, Incidence *incidence )
01672 {
01673 //  kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
01674 
01675   struct icalrecurrencetype r = icalproperty_get_exrule(rrule);
01676 //   dumpIcalRecurrence(r);
01677 
01678   RecurrenceRule *recurrule = new RecurrenceRule( /*incidence*/ );
01679   recurrule->setStartDt( incidence->dtStart() );
01680   readRecurrence( r, recurrule );
01681 
01682   Recurrence *recur = incidence->recurrence();
01683   recur->addExRule( recurrule );
01684 }
01685 
01686 void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, RecurrenceRule* recur )
01687 {
01688   // Generate the RRULE string
01689   recur->mRRule = TQString( icalrecurrencetype_as_string( const_cast<struct icalrecurrencetype*>(&r) ) );
01690   // Period
01691   switch ( r.freq ) {
01692     case ICAL_SECONDLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rSecondly ); break;
01693     case ICAL_MINUTELY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rMinutely ); break;
01694     case ICAL_HOURLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rHourly ); break;
01695     case ICAL_DAILY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rDaily ); break;
01696     case ICAL_WEEKLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rWeekly ); break;
01697     case ICAL_MONTHLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rMonthly ); break;
01698     case ICAL_YEARLY_RECURRENCE: recur->setRecurrenceType( RecurrenceRule::rYearly ); break;
01699     case ICAL_NO_RECURRENCE:
01700     default:
01701         recur->setRecurrenceType( RecurrenceRule::rNone );
01702   }
01703   // Frequency
01704   recur->setFrequency( r.interval );
01705 
01706   // Duration & End Date
01707   if ( !icaltime_is_null_time( r.until ) ) {
01708     icaltimetype t;
01709     t = r.until;
01710     // Convert to the correct time zone! it's in UTC by specification.
01711     TQDateTime endDate( readICalDateTime(0, t) );
01712     recur->setEndDt( endDate );
01713   } else {
01714     if (r.count == 0)
01715       recur->setDuration( -1 );
01716     else
01717       recur->setDuration( r.count );
01718   }
01719 
01720   // Week start setting
01721   int wkst = (r.week_start + 5)%7 + 1;
01722   recur->setWeekStart( wkst );
01723 
01724   // And now all BY*
01725   TQValueList<int> lst;
01726   int i;
01727   int index = 0;
01728 
01729 #define readSetByList(rrulecomp,setfunc) \
01730   index = 0; \
01731   lst.clear(); \
01732   while ( (i = r.rrulecomp[index++] ) != ICAL_RECURRENCE_ARRAY_MAX ) \
01733     lst.append( i ); \
01734   if ( !lst.isEmpty() ) recur->setfunc( lst );
01735 
01736   // BYSECOND, MINUTE and HOUR, MONTHDAY, YEARDAY, WEEKNUMBER, MONTH
01737   // and SETPOS are standard int lists, so we can treat them with the
01738   // same macro
01739   readSetByList( by_second, setBySeconds );
01740   readSetByList( by_minute, setByMinutes );
01741   readSetByList( by_hour, setByHours );
01742   readSetByList( by_month_day, setByMonthDays );
01743   readSetByList( by_year_day, setByYearDays );
01744   readSetByList( by_week_no, setByWeekNumbers );
01745   readSetByList( by_month, setByMonths );
01746   readSetByList( by_set_pos, setBySetPos );
01747 #undef readSetByList
01748 
01749   // BYDAY is a special case, since it's not an int list
01750   TQValueList<RecurrenceRule::WDayPos> wdlst;
01751   short day;
01752   index=0;
01753   while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
01754     RecurrenceRule::WDayPos pos;
01755     pos.setDay( ( icalrecurrencetype_day_day_of_week( day ) + 5 )%7 + 1 );
01756     pos.setPos( icalrecurrencetype_day_position( day ) );
01757 //     kdDebug(5800)<< "    o) By day, index="<<index-1<<", pos="<<pos.Pos<<", day="<<pos.Day<<endl;
01758     wdlst.append( pos );
01759   }
01760   if ( !wdlst.isEmpty() ) recur->setByDays( wdlst );
01761 
01762 
01763   // TODO Store all X- fields of the RRULE inside the recurrence (so they are
01764   // preserved
01765 }
01766 
01767 
01768 void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence)
01769 {
01770 //   kdDebug(5800) << "Read alarm for " << incidence->summary() << endl;
01771 
01772   Alarm* ialarm = incidence->newAlarm();
01773   ialarm->setRepeatCount(0);
01774   ialarm->setEnabled(true);
01775 
01776   // Determine the alarm's action type
01777   icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY);
01778   Alarm::Type type = Alarm::Display;
01779   icalproperty_action action = ICAL_ACTION_DISPLAY;
01780   if ( !p ) {
01781     kdDebug(5800) << "Unknown type of alarm, using default" << endl;
01782 //    return;
01783   } else {
01784 
01785     action = icalproperty_get_action(p);
01786     switch ( action ) {
01787       case ICAL_ACTION_DISPLAY:   type = Alarm::Display;  break;
01788       case ICAL_ACTION_AUDIO:     type = Alarm::Audio;  break;
01789       case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure;  break;
01790       case ICAL_ACTION_EMAIL:     type = Alarm::Email;  break;
01791       default:
01792         kdDebug(5800) << "Unknown type of alarm: " << action << endl;
01793 //        type = Alarm::Invalid;
01794     }
01795   }
01796   ialarm->setType(type);
01797 // kdDebug(5800) << " alarm type =" << type << endl;
01798 
01799   p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY);
01800   while (p) {
01801     icalproperty_kind kind = icalproperty_isa(p);
01802 
01803     switch (kind) {
01804 
01805       case ICAL_TRIGGER_PROPERTY: {
01806         icaltriggertype trigger = icalproperty_get_trigger(p);
01807         if (icaltime_is_null_time(trigger.time)) {
01808           if (icaldurationtype_is_null_duration(trigger.duration)) {
01809             kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl;
01810           } else {
01811             Duration duration = icaldurationtype_as_int( trigger.duration );
01812             icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER);
01813             if (param && icalparameter_get_related(param) == ICAL_RELATED_END)
01814               ialarm->setEndOffset(duration);
01815             else
01816               ialarm->setStartOffset(duration);
01817           }
01818         } else {
01819           ialarm->setTime(readICalDateTime(p, trigger.time));
01820         }
01821         break;
01822       }
01823       case ICAL_DURATION_PROPERTY: {
01824         icaldurationtype duration = icalproperty_get_duration(p);
01825         ialarm->setSnoozeTime( readICalDuration( duration ) );
01826         break;
01827       }
01828       case ICAL_REPEAT_PROPERTY:
01829         ialarm->setRepeatCount(icalproperty_get_repeat(p));
01830         break;
01831 
01832       // Only in DISPLAY and EMAIL and PROCEDURE alarms
01833       case ICAL_DESCRIPTION_PROPERTY: {
01834         TQString description = TQString::fromUtf8(icalproperty_get_description(p));
01835         switch ( action ) {
01836           case ICAL_ACTION_DISPLAY:
01837             ialarm->setText( description );
01838             break;
01839           case ICAL_ACTION_PROCEDURE:
01840             ialarm->setProgramArguments( description );
01841             break;
01842           case ICAL_ACTION_EMAIL:
01843             ialarm->setMailText( description );
01844             break;
01845           default:
01846             break;
01847         }
01848         break;
01849       }
01850       // Only in EMAIL alarm
01851       case ICAL_SUMMARY_PROPERTY:
01852         ialarm->setMailSubject(TQString::fromUtf8(icalproperty_get_summary(p)));
01853         break;
01854 
01855       // Only in EMAIL alarm
01856       case ICAL_ATTENDEE_PROPERTY: {
01857         TQString email = TQString::fromUtf8(icalproperty_get_attendee(p));
01858         if ( email.startsWith("mailto:", false ) ) {
01859           email = email.mid( 7 );
01860         }
01861         TQString name;
01862         icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER);
01863         if (param) {
01864           name = TQString::fromUtf8(icalparameter_get_cn(param));
01865         }
01866         ialarm->addMailAddress(Person(name, email));
01867         break;
01868       }
01869       // Only in AUDIO and EMAIL and PROCEDURE alarms
01870       case ICAL_ATTACH_PROPERTY: {
01871         Attachment *attach = readAttachment( p );
01872         if ( attach && attach->isUri() ) {
01873           switch ( action ) {
01874             case ICAL_ACTION_AUDIO:
01875               ialarm->setAudioFile( attach->uri() );
01876               break;
01877             case ICAL_ACTION_PROCEDURE:
01878               ialarm->setProgramFile( attach->uri() );
01879               break;
01880             case ICAL_ACTION_EMAIL:
01881               ialarm->addMailAttachment( attach->uri() );
01882               break;
01883             default:
01884               break;
01885           }
01886         } else {
01887           kdDebug() << "Alarm attachments currently only support URIs, but "
01888                        "no binary data" << endl;
01889         }
01890         delete attach;
01891         break;
01892       }
01893       default:
01894         break;
01895     }
01896 
01897     p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY);
01898   }
01899 
01900   // custom properties
01901   readCustomProperties(alarm, ialarm);
01902 
01903   // TODO: check for consistency of alarm properties
01904 }
01905 
01906 icaldatetimeperiodtype ICalFormatImpl::writeICalDatePeriod( const TQDate &date )
01907 {
01908   icaldatetimeperiodtype t;
01909   t.time = writeICalDate( date );
01910   t.period = icalperiodtype_null_period();
01911   return t;
01912 }
01913 
01914 icaldatetimeperiodtype ICalFormatImpl::writeICalDateTimePeriod( const TQDateTime &date )
01915 {
01916   icaldatetimeperiodtype t;
01917   t.time = writeICalDateTime( date );
01918   t.period = icalperiodtype_null_period();
01919   return t;
01920 }
01921 
01922 icaltimetype ICalFormatImpl::writeICalDate(const TQDate &date)
01923 {
01924   icaltimetype t = icaltime_null_time();
01925 
01926   t.year = date.year();
01927   t.month = date.month();
01928   t.day = date.day();
01929 
01930   t.hour = 0;
01931   t.minute = 0;
01932   t.second = 0;
01933 
01934   t.is_date = 1;
01935 
01936   t.is_utc = 0;
01937 
01938   t.zone = 0;
01939 
01940   return t;
01941 }
01942 
01943 icaltimetype ICalFormatImpl::writeICalDateTime(const TQDateTime &datetime)
01944 {
01945   icaltimetype t = icaltime_null_time();
01946 
01947   t.year = datetime.date().year();
01948   t.month = datetime.date().month();
01949   t.day = datetime.date().day();
01950 
01951   t.hour = datetime.time().hour();
01952   t.minute = datetime.time().minute();
01953   t.second = datetime.time().second();
01954 
01955   t.is_date = 0;
01956   t.zone = icaltimezone_get_builtin_timezone ( mParent->timeZoneId().latin1() );
01957   t.is_utc = 0;
01958 
01959  // _dumpIcaltime( t );
01960   /* The TQDateTime we get passed in is to be considered in the timezone of
01961    * the current calendar (mParent's), or, if there is none, to be floating.
01962    * In the later case store a floating time, in the former normalize to utc. */
01963   if (mParent->timeZoneId().isEmpty())
01964     t = icaltime_convert_to_zone( t, 0 ); //make floating timezone
01965   else {
01966     icaltimezone* tz = icaltimezone_get_builtin_timezone ( mParent->timeZoneId().latin1() );
01967     icaltimezone* utc = icaltimezone_get_utc_timezone();
01968     if ( tz != utc ) {
01969       t.zone = tz;
01970       t = icaltime_convert_to_zone( t, utc );
01971     } else {
01972       t.is_utc = 1;
01973       t.zone = utc;
01974     }
01975   }
01976 //  _dumpIcaltime( t );
01977 
01978   return t;
01979 }
01980 
01981 TQDateTime ICalFormatImpl::readICalDateTime( icalproperty *p, icaltimetype& t, icaltimezone* tz )
01982 {
01983 //   kdDebug(5800) << "ICalFormatImpl::readICalDateTime()" << endl;
01984   if ( tz && t.is_utc == 0 ) { // Only use the TZ if time is not UTC.
01985     // FIXME: We'll need to make sure to apply the appropriate TZ, not just
01986     //        the first one found.
01987     t.is_utc = (tz == icaltimezone_get_utc_timezone())?1:0;
01988     if (t.is_utc == 0) {
01989         icalparameter *param = p ? icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER) : 0;
01990         const char *tzid = param ? icalparameter_get_tzid(param) : 0;
01991         if ( !tzid )
01992             t.zone = tz;
01993         else {
01994             icaltimezone* icaltz;
01995             // Try to match the ID with the libical time zone's location property
01996             icaltz = icaltimezone_get_builtin_timezone( tzid );
01997             if ( icaltz ) {
01998 //              kdDebug(5800) << "ICalFormatImpl::readICalDateTime(): time zone '" << tzid << "' read from libical database" << endl;
01999             }
02000             t.zone = icaltz;
02001         }
02002     }
02003   } else {
02004     t.zone = icaltimezone_get_utc_timezone();
02005   }
02006   //_dumpIcaltime( t );
02007 
02008   // Convert to view time
02009   if ( !mParent->timeZoneId().isEmpty() && t.zone ) {
02010 //    kdDebug(5800) << "--- Converting time from: " << icaltimezone_get_tzid( const_cast<icaltimezone*>( t.zone ) ) << " (" << ICalDate2TQDate(t) << ")." << endl;
02011     icaltimezone* viewTimeZone = icaltimezone_get_builtin_timezone ( mParent->timeZoneId().latin1() );
02012     icaltimezone_convert_time(  &t, const_cast<icaltimezone*>(t.zone), viewTimeZone );
02013 //    kdDebug(5800) << "--- Converted to zone " << mParent->timeZoneId() << " (" << ICalDate2TQDate(t) << ")." << endl;
02014   }
02015 
02016   return ICalDate2TQDate(t);
02017 }
02018 
02019 TQDate ICalFormatImpl::readICalDate(icaltimetype t)
02020 {
02021   return ICalDate2TQDate(t).date();
02022 }
02023 
02024 icaldurationtype ICalFormatImpl::writeICalDuration(int seconds)
02025 {
02026   // should be able to use icaldurationtype_from_int(), except we know
02027   // that some older tools do not properly support weeks. So we never
02028   // set a week duration, only days
02029 
02030   icaldurationtype d;
02031 
02032   d.is_neg  = (seconds<0)?1:0;
02033   if (seconds<0) seconds = -seconds;
02034 
02035   d.weeks    = 0;
02036   d.days     = seconds / gSecondsPerDay;
02037   seconds   %= gSecondsPerDay;
02038   d.hours    = seconds / gSecondsPerHour;
02039   seconds   %= gSecondsPerHour;
02040   d.minutes  = seconds / gSecondsPerMinute;
02041   seconds   %= gSecondsPerMinute;
02042   d.seconds  = seconds;
02043 
02044   return d;
02045 }
02046 
02047 int ICalFormatImpl::readICalDuration(icaldurationtype d)
02048 {
02049   int result = 0;
02050 
02051   result += d.weeks   * gSecondsPerWeek;
02052   result += d.days    * gSecondsPerDay;
02053   result += d.hours   * gSecondsPerHour;
02054   result += d.minutes * gSecondsPerMinute;
02055   result += d.seconds;
02056 
02057   if (d.is_neg) result *= -1;
02058 
02059   return result;
02060 }
02061 
02062 icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal)
02063 {
02064   icalcomponent *calendar;
02065 
02066   // Root component
02067   calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
02068 
02069   icalproperty *p;
02070 
02071   // Product Identifier
02072   p = icalproperty_new_prodid(CalFormat::productId().utf8());
02073   icalcomponent_add_property(calendar,p);
02074 
02075   // TODO: Add time zone
02076 
02077   // iCalendar version (2.0)
02078   p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION));
02079   icalcomponent_add_property(calendar,p);
02080 
02081   // Custom properties
02082   if( cal != 0 )
02083     writeCustomProperties(calendar, cal);
02084 
02085   return calendar;
02086 }
02087 
02088 
02089 
02090 // take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
02091 // and break it down from its tree-like format into the dictionary format
02092 // that is used internally in the ICalFormatImpl.
02093 bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar )
02094 {
02095   // this function will populate the caldict dictionary and other event
02096   // lists. It turns vevents into Events and then inserts them.
02097 
02098     if (!calendar) return false;
02099 
02100 // TODO: check for METHOD
02101 
02102   icalproperty *p;
02103 
02104   p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY);
02105   if (!p) {
02106     kdDebug(5800) << "No PRODID property found" << endl;
02107     mLoadedProductId = "";
02108   } else {
02109     mLoadedProductId = TQString::fromUtf8(icalproperty_get_prodid(p));
02110 //    kdDebug(5800) << "VCALENDAR prodid: '" << mLoadedProductId << "'" << endl;
02111 
02112     delete mCompat;
02113     mCompat = CompatFactory::createCompat( mLoadedProductId );
02114   }
02115 
02116   p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY);
02117   if (!p) {
02118     kdDebug(5800) << "No VERSION property found" << endl;
02119     mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
02120     return false;
02121   } else {
02122     const char *version = icalproperty_get_version(p);
02123     if ( !version ) {
02124       kdDebug(5800) << "No VERSION property found" << endl;
02125       mParent->setException( new ErrorFormat(
02126                                ErrorFormat::CalVersionUnknown,
02127                                i18n( "No VERSION property found" ) ) );
02128       return false;
02129     }
02130 
02131 //    kdDebug(5800) << "VCALENDAR version: '" << version << "'" << endl;
02132 
02133     if (strcmp(version,"1.0") == 0) {
02134       kdDebug(5800) << "Expected iCalendar, got vCalendar" << endl;
02135       mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1,
02136                             i18n("Expected iCalendar format")));
02137       return false;
02138     } else if (strcmp(version,"2.0") != 0) {
02139       kdDebug(5800) << "Expected iCalendar, got unknown format" << endl;
02140       mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
02141       return false;
02142     }
02143   }
02144 
02145   // custom properties
02146   readCustomProperties(calendar, cal);
02147 
02148 // TODO: set time zone
02149 
02150   // read a VTIMEZONE if there is one
02151   icalcomponent *ctz =
02152     icalcomponent_get_first_component( calendar, ICAL_VTIMEZONE_COMPONENT );
02153 
02154   // Store all events with a relatedTo property in a list for post-processing
02155   mEventsRelate.clear();
02156   mTodosRelate.clear();
02157   // TODO: make sure that only actually added events go to this lists.
02158 
02159   icalcomponent *c;
02160 
02161   // Iterate through all todos
02162   c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT);
02163   while (c) {
02164 //    kdDebug(5800) << "----Todo found" << endl;
02165     Todo *todo = readTodo(c);
02166     if (todo) {
02167       if (todo->hasRecurrenceID()) {
02168         TQString originalUid = todo->uid();
02169         todo->setUid(originalUid + TQString("-recur-%1").arg(todo->recurrenceID().toTime_t()));
02170         if (!cal->todo(todo->uid())) {
02171           if ( !cal->addTodo( todo ) ) {
02172             cal->endBatchAdding();
02173             // If the user pressed cancel, return true, it's not an error.
02174             return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
02175           }
02176           if (!cal->event(originalUid)) {
02177             printf("FIXME! [WARNING] Parent for child event does not yet exist!\n");
02178           }
02179           else {
02180             // Add this todo to its parent
02181             cal->todo(originalUid)->addChildIncidence(todo->uid());
02182             // And the parent to the child
02183             todo->addChildIncidence(cal->todo(originalUid)->uid());
02184           }
02185         }
02186       }
02187       else {
02188         if (!cal->todo(todo->uid())) {
02189           if ( !cal->addTodo( todo ) ) {
02190             cal->endBatchAdding();
02191             // If the user pressed cancel, return true, it's not an error.
02192             return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
02193           }
02194         } else {
02195           delete todo;
02196           mTodosRelate.remove( todo );
02197         }
02198       }
02199     }
02200     c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT);
02201   }
02202 
02203   // Iterate through all events
02204   c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT);
02205   while (c) {
02206 //    kdDebug(5800) << "----Event found" << endl;
02207     Event *event = readEvent(c, ctz);
02208     if (event) {
02209       if (event->hasRecurrenceID()) {
02210         TQString originalUid = event->uid();
02211         event->setUid(originalUid + TQString("-recur-%1").arg(event->recurrenceID().toTime_t()));
02212         if (!cal->event(event->uid())) {
02213           cal->addEvent(event);
02214           if (!cal->event(originalUid)) {
02215             printf("FIXME! [WARNING] Parent for child event does not yet exist!\n");
02216           }
02217           else {
02218             // Add this event to its parent
02219             cal->event(originalUid)->addChildIncidence(event->uid());
02220             // And the parent to the child
02221             event->addChildIncidence(cal->event(originalUid)->uid());
02222           }
02223         }
02224       }
02225       else {
02226         if (!cal->event(event->uid())) {
02227         if ( !cal->addEvent( event ) ) {
02228           cal->endBatchAdding();
02229           // If the user pressed cancel, return true, it's not an error.
02230           return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
02231         }
02232         } else {
02233           delete event;
02234           mEventsRelate.remove( event );
02235         }
02236       }
02237     }
02238     c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT);
02239   }
02240 
02241   // Iterate through all journals
02242   c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT);
02243   while (c) {
02244 //    kdDebug(5800) << "----Journal found" << endl;
02245     Journal *journal = readJournal(c);
02246     if (journal) {
02247       if (journal->hasRecurrenceID()) {
02248         TQString originalUid = journal->uid();
02249         journal->setUid(originalUid + TQString("-recur-%1").arg(journal->recurrenceID().toTime_t()));
02250         if (!cal->journal(journal->uid())) {
02251           cal->addJournal(journal);
02252           if (!cal->event(originalUid)) {
02253             printf("FIXME! [WARNING] Parent for child event does not yet exist!\n");
02254           }
02255           else {
02256             // Add this journal to its parent
02257             cal->journal(originalUid)->addChildIncidence(journal->uid());
02258             // And the parent to the child
02259             journal->addChildIncidence(cal->journal(originalUid)->uid());
02260           }
02261         }
02262       }
02263       else {
02264         if (!cal->journal(journal->uid())) {
02265         if ( !cal->addJournal(journal) ) {
02266           cal->endBatchAdding();
02267           // If the user pressed cancel, return true, it's not an error.
02268           return cal->exception() && cal->exception()->errorCode() == ErrorFormat::UserCancel;
02269         }
02270         } else {
02271           delete journal;
02272         }
02273       }
02274     }
02275     c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT);
02276   }
02277 
02278   cal->endBatchAdding();
02279 
02280   // Post-Process list of events with relations, put Event objects in relation
02281   Event::List::ConstIterator eIt;
02282   for ( eIt = mEventsRelate.begin(); eIt != mEventsRelate.end(); ++eIt ) {
02283     (*eIt)->setRelatedTo( cal->incidence( (*eIt)->relatedToUid() ) );
02284   }
02285   Todo::List::ConstIterator tIt;
02286   for ( tIt = mTodosRelate.begin(); tIt != mTodosRelate.end(); ++tIt ) {
02287     (*tIt)->setRelatedTo( cal->incidence( (*tIt)->relatedToUid() ) );
02288    }
02289 
02290   return true;
02291 }
02292 
02293 TQString ICalFormatImpl::extractErrorProperty(icalcomponent *c)
02294 {
02295 //  kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: "
02296 //            << icalcomponent_as_ical_string(c) << endl;
02297 
02298   TQString errorMessage;
02299 
02300   icalproperty *error;
02301   error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY);
02302   while(error) {
02303     errorMessage += icalproperty_get_xlicerror(error);
02304     errorMessage += "\n";
02305     error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY);
02306   }
02307 
02308 //  kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl;
02309 
02310   return errorMessage;
02311 }
02312 
02313 void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r)
02314 {
02315   int i;
02316 
02317   kdDebug(5800) << " Freq: " << r.freq << endl;
02318   kdDebug(5800) << " Until: " << icaltime_as_ical_string(r.until) << endl;
02319   kdDebug(5800) << " Count: " << r.count << endl;
02320   if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
02321     int index = 0;
02322     TQString out = " By Day: ";
02323     while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
02324       out.append(TQString::number(i) + " ");
02325     }
02326     kdDebug(5800) << out << endl;
02327   }
02328   if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
02329     int index = 0;
02330     TQString out = " By Month Day: ";
02331     while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
02332       out.append(TQString::number(i) + " ");
02333     }
02334     kdDebug(5800) << out << endl;
02335   }
02336   if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
02337     int index = 0;
02338     TQString out = " By Year Day: ";
02339     while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
02340       out.append(TQString::number(i) + " ");
02341     }
02342     kdDebug(5800) << out << endl;
02343   }
02344   if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
02345     int index = 0;
02346     TQString out = " By Month: ";
02347     while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
02348       out.append(TQString::number(i) + " ");
02349     }
02350     kdDebug(5800) << out << endl;
02351   }
02352   if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
02353     int index = 0;
02354     TQString out = " By Set Pos: ";
02355     while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
02356       kdDebug(5800) << "========= " << i << endl;
02357       out.append(TQString::number(i) + " ");
02358     }
02359     kdDebug(5800) << out << endl;
02360   }
02361 }
02362 
02363 icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence,
02364                                                    Scheduler::Method method)
02365 {
02366   icalcomponent *message = createCalendarComponent();
02367 
02368   icalproperty_method icalmethod = ICAL_METHOD_NONE;
02369 
02370   switch (method) {
02371     case Scheduler::Publish:
02372       icalmethod = ICAL_METHOD_PUBLISH;
02373       break;
02374     case Scheduler::Request:
02375       icalmethod = ICAL_METHOD_REQUEST;
02376       break;
02377     case Scheduler::Refresh:
02378       icalmethod = ICAL_METHOD_REFRESH;
02379       break;
02380     case Scheduler::Cancel:
02381       icalmethod = ICAL_METHOD_CANCEL;
02382       break;
02383     case Scheduler::Add:
02384       icalmethod = ICAL_METHOD_ADD;
02385       break;
02386     case Scheduler::Reply:
02387       icalmethod = ICAL_METHOD_REPLY;
02388       break;
02389     case Scheduler::Counter:
02390       icalmethod = ICAL_METHOD_COUNTER;
02391       break;
02392     case Scheduler::Declinecounter:
02393       icalmethod = ICAL_METHOD_DECLINECOUNTER;
02394       break;
02395     default:
02396       kdDebug(5800) << "ICalFormat::createScheduleMessage(): Unknow method" << endl;
02397       return message;
02398   }
02399 
02400   icalcomponent_add_property(message,icalproperty_new_method(icalmethod));
02401 
02402   icalcomponent *inc = writeIncidence( incidence, method );
02403   /*
02404    * RFC 2446 states in section 3.4.3 ( REPLY to a VTODO ), that
02405    * a REQUEST-STATUS property has to be present. For the other two, event and
02406    * free busy, it can be there, but is optional. Until we do more
02407    * fine grained handling, assume all is well. Note that this is the
02408    * status of the _request_, not the attendee. Just to avoid confusion.
02409    * - till
02410    */
02411   if ( icalmethod == ICAL_METHOD_REPLY ) {
02412     struct icalreqstattype rst;
02413     rst.code = ICAL_2_0_SUCCESS_STATUS;
02414     rst.desc = 0;
02415     rst.debug = 0;
02416     icalcomponent_add_property( inc, icalproperty_new_requeststatus( rst ) );
02417   }
02418   icalcomponent_add_component( message, inc );
02419 
02420   return message;
02421 }