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