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