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