• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KCal Library

icalformat_p.cpp

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

KCal Library

Skip menu "KCal Library"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal