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