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