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