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