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