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