libkcal Library API Documentation

icalformatimpl.cpp

00001 /* 00002 This file is part of libkcal. 00003 00004 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 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 // Now do the ical reading. 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 // If this phase was not valid at the given time, give up. 00136 if (tmp > t) { 00137 kdDebug(5800) << "TimezonePhase::nearestStart(): Phase not valid" << endl; 00138 return QDateTime(); 00139 } 00140 00141 // The Recurrance class's getPreviousDateTime() logic was not designed for 00142 // start times which are not aligned with a reference time, but a little 00143 // magic is sufficient to work around that... 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 // Hide the missnamed "is_stdandard" variable in the base class. 00159 int mIsStandard; 00160 00161 // Supplement the "rrule" in the base class. 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 // The phases list is defined to be terminated by a phase with a 00181 // null name. 00182 phases = (icaltimezonephase *)malloc(sizeof(*phases)); 00183 phases[0].tzname = (const char *)0; 00184 mPhases.setAutoDelete( true ); 00185 00186 // Now do the ical reading. 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 // The timezone id is basically a unique string which is used to 00194 // identify this timezone. Note that if it begins with a "/", then it 00195 // is suppsed to have some externally specified meaning, but we are 00196 // just after its unique value. 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 // Iterate through all timezones before we do anything else. That way, the 00218 // information needed to interpret times in actually usefulobject is 00219 // available below. 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 // Main loop. Find the phase with the latest start date before t. 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 // Phases we have seen. 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 // due date 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 // start time 00372 if ( todo->hasStartDate() || todo->doesRecur() ) { 00373 icaltimetype start; 00374 if (todo->doesFloat()) { 00375 // kdDebug(5800) << " Incidence " << todo->summary() << " floats." << endl; 00376 start = writeICalDate(todo->dtStart(true).date()); 00377 } else { 00378 // kdDebug(5800) << " incidence " << todo->summary() << " has time." << endl; 00379 start = writeICalDateTime(todo->dtStart(true)); 00380 } 00381 icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start)); 00382 } 00383 00384 // completion date 00385 if (todo->isCompleted()) { 00386 if (!todo->hasCompletedDate()) { 00387 // If todo was created by KOrganizer <2.2 it has no correct completion 00388 // date. Set it to now. 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 // start time 00421 icaltimetype start; 00422 if (event->doesFloat()) { 00423 // kdDebug(5800) << " Incidence " << event->summary() << " floats." << endl; 00424 start = writeICalDate(event->dtStart().date()); 00425 } else { 00426 // kdDebug(5800) << " incidence " << event->summary() << " has time." << endl; 00427 start = writeICalDateTime(event->dtStart()); 00428 } 00429 icalcomponent_add_property(vevent,icalproperty_new_dtstart(start)); 00430 00431 if (event->hasEndDate()) { 00432 // end time 00433 icaltimetype end; 00434 if (event->doesFloat()) { 00435 // kdDebug(5800) << " Event " << event->summary() << " floats." << endl; 00436 // +1 day because end date is non-inclusive. 00437 end = writeICalDate( event->dtEnd().date().addDays( 1 ) ); 00438 } else { 00439 // kdDebug(5800) << " Event " << event->summary() << " has time." << endl; 00440 end = writeICalDateTime(event->dtEnd()); 00441 } 00442 icalcomponent_add_property(vevent,icalproperty_new_dtend(end)); 00443 } 00444 00445 // TODO: resources 00446 #if 0 00447 // resources 00448 tmpStrList = anEvent->resources(); 00449 tmpStr = tmpStrList.join(";"); 00450 if (!tmpStr.isEmpty()) 00451 addPropValue(vevent, VCResourcesProp, tmpStr.utf8()); 00452 00453 #endif 00454 00455 // Transparency 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 //Loops through all the periods in the freebusy object 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 // start time 00512 if (journal->dtStart().isValid()) { 00513 icaltimetype start; 00514 if (journal->doesFloat()) { 00515 // kdDebug(5800) << " Incidence " << event->summary() << " floats." << endl; 00516 start = writeICalDate(journal->dtStart().date()); 00517 } else { 00518 // kdDebug(5800) << " incidence " << event->summary() << " has time." << endl; 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 // pilot sync stuff 00530 // TODO: move this application-specific code to kpilot 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 // creation date 00539 icalcomponent_add_property(parent,icalproperty_new_created( 00540 writeICalDateTime(incidence->created()))); 00541 00542 // unique id 00543 icalcomponent_add_property(parent,icalproperty_new_uid( 00544 incidence->uid().utf8())); 00545 00546 // revision 00547 icalcomponent_add_property(parent,icalproperty_new_sequence( 00548 incidence->revision())); 00549 00550 // last modification date 00551 icalcomponent_add_property(parent,icalproperty_new_lastmodified( 00552 writeICalDateTime(incidence->lastModified()))); 00553 00554 // description 00555 if (!incidence->description().isEmpty()) { 00556 icalcomponent_add_property(parent,icalproperty_new_description( 00557 incidence->description().utf8())); 00558 } 00559 00560 // summary 00561 if (!incidence->summary().isEmpty()) { 00562 icalcomponent_add_property(parent,icalproperty_new_summary( 00563 incidence->summary().utf8())); 00564 } 00565 00566 // location 00567 if (!incidence->location().isEmpty()) { 00568 icalcomponent_add_property(parent,icalproperty_new_location( 00569 incidence->location().utf8())); 00570 } 00571 00572 // status 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 // secrecy 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 // priority 00613 icalcomponent_add_property(parent,icalproperty_new_priority( 00614 incidence->priority())); 00615 00616 // categories 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 // TODO: Ensure correct concatenation of categories properties. 00623 00624 /* 00625 // categories 00626 tmpStrList = incidence->getCategories(); 00627 tmpStr = ""; 00628 QString catStr; 00629 for ( QStringList::Iterator it = tmpStrList.begin(); 00630 it != tmpStrList.end(); 00631 ++it ) { 00632 catStr = *it; 00633 if (catStr[0] == ' ') 00634 tmpStr += catStr.mid(1); 00635 else 00636 tmpStr += catStr; 00637 // this must be a ';' character as the vCalendar specification requires! 00638 // vcc.y has been hacked to translate the ';' to a ',' when the vcal is 00639 // read in. 00640 tmpStr += ";"; 00641 } 00642 if (!tmpStr.isEmpty()) { 00643 tmpStr.truncate(tmpStr.length()-1); 00644 icalcomponent_add_property(parent,icalproperty_new_categories( 00645 writeText(incidence->getCategories().join(";")))); 00646 } 00647 */ 00648 00649 // related event 00650 if (incidence->relatedTo()) { 00651 icalcomponent_add_property(parent,icalproperty_new_relatedto( 00652 incidence->relatedTo()->uid().utf8())); 00653 } 00654 00655 // recurrence rule stuff 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 // recurrence exception dates and date/times 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 // attachments 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 // alarms 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 // duration 00693 00694 // turned off as it always is set to PTS0 (and must not occur together with DTEND 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 // organizer stuff 00710 icalcomponent_add_property( parent, icalproperty_new_organizer( 00711 ( "MAILTO:" + incidenceBase->organizer() ).utf8() ) ); 00712 00713 // attendees 00714 if ( incidenceBase->attendeeCount() > 0 ) { 00715 Attendee::List::ConstIterator it; 00716 for( it = incidenceBase->attendees().begin(); 00717 it != incidenceBase->attendees().end(); ++it ) { 00718 icalcomponent_add_property( parent, writeAttendee( *it ) ); 00719 } 00720 } 00721 00722 // comments 00723 QStringList comments = incidenceBase->comments(); 00724 for (QStringList::Iterator it=comments.begin(); it!=comments.end(); ++it) { 00725 icalcomponent_add_property(parent, icalproperty_new_comment((*it).utf8())); 00726 } 00727 00728 // custom properties 00729 writeCustomProperties( parent, incidenceBase ); 00730 } 00731 00732 void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties) 00733 { 00734 QMap<QCString, QString> custom = properties->customProperties(); 00735 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { 00736 icalproperty *p = icalproperty_new_x(c.data().utf8()); 00737 icalproperty_set_x_name(p,c.key()); 00738 icalcomponent_add_property(parent,p); 00739 } 00740 } 00741 00742 icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee) 00743 { 00744 icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8()); 00745 00746 if (!attendee->name().isEmpty()) { 00747 icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8())); 00748 } 00749 00750 00751 icalproperty_add_parameter(p,icalparameter_new_rsvp( 00752 attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE )); 00753 00754 icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION; 00755 switch (attendee->status()) { 00756 default: 00757 case Attendee::NeedsAction: 00758 status = ICAL_PARTSTAT_NEEDSACTION; 00759 break; 00760 case Attendee::Accepted: 00761 status = ICAL_PARTSTAT_ACCEPTED; 00762 break; 00763 case Attendee::Declined: 00764 status = ICAL_PARTSTAT_DECLINED; 00765 break; 00766 case Attendee::Tentative: 00767 status = ICAL_PARTSTAT_TENTATIVE; 00768 break; 00769 case Attendee::Delegated: 00770 status = ICAL_PARTSTAT_DELEGATED; 00771 break; 00772 case Attendee::Completed: 00773 status = ICAL_PARTSTAT_COMPLETED; 00774 break; 00775 case Attendee::InProcess: 00776 status = ICAL_PARTSTAT_INPROCESS; 00777 break; 00778 } 00779 icalproperty_add_parameter(p,icalparameter_new_partstat(status)); 00780 00781 icalparameter_role role = ICAL_ROLE_REQPARTICIPANT; 00782 switch (attendee->role()) { 00783 case Attendee::Chair: 00784 role = ICAL_ROLE_CHAIR; 00785 break; 00786 default: 00787 case Attendee::ReqParticipant: 00788 role = ICAL_ROLE_REQPARTICIPANT; 00789 break; 00790 case Attendee::OptParticipant: 00791 role = ICAL_ROLE_OPTPARTICIPANT; 00792 break; 00793 case Attendee::NonParticipant: 00794 role = ICAL_ROLE_NONPARTICIPANT; 00795 break; 00796 } 00797 icalproperty_add_parameter(p,icalparameter_new_role(role)); 00798 00799 if (!attendee->uid().isEmpty()) { 00800 icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8()); 00801 icalparameter_set_xname(icalparameter_uid,"X-UID"); 00802 icalproperty_add_parameter(p,icalparameter_uid); 00803 } 00804 00805 return p; 00806 } 00807 00808 icalproperty *ICalFormatImpl::writeAttachment(Attachment *att) 00809 { 00810 icalattachtype *attach = icalattachtype_new(); 00811 if ( att->isUri() ) 00812 icalattachtype_set_url( attach, att->uri().utf8().data() ); 00813 else 00814 icalattachtype_set_base64( attach, att->data(), 0 ); 00815 00816 icalproperty *p = icalproperty_new_attach( attach ); 00817 icalattachtype_free( attach ); 00818 00819 if ( !att->mimeType().isEmpty() ) { 00820 icalproperty_add_parameter( p, 00821 icalparameter_new_fmttype( att->mimeType().utf8().data() ) ); 00822 } 00823 00824 if ( att->isBinary() ) { 00825 icalproperty_add_parameter( p, 00826 icalparameter_new_value( ICAL_VALUE_BINARY ) ); 00827 icalproperty_add_parameter( p, 00828 icalparameter_new_encoding( ICAL_ENCODING_BASE64 ) ); 00829 } 00830 return p; 00831 } 00832 00833 icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur) 00834 { 00835 // kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl; 00836 00837 icalrecurrencetype r; 00838 00839 icalrecurrencetype_clear(&r); 00840 00841 int index = 0; 00842 int index2 = 0; 00843 00844 QPtrList<Recurrence::rMonthPos> tmpPositions; 00845 QPtrList<int> tmpDays; 00846 int *tmpDay; 00847 Recurrence::rMonthPos *tmpPos; 00848 bool datetime = false; 00849 int day; 00850 int i; 00851 00852 switch(recur->doesRecur()) { 00853 case Recurrence::rMinutely: 00854 r.freq = ICAL_MINUTELY_RECURRENCE; 00855 datetime = true; 00856 break; 00857 case Recurrence::rHourly: 00858 r.freq = ICAL_HOURLY_RECURRENCE; 00859 datetime = true; 00860 break; 00861 case Recurrence::rDaily: 00862 r.freq = ICAL_DAILY_RECURRENCE; 00863 break; 00864 case Recurrence::rWeekly: 00865 r.freq = ICAL_WEEKLY_RECURRENCE; 00866 r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1); 00867 for (i = 0; i < 7; i++) { 00868 if (recur->days().testBit(i)) { 00869 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 00870 r.by_day[index++] = icalrecurrencetype_day_day_of_week(day); 00871 } 00872 } 00873 // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 00874 break; 00875 case Recurrence::rMonthlyPos: 00876 r.freq = ICAL_MONTHLY_RECURRENCE; 00877 00878 tmpPositions = recur->monthPositions(); 00879 for (tmpPos = tmpPositions.first(); 00880 tmpPos; 00881 tmpPos = tmpPositions.next()) { 00882 for (i = 0; i < 7; i++) { 00883 if (tmpPos->rDays.testBit(i)) { 00884 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 00885 day += tmpPos->rPos*8; 00886 if (tmpPos->negative) day = -day; 00887 r.by_day[index++] = day; 00888 } 00889 } 00890 } 00891 // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 00892 break; 00893 case Recurrence::rMonthlyDay: 00894 r.freq = ICAL_MONTHLY_RECURRENCE; 00895 00896 tmpDays = recur->monthDays(); 00897 for (tmpDay = tmpDays.first(); 00898 tmpDay; 00899 tmpDay = tmpDays.next()) { 00900 r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8); 00901 } 00902 // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 00903 break; 00904 case Recurrence::rYearlyMonth: 00905 case Recurrence::rYearlyPos: 00906 r.freq = ICAL_YEARLY_RECURRENCE; 00907 00908 tmpDays = recur->yearNums(); 00909 for (tmpDay = tmpDays.first(); 00910 tmpDay; 00911 tmpDay = tmpDays.next()) { 00912 r.by_month[index++] = *tmpDay; 00913 } 00914 // r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX; 00915 if (recur->doesRecur() == Recurrence::rYearlyPos) { 00916 tmpPositions = recur->monthPositions(); 00917 for (tmpPos = tmpPositions.first(); 00918 tmpPos; 00919 tmpPos = tmpPositions.next()) { 00920 for (i = 0; i < 7; i++) { 00921 if (tmpPos->rDays.testBit(i)) { 00922 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 00923 day += tmpPos->rPos*8; 00924 if (tmpPos->negative) day = -day; 00925 r.by_day[index2++] = day; 00926 } 00927 } 00928 } 00929 // r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX; 00930 } 00931 else { 00932 tmpDays = recur->monthDays(); 00933 for (tmpDay = tmpDays.first(); 00934 tmpDay; 00935 tmpDay = tmpDays.next()) { 00936 r.by_month_day[index2++] = icalrecurrencetype_day_position(*tmpDay*8); 00937 } 00938 // r.by_month_day[index2] = ICAL_RECURRENCE_ARRAY_MAX; 00939 } 00940 break; 00941 case Recurrence::rYearlyDay: 00942 r.freq = ICAL_YEARLY_RECURRENCE; 00943 00944 tmpDays = recur->yearNums(); 00945 for (tmpDay = tmpDays.first(); 00946 tmpDay; 00947 tmpDay = tmpDays.next()) { 00948 r.by_year_day[index++] = *tmpDay; 00949 } 00950 // r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 00951 break; 00952 default: 00953 r.freq = ICAL_NO_RECURRENCE; 00954 kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl; 00955 break; 00956 } 00957 00958 r.interval = recur->frequency(); 00959 00960 if (recur->duration() > 0) { 00961 r.count = recur->duration(); 00962 } else if (recur->duration() == -1) { 00963 r.count = 0; 00964 } else { 00965 if (datetime) 00966 r.until = writeICalDateTime(recur->endDateTime()); 00967 else 00968 r.until = writeICalDate(recur->endDate()); 00969 } 00970 00971 // Debug output 00972 #if 0 00973 const char *str = icalrecurrencetype_as_string(&r); 00974 if (str) { 00975 kdDebug(5800) << " String: " << str << endl; 00976 } else { 00977 kdDebug(5800) << " No String" << endl; 00978 } 00979 #endif 00980 00981 return icalproperty_new_rrule(r); 00982 } 00983 00984 icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm) 00985 { 00986 icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT); 00987 00988 icalproperty_action action; 00989 icalattachtype *attach = 0; 00990 00991 switch (alarm->type()) { 00992 case Alarm::Procedure: 00993 action = ICAL_ACTION_PROCEDURE; 00994 attach = icalattachtype_new(); 00995 icalattachtype_set_url(attach,QFile::encodeName(alarm->programFile()).data()); 00996 icalcomponent_add_property(a,icalproperty_new_attach(attach)); 00997 icalattachtype_free(attach); 00998 if (!alarm->programArguments().isEmpty()) { 00999 icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8())); 01000 } 01001 break; 01002 case Alarm::Audio: 01003 action = ICAL_ACTION_AUDIO; 01004 if (!alarm->audioFile().isEmpty()) { 01005 attach = icalattachtype_new(); 01006 icalattachtype_set_url(attach,QFile::encodeName( alarm->audioFile() ).data()); 01007 icalcomponent_add_property(a,icalproperty_new_attach(attach)); 01008 icalattachtype_free(attach); 01009 } 01010 break; 01011 case Alarm::Email: { 01012 action = ICAL_ACTION_EMAIL; 01013 QValueList<Person> addresses = alarm->mailAddresses(); 01014 for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) { 01015 icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8()); 01016 if (!(*ad).name().isEmpty()) { 01017 icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8())); 01018 } 01019 icalcomponent_add_property(a,p); 01020 } 01021 icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8())); 01022 icalcomponent_add_property(a,icalproperty_new_description(alarm->mailText().utf8())); 01023 QStringList attachments = alarm->mailAttachments(); 01024 if (attachments.count() > 0) { 01025 for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) { 01026 attach = icalattachtype_new(); 01027 icalattachtype_set_url(attach,QFile::encodeName( *at ).data()); 01028 icalcomponent_add_property(a,icalproperty_new_attach(attach)); 01029 icalattachtype_free(attach); 01030 } 01031 } 01032 break; 01033 } 01034 case Alarm::Display: 01035 action = ICAL_ACTION_DISPLAY; 01036 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); 01037 break; 01038 case Alarm::Invalid: 01039 default: 01040 kdDebug(5800) << "Unknown type of alarm" << endl; 01041 action = ICAL_ACTION_NONE; 01042 break; 01043 } 01044 icalcomponent_add_property(a,icalproperty_new_action(action)); 01045 01046 // Trigger time 01047 icaltriggertype trigger; 01048 if ( alarm->hasTime() ) { 01049 trigger.time = writeICalDateTime(alarm->time()); 01050 trigger.duration = icaldurationtype_null_duration(); 01051 } else { 01052 trigger.time = icaltime_null_time(); 01053 Duration offset; 01054 if ( alarm->hasStartOffset() ) 01055 offset = alarm->startOffset(); 01056 else 01057 offset = alarm->endOffset(); 01058 trigger.duration = icaldurationtype_from_int( offset.asSeconds() ); 01059 } 01060 icalproperty *p = icalproperty_new_trigger(trigger); 01061 if ( alarm->hasEndOffset() ) 01062 icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END)); 01063 icalcomponent_add_property(a,p); 01064 01065 // Repeat count and duration 01066 if (alarm->repeatCount()) { 01067 icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount())); 01068 icalcomponent_add_property(a,icalproperty_new_duration( 01069 icaldurationtype_from_int(alarm->snoozeTime()*60))); 01070 } 01071 01072 // Custom properties 01073 QMap<QCString, QString> custom = alarm->customProperties(); 01074 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { 01075 icalproperty *p = icalproperty_new_x(c.data().utf8()); 01076 icalproperty_set_x_name(p,c.key()); 01077 icalcomponent_add_property(a,p); 01078 } 01079 01080 return a; 01081 } 01082 01083 // Read a timezone and store it in a list where it can be accessed as needed 01084 // by the other readXXX() routines. Note that no writeTimezone is needed 01085 // because we always store in UTC. 01086 void ICalFormatImpl::readTimezone(icalcomponent *vtimezone) 01087 { 01088 Timezone *timezone = new Timezone(this, vtimezone); 01089 01090 mTimezones.insert(timezone->id(), timezone); 01091 } 01092 01093 Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo) 01094 { 01095 Todo *todo = new Todo; 01096 01097 readIncidence(vtodo,todo); 01098 01099 icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY); 01100 01101 // int intvalue; 01102 icaltimetype icaltime; 01103 01104 QStringList categories; 01105 01106 while (p) { 01107 icalproperty_kind kind = icalproperty_isa(p); 01108 switch (kind) { 01109 01110 case ICAL_DUE_PROPERTY: // due date 01111 icaltime = icalproperty_get_due(p); 01112 readTzidParameter(p,icaltime); 01113 if (icaltime.is_date) { 01114 todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0)),true); 01115 todo->setFloats(true); 01116 01117 } else { 01118 todo->setDtDue(readICalDateTime(icaltime),true); 01119 todo->setFloats(false); 01120 } 01121 todo->setHasDueDate(true); 01122 break; 01123 01124 case ICAL_COMPLETED_PROPERTY: // completion date 01125 icaltime = icalproperty_get_completed(p); 01126 readTzidParameter(p,icaltime); 01127 todo->setCompleted(readICalDateTime(icaltime)); 01128 break; 01129 01130 case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed 01131 todo->setPercentComplete(icalproperty_get_percentcomplete(p)); 01132 break; 01133 01134 case ICAL_RELATEDTO_PROPERTY: // related todo (parent) 01135 todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); 01136 mTodosRelate.append(todo); 01137 break; 01138 01139 case ICAL_DTSTART_PROPERTY: { 01140 // Flag that todo has start date. Value is read in by readIncidence(). 01141 if ( todo->comments().grep("NoStartDate").count() ) 01142 todo->setHasStartDate( false ); 01143 else 01144 todo->setHasStartDate( true ); 01145 break; 01146 } 01147 01148 case ICAL_RECURRENCEID_PROPERTY: 01149 icaltime = icalproperty_get_recurrenceid(p); 01150 readTzidParameter(p,icaltime); 01151 todo->setDtRecurrence( readICalDateTime(icaltime) ); 01152 break; 01153 01154 default: 01155 // kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind 01156 // << endl; 01157 break; 01158 } 01159 01160 p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY); 01161 } 01162 01163 mCompat->fixEmptySummary( todo ); 01164 01165 return todo; 01166 } 01167 01168 Event *ICalFormatImpl::readEvent(icalcomponent *vevent) 01169 { 01170 Event *event = new Event; 01171 event->setFloats(false); 01172 01173 readIncidence(vevent,event); 01174 01175 icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY); 01176 01177 // int intvalue; 01178 icaltimetype icaltime; 01179 01180 QStringList categories; 01181 QString transparency; 01182 01183 while (p) { 01184 icalproperty_kind kind = icalproperty_isa(p); 01185 switch (kind) { 01186 01187 case ICAL_DTEND_PROPERTY: // start date and time 01188 icaltime = icalproperty_get_dtend(p); 01189 readTzidParameter(p,icaltime); 01190 if (icaltime.is_date) { 01191 event->setFloats( true ); 01192 // End date is non-inclusive 01193 QDate endDate = readICalDate( icaltime ).addDays( -1 ); 01194 mCompat->fixFloatingEnd( endDate ); 01195 if ( endDate < event->dtStart().date() ) { 01196 endDate = event->dtStart().date(); 01197 } 01198 event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) ); 01199 } else { 01200 event->setDtEnd(readICalDateTime(icaltime)); 01201 } 01202 break; 01203 01204 // TODO: 01205 // at this point, there should be at least a start or end time. 01206 // fix up for events that take up no time but have a time associated 01207 #if 0 01208 if (!(vo = isAPropertyOf(vevent, VCDTstartProp))) 01209 anEvent->setDtStart(anEvent->dtEnd()); 01210 if (!(vo = isAPropertyOf(vevent, VCDTendProp))) 01211 anEvent->setDtEnd(anEvent->dtStart()); 01212 #endif 01213 01214 #if 0 01215 // secrecy 01216 if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) { 01217 anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo))); 01218 deleteStr(s); 01219 } 01220 else 01221 anEvent->setSecrecy("PUBLIC"); 01222 01223 // attachments 01224 tmpStrList.clear(); 01225 initPropIterator(&voi, vevent); 01226 while (moreIteration(&voi)) { 01227 vo = nextVObject(&voi); 01228 if (strcmp(vObjectName(vo), VCAttachProp) == 0) { 01229 tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo))); 01230 deleteStr(s); 01231 } 01232 } 01233 anEvent->setAttachments(tmpStrList); 01234 01235 // resources 01236 if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) { 01237 QString resources = (s = fakeCString(vObjectUStringZValue(vo))); 01238 deleteStr(s); 01239 tmpStrList.clear(); 01240 index1 = 0; 01241 index2 = 0; 01242 QString resource; 01243 while ((index2 = resources.find(';', index1)) != -1) { 01244 resource = resources.mid(index1, (index2 - index1)); 01245 tmpStrList.append(resource); 01246 index1 = index2; 01247 } 01248 anEvent->setResources(tmpStrList); 01249 } 01250 #endif 01251 01252 case ICAL_RELATEDTO_PROPERTY: // related event (parent) 01253 event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); 01254 mEventsRelate.append(event); 01255 break; 01256 01257 01258 case ICAL_TRANSP_PROPERTY: // Transparency 01259 transparency = QString::fromUtf8(icalproperty_get_transp(p)); 01260 if( transparency == "TRANSPARENT" ) 01261 event->setTransparency( Event::Transparent ); 01262 else 01263 event->setTransparency( Event::Opaque ); 01264 break; 01265 01266 default: 01267 // kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind 01268 // << endl; 01269 break; 01270 } 01271 01272 p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY); 01273 } 01274 01275 QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT"); 01276 if (!msade.isNull()) { 01277 bool floats = (msade == QString::fromLatin1("TRUE")); 01278 kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl; 01279 event->setFloats(floats); 01280 if (floats) { 01281 QDateTime endDate = event->dtEnd(); 01282 event->setDtEnd(endDate.addDays(-1)); 01283 } 01284 } 01285 01286 mCompat->fixEmptySummary( event ); 01287 01288 return event; 01289 } 01290 01291 FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy) 01292 { 01293 FreeBusy *freebusy = new FreeBusy; 01294 01295 readIncidenceBase(vfreebusy,freebusy); 01296 01297 icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY); 01298 01299 icaltimetype icaltime; 01300 icalperiodtype icalperiod; 01301 QDateTime period_start, period_end; 01302 01303 while (p) { 01304 icalproperty_kind kind = icalproperty_isa(p); 01305 switch (kind) { 01306 01307 case ICAL_DTSTART_PROPERTY: // start date and time 01308 icaltime = icalproperty_get_dtstart(p); 01309 readTzidParameter(p,icaltime); 01310 freebusy->setDtStart(readICalDateTime(icaltime)); 01311 break; 01312 01313 case ICAL_DTEND_PROPERTY: // start End Date and Time 01314 icaltime = icalproperty_get_dtend(p); 01315 readTzidParameter(p,icaltime); 01316 freebusy->setDtEnd(readICalDateTime(icaltime)); 01317 break; 01318 01319 case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times 01320 icalperiod = icalproperty_get_freebusy(p); 01321 readTzidParameter(p,icalperiod.start); 01322 readTzidParameter(p,icalperiod.end); 01323 period_start = readICalDateTime(icalperiod.start); 01324 period_end = readICalDateTime(icalperiod.end); 01325 freebusy->addPeriod(period_start, period_end); 01326 break; 01327 01328 default: 01329 // kdDebug(5800) << "ICalFormatImpl::readIncidence(): Unknown property: " 01330 // << kind << endl; 01331 break; 01332 } 01333 p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY); 01334 } 01335 01336 return freebusy; 01337 } 01338 01339 Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal) 01340 { 01341 Journal *journal = new Journal; 01342 01343 readIncidence(vjournal,journal); 01344 01345 return journal; 01346 } 01347 01348 Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee) 01349 { 01350 icalparameter *p = 0; 01351 01352 QString email = QString::fromUtf8(icalproperty_get_attendee(attendee)); 01353 01354 QString name; 01355 QString uid = QString::null; 01356 p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER); 01357 if (p) { 01358 name = QString::fromUtf8(icalparameter_get_cn(p)); 01359 } else { 01360 } 01361 01362 bool rsvp=false; 01363 p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER); 01364 if (p) { 01365 icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p); 01366 if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true; 01367 } 01368 01369 Attendee::PartStat status = Attendee::NeedsAction; 01370 p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER); 01371 if (p) { 01372 icalparameter_partstat partStatParameter = icalparameter_get_partstat(p); 01373 switch(partStatParameter) { 01374 default: 01375 case ICAL_PARTSTAT_NEEDSACTION: 01376 status = Attendee::NeedsAction; 01377 break; 01378 case ICAL_PARTSTAT_ACCEPTED: 01379 status = Attendee::Accepted; 01380 break; 01381 case ICAL_PARTSTAT_DECLINED: 01382 status = Attendee::Declined; 01383 break; 01384 case ICAL_PARTSTAT_TENTATIVE: 01385 status = Attendee::Tentative; 01386 break; 01387 case ICAL_PARTSTAT_DELEGATED: 01388 status = Attendee::Delegated; 01389 break; 01390 case ICAL_PARTSTAT_COMPLETED: 01391 status = Attendee::Completed; 01392 break; 01393 case ICAL_PARTSTAT_INPROCESS: 01394 status = Attendee::InProcess; 01395 break; 01396 } 01397 } 01398 01399 Attendee::Role role = Attendee::ReqParticipant; 01400 p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER); 01401 if (p) { 01402 icalparameter_role roleParameter = icalparameter_get_role(p); 01403 switch(roleParameter) { 01404 case ICAL_ROLE_CHAIR: 01405 role = Attendee::Chair; 01406 break; 01407 default: 01408 case ICAL_ROLE_REQPARTICIPANT: 01409 role = Attendee::ReqParticipant; 01410 break; 01411 case ICAL_ROLE_OPTPARTICIPANT: 01412 role = Attendee::OptParticipant; 01413 break; 01414 case ICAL_ROLE_NONPARTICIPANT: 01415 role = Attendee::NonParticipant; 01416 break; 01417 } 01418 } 01419 01420 p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER); 01421 uid = icalparameter_get_xvalue(p); 01422 // This should be added, but there seems to be a libical bug here. 01423 /*while (p) { 01424 // if (icalparameter_get_xname(p) == "X-UID") { 01425 uid = icalparameter_get_xvalue(p); 01426 p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER); 01427 } */ 01428 01429 return new Attendee( name, email, rsvp, status, role, uid ); 01430 } 01431 01432 Attachment *ICalFormatImpl::readAttachment(icalproperty *attach) 01433 { 01434 icalattachtype *a = icalproperty_get_attach(attach); 01435 icalparameter_value v = ICAL_VALUE_NONE; 01436 icalparameter_encoding e = ICAL_ENCODING_NONE; 01437 01438 Attachment *attachment = 0; 01439 01440 icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER); 01441 if (vp) 01442 v = icalparameter_get_value(vp); 01443 01444 icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER); 01445 if (ep) 01446 e = icalparameter_get_encoding(ep); 01447 01448 if (v == ICAL_VALUE_BINARY && e == ICAL_ENCODING_BASE64) { 01449 attachment = new Attachment(icalattachtype_get_base64(a)); 01450 } else if ((v == ICAL_VALUE_NONE || v == ICAL_VALUE_URI) && (e == ICAL_ENCODING_NONE || e == ICAL_ENCODING_8BIT)) { 01451 attachment = new Attachment(QString(icalattachtype_get_url(a))); 01452 } else { 01453 kdWarning(5800) << "Unsupported attachment format, discarding it!" << endl; 01454 return 0; 01455 } 01456 01457 icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER); 01458 if (p) 01459 attachment->setMimeType(QString(icalparameter_get_fmttype(p))); 01460 01461 return attachment; 01462 } 01463 01464 void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence) 01465 { 01466 readIncidenceBase(parent,incidence); 01467 01468 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); 01469 01470 const char *text; 01471 int intvalue; 01472 icaltimetype icaltime; 01473 icaldurationtype icalduration; 01474 01475 QStringList categories; 01476 01477 while (p) { 01478 icalproperty_kind kind = icalproperty_isa(p); 01479 switch (kind) { 01480 01481 case ICAL_CREATED_PROPERTY: 01482 icaltime = icalproperty_get_created(p); 01483 readTzidParameter(p,icaltime); 01484 incidence->setCreated(readICalDateTime(icaltime)); 01485 break; 01486 01487 case ICAL_SEQUENCE_PROPERTY: // sequence 01488 intvalue = icalproperty_get_sequence(p); 01489 incidence->setRevision(intvalue); 01490 break; 01491 01492 case ICAL_LASTMODIFIED_PROPERTY: // last modification date 01493 icaltime = icalproperty_get_lastmodified(p); 01494 readTzidParameter(p,icaltime); 01495 incidence->setLastModified(readICalDateTime(icaltime)); 01496 break; 01497 01498 case ICAL_DTSTART_PROPERTY: // start date and time 01499 icaltime = icalproperty_get_dtstart(p); 01500 readTzidParameter(p,icaltime); 01501 if (icaltime.is_date) { 01502 incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0))); 01503 incidence->setFloats(true); 01504 } else { 01505 incidence->setDtStart(readICalDateTime(icaltime)); 01506 } 01507 break; 01508 01509 case ICAL_DURATION_PROPERTY: // start date and time 01510 icalduration = icalproperty_get_duration(p); 01511 incidence->setDuration(readICalDuration(icalduration)); 01512 break; 01513 01514 case ICAL_DESCRIPTION_PROPERTY: // description 01515 text = icalproperty_get_description(p); 01516 incidence->setDescription(QString::fromUtf8(text)); 01517 break; 01518 01519 case ICAL_SUMMARY_PROPERTY: // summary 01520 text = icalproperty_get_summary(p); 01521 incidence->setSummary(QString::fromUtf8(text)); 01522 break; 01523 01524 case ICAL_LOCATION_PROPERTY: // location 01525 text = icalproperty_get_location(p); 01526 incidence->setLocation(QString::fromUtf8(text)); 01527 break; 01528 01529 case ICAL_STATUS_PROPERTY: { // status 01530 Incidence::Status stat; 01531 switch (icalproperty_get_status(p)) { 01532 case ICAL_STATUS_TENTATIVE: stat = Incidence::StatusTentative; break; 01533 case ICAL_STATUS_CONFIRMED: stat = Incidence::StatusConfirmed; break; 01534 case ICAL_STATUS_COMPLETED: stat = Incidence::StatusCompleted; break; 01535 case ICAL_STATUS_NEEDSACTION: stat = Incidence::StatusNeedsAction; break; 01536 case ICAL_STATUS_CANCELLED: stat = Incidence::StatusCanceled; break; 01537 case ICAL_STATUS_INPROCESS: stat = Incidence::StatusInProcess; break; 01538 case ICAL_STATUS_DRAFT: stat = Incidence::StatusDraft; break; 01539 case ICAL_STATUS_FINAL: stat = Incidence::StatusFinal; break; 01540 case ICAL_STATUS_X: 01541 incidence->setCustomStatus(QString::fromUtf8(icalvalue_get_x(icalproperty_get_value(p)))); 01542 stat = Incidence::StatusX; 01543 break; 01544 case ICAL_STATUS_NONE: 01545 default: stat = Incidence::StatusNone; break; 01546 } 01547 if (stat != Incidence::StatusX) 01548 incidence->setStatus(stat); 01549 break; 01550 } 01551 01552 case ICAL_PRIORITY_PROPERTY: // priority 01553 intvalue = icalproperty_get_priority(p); 01554 incidence->setPriority(intvalue); 01555 break; 01556 01557 case ICAL_CATEGORIES_PROPERTY: // categories 01558 text = icalproperty_get_categories(p); 01559 categories.append(QString::fromUtf8(text)); 01560 break; 01561 01562 case ICAL_RRULE_PROPERTY: 01563 readRecurrenceRule(p,incidence); 01564 break; 01565 01566 case ICAL_EXDATE_PROPERTY: 01567 icaltime = icalproperty_get_exdate(p); 01568 readTzidParameter(p,icaltime); 01569 if (icaltime.is_date) { 01570 incidence->addExDate(readICalDate(icaltime)); 01571 } else { 01572 incidence->addExDateTime(readICalDateTime(icaltime)); 01573 } 01574 break; 01575 01576 case ICAL_CLASS_PROPERTY: 01577 text = icalproperty_get_class(p); 01578 if (strcmp(text,"PUBLIC") == 0) { 01579 incidence->setSecrecy(Incidence::SecrecyPublic); 01580 } else if (strcmp(text,"CONFIDENTIAL") == 0) { 01581 incidence->setSecrecy(Incidence::SecrecyConfidential); 01582 } else { 01583 incidence->setSecrecy(Incidence::SecrecyPrivate); 01584 } 01585 break; 01586 01587 case ICAL_ATTACH_PROPERTY: // attachments 01588 incidence->addAttachment(readAttachment(p)); 01589 break; 01590 01591 default: 01592 // kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind 01593 // << endl; 01594 break; 01595 } 01596 01597 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); 01598 } 01599 01600 // kpilot stuff 01601 // TODO: move this application-specific code to kpilot 01602 QString kp = incidence->nonKDECustomProperty("X-PILOTID"); 01603 if (!kp.isNull()) { 01604 incidence->setPilotId(kp.toInt()); 01605 } 01606 kp = incidence->nonKDECustomProperty("X-PILOTSTAT"); 01607 if (!kp.isNull()) { 01608 incidence->setSyncStatus(kp.toInt()); 01609 } 01610 01611 // Now that recurrence and exception stuff is completely set up, 01612 // do any backwards compatibility adjustments. 01613 if (incidence->doesRecur()) 01614 mCompat->fixRecurrence( incidence ); 01615 01616 // add categories 01617 incidence->setCategories(categories); 01618 01619 // iterate through all alarms 01620 for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT); 01621 alarm; 01622 alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) { 01623 readAlarm(alarm,incidence); 01624 } 01625 } 01626 01627 void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) 01628 { 01629 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); 01630 01631 while (p) { 01632 icalproperty_kind kind = icalproperty_isa(p); 01633 switch (kind) { 01634 01635 case ICAL_UID_PROPERTY: // unique id 01636 incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p))); 01637 break; 01638 01639 case ICAL_ORGANIZER_PROPERTY: // organizer 01640 incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p))); 01641 break; 01642 01643 case ICAL_ATTENDEE_PROPERTY: // attendee 01644 incidenceBase->addAttendee(readAttendee(p)); 01645 break; 01646 01647 case ICAL_COMMENT_PROPERTY: 01648 incidenceBase->addComment( 01649 QString::fromUtf8(icalproperty_get_comment(p))); 01650 break; 01651 01652 default: 01653 break; 01654 } 01655 01656 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); 01657 } 01658 01659 // custom properties 01660 readCustomProperties(parent, incidenceBase); 01661 } 01662 01663 void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties) 01664 { 01665 QMap<QCString, QString> customProperties; 01666 01667 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY); 01668 01669 while (p) { 01670 01671 QString value = QString::fromUtf8(icalproperty_get_x(p)); 01672 customProperties[icalproperty_get_name(p)] = value; 01673 01674 p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY); 01675 } 01676 01677 properties->setCustomProperties(customProperties); 01678 } 01679 01680 void ICalFormatImpl::readRecurrenceRule(icalproperty *rrule,Incidence *incidence) 01681 { 01682 // kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl; 01683 01684 Recurrence *recur = incidence->recurrence(); 01685 recur->setCompatVersion(mCalendarVersion); 01686 recur->unsetRecurs(); 01687 01688 struct icalrecurrencetype r = icalproperty_get_rrule(rrule); 01689 01690 dumpIcalRecurrence(r); 01691 01692 readRecurrence( r, recur ); 01693 } 01694 01695 void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur ) 01696 { 01697 int wkst; 01698 int index = 0; 01699 short day = 0; 01700 QBitArray qba(7); 01701 01702 switch (r.freq) { 01703 case ICAL_MINUTELY_RECURRENCE: 01704 if (!icaltime_is_null_time(r.until)) { 01705 recur->setMinutely(r.interval,readICalDateTime(r.until)); 01706 } else { 01707 if (r.count == 0) 01708 recur->setMinutely(r.interval,-1); 01709 else 01710 recur->setMinutely(r.interval,r.count); 01711 } 01712 break; 01713 case ICAL_HOURLY_RECURRENCE: 01714 if (!icaltime_is_null_time(r.until)) { 01715 recur->setHourly(r.interval,readICalDateTime(r.until)); 01716 } else { 01717 if (r.count == 0) 01718 recur->setHourly(r.interval,-1); 01719 else 01720 recur->setHourly(r.interval,r.count); 01721 } 01722 break; 01723 case ICAL_DAILY_RECURRENCE: 01724 if (!icaltime_is_null_time(r.until)) { 01725 recur->setDaily(r.interval,readICalDate(r.until)); 01726 } else { 01727 if (r.count == 0) 01728 recur->setDaily(r.interval,-1); 01729 else 01730 recur->setDaily(r.interval,r.count); 01731 } 01732 break; 01733 case ICAL_WEEKLY_RECURRENCE: 01734 // kdDebug(5800) << "WEEKLY_RECURRENCE" << endl; 01735 wkst = (r.week_start + 5)%7 + 1; 01736 if (!icaltime_is_null_time(r.until)) { 01737 recur->setWeekly(r.interval,qba,readICalDate(r.until),wkst); 01738 } else { 01739 if (r.count == 0) 01740 recur->setWeekly(r.interval,qba,-1,wkst); 01741 else 01742 recur->setWeekly(r.interval,qba,r.count,wkst); 01743 } 01744 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 01745 // kdDebug(5800) << " " << day << endl; 01746 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 01747 } 01748 break; 01749 case ICAL_MONTHLY_RECURRENCE: 01750 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01751 if (!icaltime_is_null_time(r.until)) { 01752 recur->setMonthly(Recurrence::rMonthlyPos,r.interval, 01753 readICalDate(r.until)); 01754 } else { 01755 if (r.count == 0) 01756 recur->setMonthly(Recurrence::rMonthlyPos,r.interval,-1); 01757 else 01758 recur->setMonthly(Recurrence::rMonthlyPos,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 // kdDebug(5800) << "----a " << index << ": " << day << endl; 01764 pos = icalrecurrencetype_day_position(day); 01765 if (pos) { 01766 day = icalrecurrencetype_day_day_of_week(day); 01767 QBitArray ba(7); // don't wipe qba 01768 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 01769 recur->addMonthlyPos(pos,ba); 01770 } else { 01771 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 01772 useSetPos = true; 01773 } 01774 } 01775 if (useSetPos) { 01776 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01777 recur->addMonthlyPos(r.by_set_pos[0],qba); 01778 } 01779 } 01780 } else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01781 if (!icaltime_is_null_time(r.until)) { 01782 recur->setMonthly(Recurrence::rMonthlyDay,r.interval, 01783 readICalDate(r.until)); 01784 } else { 01785 if (r.count == 0) 01786 recur->setMonthly(Recurrence::rMonthlyDay,r.interval,-1); 01787 else 01788 recur->setMonthly(Recurrence::rMonthlyDay,r.interval,r.count); 01789 } 01790 while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 01791 // kdDebug(5800) << "----b " << day << endl; 01792 recur->addMonthlyDay(day); 01793 } 01794 } 01795 break; 01796 case ICAL_YEARLY_RECURRENCE: 01797 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01798 if (!icaltime_is_null_time(r.until)) { 01799 recur->setYearly(Recurrence::rYearlyDay,r.interval, 01800 readICalDate(r.until)); 01801 } else { 01802 if (r.count == 0) 01803 recur->setYearly(Recurrence::rYearlyDay,r.interval,-1); 01804 else 01805 recur->setYearly(Recurrence::rYearlyDay,r.interval,r.count); 01806 } 01807 while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 01808 recur->addYearlyNum(day); 01809 } 01810 } if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01811 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01812 if (!icaltime_is_null_time(r.until)) { 01813 recur->setYearly(Recurrence::rYearlyPos,r.interval, 01814 readICalDate(r.until)); 01815 } else { 01816 if (r.count == 0) 01817 recur->setYearly(Recurrence::rYearlyPos,r.interval,-1); 01818 else 01819 recur->setYearly(Recurrence::rYearlyPos,r.interval,r.count); 01820 } 01821 bool useSetPos = false; 01822 short pos = 0; 01823 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 01824 // kdDebug(5800) << "----a " << index << ": " << day << endl; 01825 pos = icalrecurrencetype_day_position(day); 01826 if (pos) { 01827 day = icalrecurrencetype_day_day_of_week(day); 01828 QBitArray ba(7); // don't wipe qba 01829 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 01830 recur->addYearlyMonthPos(pos,ba); 01831 } else { 01832 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 01833 useSetPos = true; 01834 } 01835 } 01836 if (useSetPos) { 01837 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { 01838 recur->addYearlyMonthPos(r.by_set_pos[0],qba); 01839 } 01840 } 01841 } else { 01842 if (!icaltime_is_null_time(r.until)) { 01843 recur->setYearly(Recurrence::rYearlyMonth,r.interval, 01844 readICalDate(r.until)); 01845 } else { 01846 if (r.count == 0) 01847 recur->setYearly(Recurrence::rYearlyMonth,r.interval,-1); 01848 else 01849 recur->setYearly(Recurrence::rYearlyMonth,r.interval,r.count); 01850 } 01851 while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 01852 recur->addMonthlyDay(day); 01853 } 01854 } 01855 index = 0; 01856 while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 01857 recur->addYearlyNum(day); 01858 } 01859 } 01860 break; 01861 default: 01862 kdDebug(5800) << "Unknown type of recurrence: " << r.freq << endl; 01863 break; 01864 } 01865 } 01866 01867 void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence) 01868 { 01869 //kdDebug(5800) << "Read alarm for " << incidence->summary() << endl; 01870 01871 Alarm* ialarm = incidence->newAlarm(); 01872 ialarm->setRepeatCount(0); 01873 ialarm->setEnabled(true); 01874 01875 // Determine the alarm's action type 01876 icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY); 01877 Alarm::Type type = Alarm::Display; 01878 icalproperty_action action = ICAL_ACTION_DISPLAY; 01879 if ( !p ) { 01880 kdDebug(5800) << "Unknown type of alarm, using default" << endl; 01881 // return; 01882 } else { 01883 01884 action = icalproperty_get_action(p); 01885 switch ( action ) { 01886 case ICAL_ACTION_DISPLAY: type = Alarm::Display; break; 01887 case ICAL_ACTION_AUDIO: type = Alarm::Audio; break; 01888 case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break; 01889 case ICAL_ACTION_EMAIL: type = Alarm::Email; break; 01890 default: 01891 kdDebug(5800) << "Unknown type of alarm: " << action << endl; 01892 // type = Alarm::Invalid; 01893 } 01894 } 01895 ialarm->setType(type); 01896 01897 p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY); 01898 while (p) { 01899 icalproperty_kind kind = icalproperty_isa(p); 01900 01901 switch (kind) { 01902 01903 case ICAL_TRIGGER_PROPERTY: { 01904 icaltriggertype trigger = icalproperty_get_trigger(p); 01905 if (icaltime_is_null_time(trigger.time)) { 01906 if (icaldurationtype_is_null_duration(trigger.duration)) { 01907 kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl; 01908 } else { 01909 Duration duration = icaldurationtype_as_int( trigger.duration ); 01910 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER); 01911 if (param && icalparameter_get_related(param) == ICAL_RELATED_END) 01912 ialarm->setEndOffset(duration); 01913 else 01914 ialarm->setStartOffset(duration); 01915 } 01916 } else { 01917 ialarm->setTime(readICalDateTime(trigger.time)); 01918 } 01919 break; 01920 } 01921 case ICAL_DURATION_PROPERTY: { 01922 icaldurationtype duration = icalproperty_get_duration(p); 01923 ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60); 01924 break; 01925 } 01926 case ICAL_REPEAT_PROPERTY: 01927 ialarm->setRepeatCount(icalproperty_get_repeat(p)); 01928 break; 01929 01930 // Only in DISPLAY and EMAIL and PROCEDURE alarms 01931 case ICAL_DESCRIPTION_PROPERTY: { 01932 QString description = QString::fromUtf8(icalproperty_get_description(p)); 01933 switch ( action ) { 01934 case ICAL_ACTION_DISPLAY: 01935 ialarm->setText( description ); 01936 break; 01937 case ICAL_ACTION_PROCEDURE: 01938 ialarm->setProgramArguments( description ); 01939 break; 01940 case ICAL_ACTION_EMAIL: 01941 ialarm->setMailText( description ); 01942 break; 01943 default: 01944 break; 01945 } 01946 break; 01947 } 01948 // Only in EMAIL alarm 01949 case ICAL_SUMMARY_PROPERTY: 01950 ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p))); 01951 break; 01952 01953 // Only in EMAIL alarm 01954 case ICAL_ATTENDEE_PROPERTY: { 01955 QString email = QString::fromUtf8(icalproperty_get_attendee(p)); 01956 QString name; 01957 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER); 01958 if (param) { 01959 name = QString::fromUtf8(icalparameter_get_cn(param)); 01960 } 01961 ialarm->addMailAddress(Person(name, email)); 01962 break; 01963 } 01964 // Only in AUDIO and EMAIL and PROCEDURE alarms 01965 case ICAL_ATTACH_PROPERTY: { 01966 icalattachtype *attach = icalproperty_get_attach(p); 01967 QString url = QFile::decodeName(icalattachtype_get_url(attach)); 01968 switch ( action ) { 01969 case ICAL_ACTION_AUDIO: 01970 ialarm->setAudioFile( url ); 01971 break; 01972 case ICAL_ACTION_PROCEDURE: 01973 ialarm->setProgramFile( url ); 01974 break; 01975 case ICAL_ACTION_EMAIL: 01976 ialarm->addMailAttachment( url ); 01977 break; 01978 default: 01979 break; 01980 } 01981 break; 01982 } 01983 default: 01984 break; 01985 } 01986 01987 p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY); 01988 } 01989 01990 // custom properties 01991 readCustomProperties(alarm, ialarm); 01992 01993 // TODO: check for consistency of alarm properties 01994 } 01995 01996 icaltimetype ICalFormatImpl::writeICalDate(const QDate &date) 01997 { 01998 icaltimetype t; 01999 02000 t.year = date.year(); 02001 t.month = date.month(); 02002 t.day = date.day(); 02003 02004 t.hour = 0; 02005 t.minute = 0; 02006 t.second = 0; 02007 02008 t.is_date = 1; 02009 02010 t.is_utc = 0; 02011 02012 t.zone = 0; 02013 02014 return t; 02015 } 02016 02017 icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &datetime) 02018 { 02019 icaltimetype t; 02020 02021 t.year = datetime.date().year(); 02022 t.month = datetime.date().month(); 02023 t.day = datetime.date().day(); 02024 02025 t.hour = datetime.time().hour(); 02026 t.minute = datetime.time().minute(); 02027 t.second = datetime.time().second(); 02028 02029 t.is_date = 0; 02030 t.zone = 0; 02031 t.is_utc = 0; 02032 02033 if ( mParent->utc() ) { 02034 if (mParent->timeZoneId().isEmpty()) 02035 t = icaltime_as_utc(t, 0); 02036 else 02037 t = icaltime_as_utc(t,mParent->timeZoneId().utf8()); 02038 } 02039 02040 return t; 02041 } 02042 02043 QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t) 02044 { 02045 /* 02046 kdDebug(5800) << "ICalFormatImpl::readICalDateTime()" << endl; 02047 kdDebug(5800) << "--- Y: " << t.year << " M: " << t.month << " D: " << t.day 02048 << endl; 02049 kdDebug(5800) << "--- H: " << t.hour << " M: " << t.minute << " S: " << t.second 02050 << endl; 02051 kdDebug(5800) << "--- isDate: " << t.is_date << endl; 02052 kdDebug(5800) << "--- isUtc: " << t.is_utc << endl; 02053 kdDebug(5800) << "--- zoneId: " << t.zone << endl; 02054 */ 02055 02056 // First convert the time into UTC if required. 02057 if ( !t.is_utc && t.zone ) { 02058 Timezone *timezone; 02059 02060 // Always lookup with quotes. 02061 if (t.zone[0] != '"') { 02062 timezone = mTimezones.find(QString("\"") + t.zone + '"'); 02063 } else { 02064 timezone = mTimezones.find(t.zone); 02065 } 02066 if (timezone) { 02067 // Apply the offset, and mark the structure as UTC! 02068 t.second -= timezone->offset(t); 02069 t = icaltime_normalize(t); 02070 t.is_utc = 1; 02071 } else { 02072 kdError(5800) << "ICalFormatImpl::readICalDateTime() cannot find timezone " 02073 << t.zone << endl; 02074 } 02075 } 02076 02077 if ( t.is_utc && mCompat->useTimeZoneShift() ) { 02078 // kdDebug(5800) << "--- Converting time to zone '" << cal->timeZoneId() << "'." << endl; 02079 if (mParent->timeZoneId().isEmpty()) 02080 t = icaltime_as_zone(t, 0); 02081 else 02082 t = icaltime_as_zone(t,mParent->timeZoneId().utf8()); 02083 } 02084 QDateTime result(QDate(t.year,t.month,t.day), 02085 QTime(t.hour,t.minute,t.second)); 02086 02087 return result; 02088 } 02089 02090 QDate ICalFormatImpl::readICalDate(icaltimetype t) 02091 { 02092 return QDate(t.year,t.month,t.day); 02093 } 02094 02095 icaldurationtype ICalFormatImpl::writeICalDuration(int seconds) 02096 { 02097 icaldurationtype d; 02098 02099 d.weeks = seconds % gSecondsPerWeek; 02100 seconds -= d.weeks * gSecondsPerWeek; 02101 d.days = seconds % gSecondsPerDay; 02102 seconds -= d.days * gSecondsPerDay; 02103 d.hours = seconds % gSecondsPerHour; 02104 seconds -= d.hours * gSecondsPerHour; 02105 d.minutes = seconds % gSecondsPerMinute; 02106 seconds -= d.minutes * gSecondsPerMinute; 02107 d.seconds = seconds; 02108 d.is_neg = 0; 02109 02110 return d; 02111 } 02112 02113 int ICalFormatImpl::readICalDuration(icaldurationtype d) 02114 { 02115 int result = 0; 02116 02117 result += d.weeks * gSecondsPerWeek; 02118 result += d.days * gSecondsPerDay; 02119 result += d.hours * gSecondsPerHour; 02120 result += d.minutes * gSecondsPerMinute; 02121 result += d.seconds; 02122 02123 if (d.is_neg) result *= -1; 02124 02125 return result; 02126 } 02127 02128 icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal) 02129 { 02130 icalcomponent *calendar; 02131 02132 // Root component 02133 calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); 02134 02135 icalproperty *p; 02136 02137 // Product Identifier 02138 p = icalproperty_new_prodid(CalFormat::productId().utf8()); 02139 icalcomponent_add_property(calendar,p); 02140 02141 // TODO: Add time zone 02142 02143 // iCalendar version (2.0) 02144 p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION)); 02145 icalcomponent_add_property(calendar,p); 02146 02147 // Custom properties 02148 if( cal != 0 ) 02149 writeCustomProperties(calendar, cal); 02150 02151 return calendar; 02152 } 02153 02154 02155 02156 // take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc. 02157 // and break it down from its tree-like format into the dictionary format 02158 // that is used internally in the ICalFormatImpl. 02159 bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar) 02160 { 02161 // this function will populate the caldict dictionary and other event 02162 // lists. It turns vevents into Events and then inserts them. 02163 02164 if (!calendar) return false; 02165 02166 // TODO: check for METHOD 02167 #if 0 02168 if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) { 02169 char *methodType = 0; 02170 methodType = fakeCString(vObjectUStringZValue(curVO)); 02171 if (mEnableDialogs) 02172 KMessageBox::information(mTopWidget, 02173 i18n("This calendar is an iTIP transaction of type \"%1\".") 02174 .arg(methodType), 02175 i18n("%1: iTIP Transaction").arg(CalFormat::application())); 02176 delete methodType; 02177 } 02178 #endif 02179 02180 icalproperty *p; 02181 02182 p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY); 02183 if (!p) { 02184 kdDebug(5800) << "No PRODID property found" << endl; 02185 // TODO: does no PRODID really matter? 02186 // mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); 02187 // return false; 02188 mLoadedProductId = ""; 02189 mCalendarVersion = 0; 02190 } else { 02191 mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p)); 02192 mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId.latin1()); 02193 // kdDebug(5800) << "VCALENDAR prodid: '" << mLoadedProductId << "'" << endl; 02194 02195 delete mCompat; 02196 mCompat = CompatFactory::createCompat( mLoadedProductId ); 02197 } 02198 02199 // TODO: check for unknown PRODID 02200 #if 0 02201 if (!mCalendarVersion 02202 && CalFormat::productId() != mLoadedProductId) { 02203 // warn the user that we might have trouble reading non-known calendar. 02204 if (mEnableDialogs) 02205 KMessageBox::information(mTopWidget, 02206 i18n("This vCalendar file was not created by KOrganizer " 02207 "or any other product we support. Loading anyway..."), 02208 i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application())); 02209 } 02210 #endif 02211 02212 p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY); 02213 if (!p) { 02214 kdDebug(5800) << "No VERSION property found" << endl; 02215 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); 02216 return false; 02217 } else { 02218 const char *version = icalproperty_get_version(p); 02219 // kdDebug(5800) << "VCALENDAR version: '" << version << "'" << endl; 02220 02221 if (strcmp(version,"1.0") == 0) { 02222 kdDebug(5800) << "Expected iCalendar, got vCalendar" << endl; 02223 mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1, 02224 i18n("Expected iCalendar format"))); 02225 return false; 02226 } else if (strcmp(version,"2.0") != 0) { 02227 kdDebug(5800) << "Expected iCalendar, got unknown format" << endl; 02228 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); 02229 return false; 02230 } 02231 } 02232 02233 02234 // TODO: check for calendar format version 02235 #if 0 02236 // warn the user we might have trouble reading this unknown version. 02237 if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) { 02238 char *s = fakeCString(vObjectUStringZValue(curVO)); 02239 if (strcmp(_VCAL_VERSION, s) != 0) 02240 if (mEnableDialogs) 02241 KMessageBox::sorry(mTopWidget, 02242 i18n("This vCalendar file has version %1.\n" 02243 "We only support %2.") 02244 .arg(s).arg(_VCAL_VERSION), 02245 i18n("%1: Unknown vCalendar Version").arg(CalFormat::application())); 02246 deleteStr(s); 02247 } 02248 #endif 02249 02250 // custom properties 02251 readCustomProperties(calendar, cal); 02252 02253 // TODO: set time zone 02254 #if 0 02255 // set the time zone 02256 if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) { 02257 char *s = fakeCString(vObjectUStringZValue(curVO)); 02258 cal->setTimeZone(s); 02259 deleteStr(s); 02260 } 02261 #endif 02262 02263 // Store all events with a relatedTo property in a list for post-processing 02264 mEventsRelate.clear(); 02265 mTodosRelate.clear(); 02266 // TODO: make sure that only actually added ecvens go to this lists. 02267 02268 icalcomponent *c; 02269 02270 // Iterate through all timezones before we do anything else. That way, the 02271 // information needed to interpret times in actually useful objects is 02272 // available below. 02273 c = icalcomponent_get_first_component(calendar,ICAL_VTIMEZONE_COMPONENT); 02274 while (c) { 02275 // kdDebug(5800) << "----Timezone found" << endl; 02276 readTimezone(c); 02277 c = icalcomponent_get_next_component(calendar,ICAL_VTIMEZONE_COMPONENT); 02278 } 02279 02280 // Iterate through all todos 02281 c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT); 02282 while (c) { 02283 // kdDebug(5800) << "----Todo found" << endl; 02284 Todo *todo = readTodo(c); 02285 if (todo && !cal->todo(todo->uid())) cal->addTodo(todo); 02286 c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT); 02287 } 02288 02289 // Iterate through all events 02290 c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT); 02291 while (c) { 02292 // kdDebug(5800) << "----Event found" << endl; 02293 Event *event = readEvent(c); 02294 if (event && !cal->event(event->uid())) cal->addEvent(event); 02295 c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT); 02296 } 02297 02298 // Iterate through all journals 02299 c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT); 02300 while (c) { 02301 // kdDebug(5800) << "----Journal found" << endl; 02302 Journal *journal = readJournal(c); 02303 if (journal && !cal->journal(journal->uid())) cal->addJournal(journal); 02304 c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT); 02305 } 02306 02307 #if 0 02308 initPropIterator(&i, vcal); 02309 02310 // go through all the vobjects in the vcal 02311 while (moreIteration(&i)) { 02312 curVO = nextVObject(&i); 02313 02314 /************************************************************************/ 02315 02316 // now, check to see that the object is an event or todo. 02317 if (strcmp(vObjectName(curVO), VCEventProp) == 0) { 02318 02319 if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) { 02320 char *s; 02321 s = fakeCString(vObjectUStringZValue(curVOProp)); 02322 // check to see if event was deleted by the kpilot conduit 02323 if (atoi(s) == Event::SYNCDEL) { 02324 deleteStr(s); 02325 kdDebug(5800) << "skipping pilot-deleted event" << endl; 02326 goto SKIP; 02327 } 02328 deleteStr(s); 02329 } 02330 02331 // this code checks to see if we are trying to read in an event 02332 // that we already find to be in the calendar. If we find this 02333 // to be the case, we skip the event. 02334 if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) { 02335 char *s = fakeCString(vObjectUStringZValue(curVOProp)); 02336 QString tmpStr(s); 02337 deleteStr(s); 02338 02339 if (cal->event(tmpStr)) { 02340 goto SKIP; 02341 } 02342 if (cal->todo(tmpStr)) { 02343 goto SKIP; 02344 } 02345 } 02346 02347 if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) && 02348 (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) { 02349 kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl; 02350 goto SKIP; 02351 } 02352 02353 anEvent = VEventToEvent(curVO); 02354 // we now use addEvent instead of insertEvent so that the 02355 // signal/slot get connected. 02356 if (anEvent) 02357 cal->addEvent(anEvent); 02358 else { 02359 // some sort of error must have occurred while in translation. 02360 goto SKIP; 02361 } 02362 } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) { 02363 anEvent = VTodoToEvent(curVO); 02364 cal->addTodo(anEvent); 02365 } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) || 02366 (strcmp(vObjectName(curVO), VCProdIdProp) == 0) || 02367 (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) { 02368 // do nothing, we know these properties and we want to skip them. 02369 // we have either already processed them or are ignoring them. 02370 ; 02371 } else { 02372 kdDebug(5800) << "Ignoring unknown vObject \"" << vObjectName(curVO) << "\"" << endl; 02373 } 02374 SKIP: 02375 ; 02376 } // while 02377 #endif 02378 02379 // Post-Process list of events with relations, put Event objects in relation 02380 Event::List::ConstIterator eIt; 02381 for ( eIt = mEventsRelate.begin(); eIt != mEventsRelate.end(); ++eIt ) { 02382 (*eIt)->setRelatedTo( cal->incidence( (*eIt)->relatedToUid() ) ); 02383 } 02384 Todo::List::ConstIterator tIt; 02385 for ( tIt = mTodosRelate.begin(); tIt != mTodosRelate.end(); ++tIt ) { 02386 (*tIt)->setRelatedTo( cal->incidence( (*tIt)->relatedToUid() ) ); 02387 } 02388 02389 return true; 02390 } 02391 02392 QString ICalFormatImpl::extractErrorProperty(icalcomponent *c) 02393 { 02394 // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " 02395 // << icalcomponent_as_ical_string(c) << endl; 02396 02397 QString errorMessage; 02398 02399 icalproperty *error; 02400 error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY); 02401 while(error) { 02402 errorMessage += icalproperty_get_xlicerror(error); 02403 errorMessage += "\n"; 02404 error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY); 02405 } 02406 02407 // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl; 02408 02409 return errorMessage; 02410 } 02411 02412 void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r) 02413 { 02414 int i; 02415 02416 kdDebug(5800) << " Freq: " << r.freq << endl; 02417 kdDebug(5800) << " Until: " << icaltime_as_ctime(r.until) << endl; 02418 kdDebug(5800) << " Count: " << r.count << endl; 02419 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 02420 int index = 0; 02421 QString out = " By Day: "; 02422 while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 02423 out.append(QString::number(i) + " "); 02424 } 02425 kdDebug(5800) << out << endl; 02426 } 02427 if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 02428 int index = 0; 02429 QString out = " By Month Day: "; 02430 while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 02431 out.append(QString::number(i) + " "); 02432 } 02433 kdDebug(5800) << out << endl; 02434 } 02435 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 02436 int index = 0; 02437 QString out = " By Year Day: "; 02438 while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 02439 out.append(QString::number(i) + " "); 02440 } 02441 kdDebug(5800) << out << endl; 02442 } 02443 if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { 02444 int index = 0; 02445 QString out = " By Month: "; 02446 while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 02447 out.append(QString::number(i) + " "); 02448 } 02449 kdDebug(5800) << out << endl; 02450 } 02451 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { 02452 int index = 0; 02453 QString out = " By Set Pos: "; 02454 while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 02455 kdDebug(5800) << "========= " << i << endl; 02456 out.append(QString::number(i) + " "); 02457 } 02458 kdDebug(5800) << out << endl; 02459 } 02460 } 02461 02462 icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence, 02463 Scheduler::Method method) 02464 { 02465 icalcomponent *message = createCalendarComponent(); 02466 02467 icalproperty_method icalmethod = ICAL_METHOD_NONE; 02468 02469 switch (method) { 02470 case Scheduler::Publish: 02471 icalmethod = ICAL_METHOD_PUBLISH; 02472 break; 02473 case Scheduler::Request: 02474 icalmethod = ICAL_METHOD_REQUEST; 02475 break; 02476 case Scheduler::Refresh: 02477 icalmethod = ICAL_METHOD_REFRESH; 02478 break; 02479 case Scheduler::Cancel: 02480 icalmethod = ICAL_METHOD_CANCEL; 02481 break; 02482 case Scheduler::Add: 02483 icalmethod = ICAL_METHOD_ADD; 02484 break; 02485 case Scheduler::Reply: 02486 icalmethod = ICAL_METHOD_REPLY; 02487 break; 02488 case Scheduler::Counter: 02489 icalmethod = ICAL_METHOD_COUNTER; 02490 break; 02491 case Scheduler::Declinecounter: 02492 icalmethod = ICAL_METHOD_DECLINECOUNTER; 02493 break; 02494 default: 02495 kdDebug(5800) << "ICalFormat::createScheduleMessage(): Unknow method" << endl; 02496 return message; 02497 } 02498 02499 icalcomponent_add_property(message,icalproperty_new_method(icalmethod)); 02500 02501 // TODO: check, if dynamic cast is required 02502 if(incidence->type() == "Todo") { 02503 Todo *todo = static_cast<Todo *>(incidence); 02504 icalcomponent_add_component(message,writeTodo(todo)); 02505 } 02506 if(incidence->type() == "Event") { 02507 Event *event = static_cast<Event *>(incidence); 02508 icalcomponent_add_component(message,writeEvent(event)); 02509 } 02510 if(incidence->type() == "FreeBusy") { 02511 FreeBusy *freebusy = static_cast<FreeBusy *>(incidence); 02512 icalcomponent_add_component(message,writeFreeBusy(freebusy, method)); 02513 } 02514 if (incidence->type() == "Journal" ) { 02515 Journal *journal = static_cast<Journal *>(incidence); 02516 icalcomponent_add_component( message, writeJournal( journal ) ); 02517 } 02518 02519 return message; 02520 } 02521 02522 // This function reads any TZID setting for an icaltime. TBD: incorporate 02523 // this into icalproperty_get_datetime() so it is picked up everywhere as 02524 // needed? 02525 void ICalFormatImpl::readTzidParameter( icalcomponent *p, 02526 icaltimetype &icaltime ) 02527 { 02528 icalproperty *tzp = icalproperty_get_first_parameter( p, 02529 ICAL_TZID_PARAMETER ); 02530 if ( tzp ) { 02531 icaltime.zone = icalparameter_get_tzid( tzp ); 02532 } 02533 } 02534
KDE Logo
This file is part of the documentation for libkcal Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:20 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003